在多对多关系中加入表属性更新

问题描述:

我有一个处理成员和地址问题域的数据模型的多对多关系设置。基本上,一个'会员'可以有多个'地址',就像你有工作地址和家庭住址一样。在多对多关系中加入表属性更新

我想在连接表上存储其他属性并保存除外键属性以外的数据。网络上有很多关于多对多关系的例子,但是我没有找到关于存储额外数据的细节/例子。

这是我坚持的问题。

的模型设置为:

模式

class Member < ActiveRecord::Base 
    has_many :member_addresses 
    has_many :addresses, :through => :member_addresses 
end 

class MemberAddress < ActiveRecord::Base 
    belongs_to :address # foreign key for address -> address_id 
    belongs_to :member # foreign key for member ->member_id 
end 

class Address < ActiveRecord::Base 
    has_many :member_addresses 
    has_many :members, :through => :member_addresses 

    accepts_nested_attributes_for :members, :allow_destroy => true 
end 

的 'accepts_nested_attributes' 的地址类是嵌套形式。

数据库架构/迁移 的表(简化为张贴)​​是在连接表定义为

create_table "addresses", :force => true do |t| 
    t.string "firstline" 
    t.string "state" 
    .... 
end 

create_table "member", :force => true do |t| 
    t.string "name" 
    .... 
end 

create_table "member_addresses", :force => true do |t| 
    t.integer "member_id" 
    t.integer "address_id" 
    t.string "address_type" 
end 

字段“address_type”被用于标记,其与相关联的地址的类型该成员(又名;“家”或“工作”)

它正在更新此字段,我卡住了。

控制器&查看

的member_controller设置的模式,如:

members_controller.rb 
def new 
    @member = Member.new 
    @member.addresses.build #pre-build the associated address 
end 

然后为会员页面视图行动

<%=的form_for @成员do | m | %>

<%= m.label :first_name, "First Name"%> 
    <%= m.text_field :first_name %> 
    </p> 

    <%= m.fields_for :addresses do |addrform|%> 
    <%= addrform.label :firstline %> 
    <%= addrform.text_field :firstline %> 
    <% end %> 

    <br /> 
    <%= label_tag 'Type of address' %> 
    <%= text_field_tag 'addrtype' %> 
    <br /> 
    <%= m.submit "Add" %><br /> 

<%结束%>

的想法是,与上会员模式“accepts_nested_attributes”我可以进入表单上的数据在名称和地址属性添加。附加label_tag是被张贴了,我想存储

所以当形式在后的数据被填充(形成陷阱)地址类型数据的模样:

{"utf8"=>"✓", 
    "authenticity_token"=>"E0R038rcdJmBGjjxQ9nQLHGVbzM4ejA0vsEaIvqkwkE=", 
    "member"=>{"first_name"=>"James", 
    "last_name"=>"SMith", 
    "addresses_attributes"=>{"0"=>{"firstline"=>"this is the first line"}}}, 
    "addrtype"=>"home", 
    "commit"=>"Add"} 

所有优秀的 - 我得到我会员数据和地址数据,以及附加字段“ADDRTYPE”,这是用于承载我的附加数据

现在如何获取数据到relati在或加入表格?在member_controller创建行动

def create 
    # create a member with the params posted 
    @member = Member.new(params[:member]) 

    # get data for 'relation data' 
    @addr_type = params[:addrtype] 



    if @member.save! 
     #update the relation now created with the address type 
     @member.member_addresses.first.address_type = @addr_type 

     # save the relationship (is this necessary?) 
     @member.save! 

     redirect_to members_path 
    end 

正如你可以在看到创建我试图填补数据上的连接表,然后强制再次保存,这样的关系或协会与附加属性被保存。

这不起作用,和/或我做错了。

任何建议将不胜感激。

尝试改变你的模型,如下所示:

class Member < ActiveRecord::Base 
    has_many :member_addresses 
    accepts_nested_attributes_for :member_addresses, :allow_destroy => true 
end 

class MemberAddress < ActiveRecord::Base 
    belongs_to :member  
    has_many :addresses 
    accepts_nested_attributes_for :addresses, allow_destroy => true 
end 

class Address < ActiveRecord::Base 
    belongs_to :member_addresses 
end 

,改变你的member_controller.create方法

@member = Member.new(params[:member]) 

这应该允许您通过MemberController.create方法创建MemberAddresses和地址。

这2个RailsCasts也可能是值得一看

#196 Nested Model Form Part 1
#197 Nested Model Form Part 2

还不如精通Rails的,我想是,但研究表明,可能这可能工作:

而不是

@member.member_addresses.first.address_type = @addr_type

尝试

@member.member_addresses.create(:address_type => @addr_type)

+0

正确的 - 它的工作原理提供了@member保存第一否则你得到的ActiveRecord :: RecordNotSaved:您不能调用创建,除非parent保存 –

+0

唯一的问题是,如果有一个@ member.save!,必须保存父项,那么在MemberAddresses连接表中创建的两个记录中会创建额外的“创建”结果;一个用于第一次保存,它具有两个外键,一个用于具有address_type字段和成员对象的ID的“创建”。它缺少address_id字段 –