I am using Ruby on Rails 3.2.2 and I would like to run some check based on the previous status of an @article instance before that it is stored in the database. That is, I have to run some method that make use of data already stored in the database related to @article (in the below case that data is {:id => 1, :title => "Sample title", :content => "Sample content", :status => "private"} and not {:id => 1, :title => "Sample title changed!", :content => "Sample content", :status => "private"}).
I thought to proceed “retrieving”/”re-building” the original instance after that its attribute values have changed. That is:
# In the controller file
# @article.attributes
# => {:id => 1, :title => "Sample title", :content => "Sample content", :status => "private"}
@article.update_attributes(params[:article])
# => {:id => 1, :title => "Sample title changed!", :content => "Sample content", :status => "private"}
# In the model file
before_save :retrieve_original
def retrieve_original
# self.attributes
# => {:id => 1, :title => "Sample title changed!", :content => "Sample content", :status => "private"}
original = ... # ?
# original.id
# => nil
# original.attributes
# => {:title => "Sample title", :content => "Sample content", :status => "private"}
# self.attributes
# => {:id => 1, :title => "Sample title changed!", :content => "Sample content", :status => "private"}
end
So, original should be an Article object and just a duplicate of the @article instance (without the id and without that @article attributes have changed).
I tried to play with some Ruby on Rails method (like ActiveRecord::Base.dup or ActiveModel::Dirty.changed_attributes), but I have not found a solution. Furthermore, I think that there’s a better way to accomplish what I would like to make compared to my approach. If so, what I might do?
I would like to do that because, for example, if an article is public it should be not possible to change the title value; if the article is private, it should be possible to change the title value. Of course, I have to make that check before to store the edited article data and for all attempts that try to update that data (for this I chose to use a before_save callback). However, if the user try to change the title value and the private value to public, then all checks run in a public “context”, but I would like that those checks still run in a private “context” since the previous status was private.
It looks like you can go through the changes hash in your hook. I.e.
duporclonethe changed version, then go through changed version’schangesand set the attributes back to what they were for your copy.