2016-01-29 229 views
1

我有一个模型,如:保存和更新子关联对象

class Content < ActiveRecord::Base 
    has_many :revisions 
end 

class Revision < ActiveRecord::Base 
    belongs_to :Content 
end 

在我的控制器中我做:

def create 
    @content = Content.new(content_params) 

    if @content.save 
    # ... 
    end 
end 

内容有:

- id 
- category_id 
- title 
- body 
- .. 

版本有:

- id 
- category_id 
- content_id 
- body 

因此,无论何时我保存/更新/删除一个内容,修改都会发生同样的事情。

我应该使用相同的方法创建before_save来处理两种情况吗? 如何轻松地将category_id,content_id和body传递给修订版?

更新

在更新过程中,如果我更新特定REVISION_ID,我必须有REVISION_ID但不知道怎么打发,当我更新的内容实例。那有意义吗?

+0

**从来没有**与'CamelCase'的名称关联,它们是'snake_case':'belongs_to:content' –

+0

而不是依靠应用程序代码来创建修订版,它可能会更好地使用数据库触发器。根据我的经验,触发器更可靠。 –

回答

1

我可能会看看ActiveRecord::Callbacks。下面是如何使用它们的例子:

class Content < ActiveRecord::Base 
    has_many :revisions, dependent: :destroy 

    after_commit :update_revision 

    private 

    def update_revision 
    # Create or update a revision object 
    end 
end 

一般情况下,我不喜欢使用创建另一个回调模型的想法。这感觉像是违反了单一责任原则。您可以使用服务对象来处理您提到的创建和更新操作。

请注意上面代码块中关于has_many关系的dependent: destroy语法。这将会将Content记录删除到其相关的Revision s。

更新

如果你只是想更新您的控制器内特定的修订版本,你可以写:

def create 
    @content = Content.new(content_params) 

    if @content.save 
    Revision.find(revision_id).update_attributes!(...) 
    end 
end 
0

直接回答你的问题是使用before_update回调,也许inverse_of(所以相关对象在内存中可用):

#app/models/content.rb 
class Content < ActiveRecord::Base 
    has_many :revisions 
    accepts_nested_attributes_for :revisions 

    before_update :set_revision 
    before_create :set_revision 

    private 

    def set_revision 
    self.revisions.build body: self.body 
    end 
end 

#app/models/revision.rb 
class Revision < ActiveRecord::Base 
    belongs_to :content 
end 

以上将创建一个新的revision每次你update你的content模型。双方将保存为你使用accepts_nested_attributes_for


作为一个建议,你可以希望看的Paper Trail宝石。

这确实是确切您正在寻找什么(根据修订) - 它保存您在模型上执行的任何更新/编辑。

#Gemfile 
gem 'paper_trail' 

$ rails generate paper_trail:install 
$ rake db:migrate 

#app/models/content.rb 
class Content < ActiveRecord::Base 
    has_paper_trail 
end 

这会自动记录修改谁执行它的模型

有一个good RailsCast about it here

相关问题