【译】在多对多的模型中使用model.collection_model_ids

Saturday, July 24, 2010

原文:http://rails-bestpractices.com/posts/8-model-collection_model_ids-many-to-many

当你想在视图中使用复选框来关联一个模型到多个模型对象,你应该利用“model.collection_model_ids”来减少控制器中的代码

丑陋的...

class User < ActiveRecord::Base
  has_many :user_role_relationships
  has_many :roles, :through => :user_role_relationships
end

class UserRoleRelationship < ActiveRecord::Base
  belongs_to :user
  belongs_to :role
end

class Role < ActiveRecord::Base
end



<% form_for @user do |f| %>
  <%= f.text_field :email %>
  <% Role.all.each |role| %>
    <%= check_box_tag 'role_id[]', role.id, @user.roles.include?(role) %>
    <%= role.name %>
  <% end %>
<% end %>



class UsersController < ApplicationController
  def update
    @user = User.find(params[:id])
    if @user.update_attributes(params[:user])
      @user.roles.delete_all
      (params[:role_id] || []).each { |i| @user.roles << Role.find(i) }
    end
  end
end

和你看到的那样, 用户模型和权限模型是多对多的关系, 这里是用一个表单来关联一个用户有多个角色, 在控制器中, 我们开始删除用户的所有角色,
然后再根据复选框的选择项对用户的权限赋值,这是个丑陋的角色分配,我们应该使用rails的精巧方法

重构...

<% form_for @user do |f| %>
  <% Role.all.each |role| %>
    <%= check_box_tag 'user[role_ids][]', role.id, @user.roles.include?(role) %>
    <%= role.name %>
  <% end %>
  <%= hidden_field_tag 'user[role_ids][]', '' %>
<% end %>



class UsersController < ApplicationController
  def update
    @user = User.find(params[:id])
    @user.update_attributes(params[:user])
    # the same as @user.role_ids = params[:user][:role_ids]
  end
end

我们把复选框的名字从"role_id[]" 改成 "user[role_ids][]"了,
这样role_ids讲自动赋值给用户,请注意有个“hidden_field_tag 'user[role_ids][]'”,
它的值是空的, 如果复选框中没有用户角色被选择,那么关联的角色将被销毁, 现在我们的控制器又一次被变得简单

This entry was tagged Rails and Best-Practices

comments powered by Disqus

© 2009-2013 lxneng.com. All rights reserved. Powered by Pyramid

go to Top