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
?
If an attribute's value can be derived from the values of other attributes, then the attribute is derivable, and is said to be a derived attribute. For example, if we have an attribute for birth date then age is derivable. Derived attributes are shown with a dotted lined oval.
Derived attribute − Derived attributes are the attributes that do not exist in the physical database, but their values are derived from other attributes present in the database. For example, average_salary in a department should not be saved directly in the database, instead it can be derived.
The Rails Attributes API is used under-the-hood to type cast attributes for ActiveRecord models. When you query for a model that has a datetime column in the database and the Ruby object that gets pulled out has a DateTime field – that's the Attributes API at work.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With