1

我正在使用 Ruby on Rails 3.2.2,我想在实例存储到数据库之前根据之前的状态运行一些检查。@article也就是说,我必须运行一些方法来利用已经存储在数据库中的相关数据@article(在下面的情况下,数据是{:id => 1, :title => "Sample title", :content => "Sample content", :status => "private"}不是 {:id => 1, :title => "Sample title changed!", :content => "Sample content", :status => "private"})。

我想在其属性值更改后继续“检索”/“重新构建”原始实例。那是:

# 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

因此,original应该是一个Article对象,并且只是@article实例的副本(没有id和没有该@article属性已更改)。

我尝试使用一些 Ruby on Rails 方法(如ActiveRecord::Base.dupor ActiveModel::Dirty.changed_attributes),但我还没有找到解决方案。此外,与我的方法相比,我认为有更好的方法来完成我想做的事情。 如果是这样,我可能会做什么?


我想这样做是因为,例如,如果一篇文章是公开的,那么应该不可能更改标题值;如果文章是私有的,则应该可以更改标题值。当然,我必须在存储编辑过的文章数据之前进行检查,并且对于所有尝试更新该数据的尝试(为此我选择使用before_save回调)。但是,如果用户尝试将标题值和私有值更改为公共,那么所有检查都在公共“上下文”中运行,但我希望这些检查仍然在私有“上下文”中运行,因为之前的状态是私有的.

4

3 回答 3

3

看起来您可以通过钩子中的更改哈希。即dupclone更改的版本,然后通过更改的版本changes并将属性设置回它们为您的副本所使用的属性。

于 2012-05-07T00:58:59.503 回答
0

只是保存

@article = Article.find(params[:id])`
@orginal = @article
if @article.update_attributes(params[:article])
  @original.do_some_method_that_probably_should_be_a_before_update
  #.... whatever is next .....
end

或者重新思考为什么你需要做你认为你需要做的事情。

于 2012-05-07T01:01:00.017 回答
0

有几种方法可以做到这一点。基本上,与其尝试在之后恢复更改并随后进行检查,不如在进行更改之前制作对象的副本会更容易。

一种方法是从当前对象的“属性”创建一个新对象,如下所示:

tmp_article = @article.attributes

在对模型对象进行任何更改之前执行此操作。然后在保存之前,您可以使用.diffrails 内置的 hash 方法:

diff_hash = tmp_article - @article.attributes
# diff will now contain any differences. It will be empty if they are identical.

这是 Rails 中 diff 扩展的链接:

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/hash/diff.rb

于 2012-05-07T01:05:13.627 回答