Rails creating and updating 2 model records simultaneously
I have 2 tables product and history
product table:
id name type price location 1 开发者_Go百科 abc electronics $200 aisle1
history table:
id product_id status 1 1 price changed from $200 to $180
Whenever the product price or location is updated by a user by hitting the update button, the changes should be automatically be reflected in the history status column without the user having to enter that manually.
If the price is updated from 200 to 180 then a new history row will be created with new id and the status column will say 'price changed from $200 to $180'.
If the location is updated from aisle1 to aisle 2 then status displays 'loc changed from aisle1 to aisle 2'.
I tried:
@product = Product.new(params[:product])
@history = History.new(params[:history])
if @product.save
@history.new(attributes) # I am not sure of whether this approach is correct
I would really appreciate if someone could tell me how the history can be automatically updated in this case.
Add a after_save
filter to the Product model.
class Product < ActiveRecord::Base
after_save :make_history
has_many :histories
def make_history
status = ""
status << "Price changed from #{price_was} to #{price}" if price_changed?
status << "Location changed from #{location_was} to #{location}" if location_changed?
return if status.empty?
errors = histories.create(:status = status).errors.full_messages.join(",\n")
# return true if no error
return true if errors.empty?
# Roll the error to base
errors.add_to_base("History creation error:\n#{errors}")
# explicitly rollback
raise ActiveRecord::Rollback
# return false to terminate the callback chain
return false
end
end
Edit
I have added code to rollback the Product
when History
creation fails.
What you want is to use an Observer.
You can set one up like so:
class ProductObserver < ActiveRecord::Observer
def after_save(product)
#get attributes here
history.new(attributes)
history.save
end
end
Note that you have to manually specify which observers are loaded in your environment configuration; you can't simply add the file and get it to work.
One way to go is to use a after_save callback on the model. Add this to your Product ActiveRecord model:
after_save :update_history
def update_history
do_whatever
end
check it out here.
精彩评论