保存记录连接表Has_many:通过

时间:2011-10-17 07:51:28

标签: ruby-on-rails-3 model associations

我是Rails 3的新手,无法在Join表中保存记录。我一直在环顾四周,尝试在本网站和文档或书籍中找到不同的例子,但我不明白为什么我不能让它工作。我试图通过创建角色并将它们与用户关联来创建授权。到目前为止,我一直在尝试从用户控制器中的更新操作分配角色而不占优势。

我有3个模型:User.rb,role.rb和assignment.rb(连接表)

class User < ActiveRecord::Base
  has_many :assignments, :dependent => :destroy
  has_many :roles, :through => :assignments, :foreign_key => :role_id
  accepts_nested_attributes_for :roles
  attr_accessor :password, :role_ids
  attr_accessible :first_name, :last_name, :email, :password, :password_confirmation, :status, :description, :username, :roles_attributes
  ...
end

class Role < ActiveRecord::Base
  has_many :assignments
  has_many :users, :through => :assignments, :foreign_key => :user_id
  accepts_nested_attributes_for :users
  attr_accessible :name
end

class Assignment < ActiveRecord::Base
  belongs_to :user
  belongs_to :role
  accepts_nested_attributes_for :roles
end  

更新操作中的用户控制器我有以下

class UsersController < ApplicationController
  ...
  def update
    @user = User.find(params[:id])
    if @user.update_attributes(params[:user])
      @user.roles.build
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      @title = "Edit" + " " + @user.username
      render 'edit'
    end
  end
  ...
end

并且在“编辑”视图页面中,我打算使用复选框来更新具有关联角色的用户记录:

编辑:将“check_box”更改为“check_box_tag”...复选框显示正确,但未保存值。

<%= form_for(@user) do |f| %>
  ...
  <div class="field">
     <%= f.label :roles %><br />
     <%= f.fields_for :role_ids do |r| %>
       <% @roles.each do |role| %>
         <%= check_box_tag "user[roles][]", role.id, @user.roles.include?(role.id) %>   
         <%= role.name %>   
       <% end %>
       <%= hidden_field_tag "user[roles][]", "" %>
     <% end %>
  </div>
<% end %>

使用此代码,我甚至会收到“角色”没有关联的错误。

编辑:使用accepts_nested_attributes_for :role更正了此问题。谢谢!

  

找不到名称`roles'的关联。它已被定义了吗?

我真的很困惑我做错了什么。非常感谢您的帮助。

的Aurelien

2 个答案:

答案 0 :(得分:2)

您必须在定义关联时使用与“accepts_nested_attributes_for”相同的名称:

class Assignment < ActiveRecord::Base
  belongs_to :user
  belongs_to :role
  accepts_nested_attributes_for :role
end 

答案 1 :(得分:0)

最后解决了我可以分享的问题和想法。

模型关联,但我确实更改了attr_accessible:

class User < ActiveRecord::Base
  has_many :assignments, :dependent => :destroy
  has_many :roles, :through => :assignments, :foreign_key => :role_id
  accepts_nested_attributes_for :roles
  attr_accessor :password
  attr_accessible ..., :roles_ids
  ...
end

在编辑和更新操作的用户控制器中。

def edit
  @title = "Edit" + " " + @user.username
  @roles = Role.find(:all)
  @user.assignments.build
end

def update
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user])
    flash[:success] = "Profile updated"
    redirect_to @user
  else
    @title = "Edit" + " " + @user.username
    render 'edit'
  end
end

重要的部分是视图部分,并为复选框标记

指定正确的名称
<%= form_for(@user) do |f| %>
  <div class="field">
  <%= f.label :roles %><br />
  <%= f.fields_for :role_ids do |r| %>
    <% @roles.each do |role| %>
      <%= check_box_tag "user[role_ids][]", role.id, @user.roles.include?(role) %>  
      <%= role.name %>  
    <% end %>
    <%= hidden_field_tag "user[role_ids][]", @user.id %>
  <% end %>
</div>

check_box_tag让表单保存数组并提供比check_box更多的控制权 然后,为了分配多个角色ID,check_box_tag的名称应包含user[roles_ids][]。 最后,如果用户已经有角色,check_box_tag的最后一个参数将返回,如果为true,则选中复选框。

我必须承认check_box_tags的名称部分确实令人困惑,但它有效:)。