Nick
Nick

Reputation: 9866

Rails - Where should I calculate derived attributes?

Noob question for Ruby on Rails- here's an example of my situation: If I have model circle and attribute radius, where do I do the calculations for circumference? Would this be in the model or the controller, and how might it look? circumference would need to be accessible in my views.

Also, would I be correct in thinking that I don't need to make circumference an attribute that's part of my model/database since it can be derived from a user-input radius?

Upvotes: 13

Views: 5478

Answers (1)

Emily
Emily

Reputation: 18193

The logic for calculating a derived attribute absolutely belongs in the model. The circumference is a property of the circle itself, not a concern of how you're presenting it in the web interface.

In order to access the circumference from anywhere, just define a method on the class, such as the following:

require 'mathn'
class Circle < ActiveRecord::Base
  # assume `radius` column exists in the database

  def circumference
    Math::PI * 2 * radius
  end
end

Since it's pretty cheap computationally to calculate the circumference, you can just calculate it as needed. If it were something that involved more complex calculation that you didn't want to run multiple times, you could memoize it as follows:

def circumference
  @circumference ||= Math::PI * 2 * radius
end

That would set the @circumference instance variable the first time the method is called, then return the result of the first calculation on every subsequent call. If you were doing that, you'd need to make sure to set @circumference to nil when the radius changed to make sure it's accurate.

def radius=(value)
  @circumference = nil
  super(value)
end

Upvotes: 17

Related Questions