Where to translate from Fahrenheit to Celsius in Rails app?
-
02-07-2021 - |
문제
I'm relatively new to Rails, and I'm building an application that deals with weather data. My main uses will be inside the US so the presentation to the user will presumably be in Fahrenheit. The data feeds I consume are in Celsius.
The normal way I would solve this would be to have a celsius
column in the model and then a custom fahrenheit
model method that converts from F to C. However, because of various design decisions I don't have a specific field for temperature. (tl;dr I'm tracking a lot of different environmental conditions beyond just weather so I have a generic value
column and a type
column.)
I see a few alternatives:
- Store F internally. Only convert to C when I consume the weather data feed. Assume I don't ever have users in a locality with a sane system of measurement.
- Store C internally. Convert to F in the view (if the user's preference is to see F). This would be tricky since the formula to convert
value
would need to be implemented in both the Rails view and in JS, as far as I can see. - Store C internally. Convert to F depending on the context, i.e. when creating a record where the
type
is temperature and the user has a preference for Fahrenheit, run abefore_save
callback that does the conversion. I have no idea what to do for a read...
What's the right way to structure this? Thanks!
해결책 4
I meditated on the very general response @Alnitak gave for a bit and figured out what I need to do. I have a temperature
type. So I leave that type alone and let that be Celsius. Then I add a new type temperature_fahrenheit
. Then I have a :before_save call-back in my model which does the F to C conversion. That way I leave the internal data always as Celsius but can still easily have the form submit in Fahrenheit.
Seems obvious now but it was escaping me for a while.
다른 팁
Store one form internally, and it should be the internationally standardised Celcius scale.
Anything else is a presentation problem.
I would say store it in one presentation (C or F) in the database and convert it client-side in JS. This would also make it trivial to code the functionality so a user can decide him/herself to flip between C and F without a roundtrip to the server.
Here is what I did:
- Made a decision to store temperatures in celsius
- created a virtual attribute on my weather report model called :air_temp_imperial
- used a setter called air_temp_imperial which did the conversion from imperial to celsius and then saved the value to :air_temp
- used a getter air_temp_imperial to return a converted celsius to imperial value
Then in my views I checked the current_user preferences imperial? value to modify my presentation and forms.
I'm not sure if it's the right way, but it seems to work.
This is an old question....but, ...
My users enter temp as a float. I have an enum for "temperature_scale" (celsius or Fahrenheit). For conversions I created an initializer 'extend_float.rb' with the following:
class Float
def to_celcius
((self - 32) * 5/9).round(1)
end
def to_fahrenheit
((self * 9/5) + 32).round(1)
end
end
Then you can do:
thing = Thing.find(1)
return thing.celsius? ? thing.temperature.to_fahrenheit : thing.temperature