How to calculate and save a derived ActiveRecord value
I have a data object which is composed_of three child instances of the same object. I need to calculate a value from that object and save it in the database. (It is later pulled form the db by another application.)
I've mocked out my class structure below, basically I want a method that will add together the Child values data_one and data_two, and store it into a third variable, total. Which I guess will be total_first, total_second and total_third in the db Parent table. Should I declare total as a Child attribute and use a callback to set it? Any help will be much appreciated - thank you! And apologies if this is a really obvious question...
class Child
attr_reader :data_one, :data_two
def initialize(data_one, data_two)
@data_one, @data_two,
end
def ==(other_child)
data_one == other_child.data_one &&
data_two == other_child.data_two
end
def Sdq.from_params(hash)
Sdq.new(
get_value(hash, :data_one),
get_value(hash, :data_two),
)
end
protected
def Sdq.get_value(hash, key)
hash.has_key?(key) ? hash[key] : hash[key.to_s]
end
end
class Parent < ActiveRecord::Base
composed_of :first_child, :class_name => "Child", :mapping => [
["data_one_first","data_one"],
["data_two_first","data_two"]
]
composed_of :second_child, :class_name => "Child", :mapping => [
["data_one_second","data_one"],
["data_two_second","data_two"]
]
composed_of :third_child, :class_name => "Child", :ma开发者_开发问答pping => [
["data_one_third","data_one"],
["data_two_third","data_two"]
]
end
I can't imagine why a parent will always have exactly two children, why not a many_to_x relation? depending if you need many to many. Hopefully not seeing the example.
You must have your reasons.
I would use call backs like you described. Maybe before_validations
and have some validation on it. Note, that returning a non-true value in a callback can result in the record not saving.
E.G If the condition is false, the method returns nil and can halt the save callback chain.
def before_save
if something_sometimes_is_false
#do normal code
end # could not run, which would return nil and break things
end
consider returning self at the end.
def before_save
if something_sometimes_is_false
# do normal code
end
self # should always be a true value in an instance of a class. will not break call backs
end
精彩评论