문제

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:

  1. 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.
  2. 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.
  3. 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 a before_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:

  1. Made a decision to store temperatures in celsius
  2. created a virtual attribute on my weather report model called :air_temp_imperial
  3. used a setter called air_temp_imperial which did the conversion from imperial to celsius and then saved the value to :air_temp
  4. 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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top