在多对多关系中连接表属性更新

时间:2011-08-24 00:42:29

标签: ruby-on-rails activerecord associations

我有一个数据模型的多对多关系设置,它处理成员和地址的问题域。基本上,“会员”可以有多个“地址”,就像有工作地址和家庭住址一样。

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

这是我遇到的问题。

模型设置为:

模型

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

Address类中的'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'用于标记与成员关联的地址类型(aka;“home”或“work”)

正在更新此字段,这是我遇到的问题。

控制器&amp;图

member_controller设置模型如:

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

然后,会员页面操作的视图为

&lt;%= form_for @member do | m | %GT;

  <%= 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 />

&lt;%end%&gt;

我的想法是,使用成员模型上的'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',用于携带我的附加内容数据

现在如何将数据导入关系或连接表?在 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

正如您在创建中所看到的,我正在尝试填充连接表上的数据,然后再次强制保存,以便保存与其他属性的关系或关联。

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

任何建议都会受到最高的赞赏。

2 个答案:

答案 0 :(得分:1)

尝试将模型更改为以下内容:

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和Addresses。

这两个RailsCasts也值得一看

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

答案 1 :(得分:0)

Rails不像我想的那样流利,但研究表明这可能会有效:

而不是

@member.member_addresses.first.address_type = @addr_type

尝试

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