`
genius_45
  • 浏览: 58105 次
  • 性别: Icon_minigender_1
  • 来自: 威海
社区版块
存档分类
最新评论

【译】rails的嵌套属性(Nested Attributes)使用

阅读更多

 

Active Record Nested Attributes


通过嵌套属性(nested attribute),你可以通过parent来保存与其相关联的属性。默认情况下,嵌套属性是关闭的,你可以开启accepts_nested_attributes_for这个类方法,就在该model上生成一个属性writer。
属性writer是以该关联命名。例如,为你的model增加两个新方法:

author_attributes=(attributes) 和 pages_attributes=(attributes).

 class Book < ActiveRecord::Base
	has_one :author
 	has_many :pages

  	accepts_nested_attributes_for :author, :pages
end
  使用了accepts_nested_attributes_for的每一个关联都自动开启:autosave

一对一关联

一个Member有一个Avatar
class Member < ActiveRecord::Base
  has_one :avatar
  accepts_nested_attributes_for :avatar
end
  开启一对一关联的嵌套属性可以通过这样方法一次性创建Member

 

params = { :member => { :name => 'Jack', :avatar_attributes => { :icon => 'smiling' } } }
member = Member.create(params[:member])
member.avatar.id # => 2
member.avatar.icon # => 'smiling'

也可以这样update avatar

params = { :member => { :avatar_attributes => { :id => '2', :icon => 'sad' } } }
member.update_attributes params[:member]
member.avatar.icon # => 'sad'
  默认情况下你只能设置或更新关联的model。如果你想通过属性hash来删除关联model,你需要使用:allow_destroy 选项
class Member < ActiveRecord::Base
  has_one :avatar
  accepts_nested_attributes_for :avatar, :allow_destroy => true
end
  此时,如果向属性hash里增加一个_destroykey,并且valuetrue,则该关联model将被删除。
member.avatar_attributes = { :id => '2', :_destroy => '1' }
member.avatar.marked_for_destruction? # => true
member.save
member.reload.avatar # => nil
  注意这里,只有当parent被保存后,关联的model才真正被删除。

一对多关联

一个member有一些post
class Member < ActiveRecord::Base
  has_many :posts
  accepts_nested_attributes_for :posts
end
  你可通过属性hash来增加或更新关联post model 每一个不含有id键的新记录会被实例化,除非该hash也包含了一个 :_destroy => true
params = { 
  :member => {

    :name => 'joe', :posts_attributes => [

      { :title => 'Kari, the awesome Ruby documentation browser!' },
      { :title => 'The egalitarian assumption of the modern citizen' },
      { :title => '', :_destroy => '1' } # 该记录会被忽略
    ]
  }
}
member = Member.create(params['member'])
member.posts.length # => 2
member.posts.first.title # => 'Kari, the awesome Ruby documentation browser!'
member.posts.second.title # => 'The egalitarian assumption of the modern citizen'
  通过 :reject_if proc 设置忽略的不满足条件的记录。例如:
class Member < ActiveRecord::Base
   has_many :posts
   accepts_nested_attributes_for :posts, :reject_if => proc { |attributes| attributes['title'].blank? }
 end

params = { :member => {
  :name => 'joe', :posts_attributes => [
    { :title => 'Kari, the awesome Ruby documentation browser!' },
    { :title => 'The egalitarian assumption of the modern citizen' },
    { :title => '' } #  这个记录会被忽略
  ]
}}

member = Member.create(params['member'])
member.posts.length # => 2
member.posts.first.title # => 'Kari, the awesome Ruby documentation browser!'
member.posts.second.title # => 'The egalitarian assumption of the modern citizen'
  :reject_if 也可一接受一个symbol来代表一个可用方法: 如果hash中含有一个id和已有的关联记录相匹配,则被匹配到的记录会被修改:
member.attributes = {
  :name => 'Joe',
  :posts_attributes => [
    { :id => 1, :title => '[UPDATED] An, as of yet, undisclosed awesome Ruby documentation browser!' },
    { :id => 2, :title => '[UPDATED] other post' }
  ]
}
member.posts.first.title # => '[UPDATED] An, as of yet, undisclosed awesome Ruby documentation browser!'
member.posts.second.title # => '[UPDATED] other post'
  默认关联记录是被保护的(不被删除)。如果想通过属性hash来删除任何关联记录,你需要打开:allow_destroy选项, 这样使用_destroy键来删除记录就行:
class Member < ActiveRecord::Base
  has_many :posts
  accepts_nested_attributes_for :posts, :allow_destroy => true
end

params = { :member => {
  :posts_attributes => [{ :id => '2', :_destroy => '1' }]
}}
member.attributes = params['member']
member.posts.detect { |p| p.id == 2 }.marked_for_destruction? # => true  标记将被删除
member.posts.length # => 2  未保存,所以还没删除
member.save
member.reload.posts.length # => 1 
 

保存

所有对model修改的行为,包括标记将要销毁,会随着parent被保存原子性的被自动保存或者删除。这些开始与parentsave方法,发生在其内部的事务里。详见 Active Record Autosave Association


使用attr_accessible

使用attr_accessible如果不小心,可能会干扰到嵌套属性的使用。例如,上述member model如下使用attr_accessible
attr_accessible :name
  你需要这样的修改:
attr_accessible :name, :posts_attributes
 
验证parent model 的存在

如果你想验证一个child记录是否和一个parent记录关联,你可以使用validates_presence_ofinverse_of

class Member < ActiveRecord::Base
  has_many :posts, :inverse_of => :member
  accepts_nested_attributes_for :posts
end

class Post < ActiveRecord::Base
  belongs_to :member, :inverse_of => :posts
  validates_presence_of :member
end
 
具体应用见 http://cn.asciicasts.com/episodes/196-nested-model-form-part-1

 

 

分享到:
评论

相关推荐

    rails-example-how-to-translate-nested-attributes:一个示例 Rails 应用程序,用于学习如何翻译嵌套属性

    我想在父模型的错误中使用本地化来重命名嵌套的多态属性。 例子 用户模型 地址模型,多态 雇主模式 用户有一个邮寄地址,多态地址 用户有一个雇主 用户验证username 、 email 、 mailing_address和employer的...

    Rails 3.2:嵌套形式的演示,第3部分:我们正在开始进攻!

    3. **接受嵌套属性(Accepts Nested Attributes For)**: 在模型中,通过声明`accepts_nested_attributes_for :comments`,我们可以告诉Rails允许通过`Post`的参数来创建或更新`Comment`s。这使得在控制器中可以...

    nested_attr:用于测试使用Factory Girl和Formastic Forms的Rails应用程序的帮助程序插件(例如Active Admin)

    当我们执行FactoryGirl.attributes_for(:factory_name)时,FactoryGirl不提供嵌套属性,但是当我们以活动管理员形式测试控制器时,通常我们需要这些嵌套属性,这通常是通过对请求后的请求进行硬编码来实现的累。...

    ember_nested_rails:尝试使Ember与嵌套资源路由一起使用

    Ember 嵌套 Rails ##Configure Rails 生成 ember-esque json # config/initializers/active_model_serializer.rb ActiveModel :: Serializer . setup do | config | config . embed = :ids config . embed_in_...

    Ruby-SimpleForm轻松处理Rails表单

    使用`accepts_nested_attributes_for`在模型中声明,然后在表单中使用`fields_for`方法: ```ruby |address_form| %&gt; ``` 8. **标签和提示** Simple Form允许自定义输入字段的标签和提示信息。默认情况下...

    stimulus-rails-nested-form:一个Stimulus控制器,可即时创建新字段以填充您的Rails关系

    一个Stimulus控制器,用于动态创建新字段,以使用accepts_nested_attributes_for填充您的Rails关系。 :books: 文献资料 请参阅。 :male_sign: 贡献 不要犹豫,通过修改或添加功能为项目做出贡献! 错误报告或请求...

    Rails 3.2:嵌套形式的演示第4部分:切换到目标计算机!

    在Rails 3.2中,我们通常会使用`accepts_nested_attributes_for`方法来定义模型间的嵌套关系。例如,在Ship模型中,我们需要这样写: ```ruby class Ship has_many :pilots accepts_nested_attributes_for :...

    196-nested-model-form-revised

    这通常涉及到使用`accepts_nested_attributes_for`方法在父模型中定义,以及在视图中使用`fields_for`辅助方法来创建关联模型的表单字段。 1. `accepts_nested_attributes_for`:这个方法是在父模型中声明的,它...

    JSON API Document

    6. **嵌套资源(Nested Resources)**:在请求或响应中,可以通过包含关联资源的完整表示来嵌套资源,这有助于减少网络请求的数量。 7. **包含(Inclusion)**:通过指定`include`参数,客户端可以要求服务器在响应...

    flight-booker:奥丁项目的航班预订项目

    Rails提供了`accepts_nested_attributes_for`方法,使得可以方便地在父模型中接收和处理子模型的属性,简化了数据操作的复杂性。 ### 四、数据模型 数据模型是Rails应用的核心部分,它们定义了数据库中的表结构和...

    jsonapi:杰森·阿皮

    6. **嵌套数据(Nested Data)**:在请求或响应中,可以包含嵌套的资源对象,以便一次传输多个相关资源。 7. **分页(Pagination)**:JSONAPI 提供了一种标准的方式来分页,通过 `links` 部分的 `first`, `last`, ...

    odin-flight-booker

    这可能涉及到`form_for`辅助方法,以及使用`accepts_nested_attributes_for`处理嵌套模型的表单。 8. **路由(Routes)**:Rails的路由系统定义了URL与控制器动作之间的映射,确保用户请求能正确导向相应的行为。 ...

Global site tag (gtag.js) - Google Analytics