开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜