【问题标题】:Rails has_one, belongs_to, join_table and nested formRails has_one、belongs_to、join_table 和嵌套表单
【发布时间】:2020-04-05 01:09:48
【问题描述】:

我正在创建一个用户、角色和用户角色。用户可以创建角色列表,并且在新用户表单中,有一个嵌套表单填充创建的角色列表,然后用户可以选择角色并与新用户关联。我能够创建角色列表,但在新用户视图文件中创建嵌套表单时遇到问题。

这是模型,如果关系正确,请告诉我。

class User < ApplicationRecord
  has_one :user_role
  has_one :role, through: :user_role
end

class Role < ApplicationRecord
  has_many :user_roles
  has_many :users, through: :user_roles
end

class UserRole < ApplicationRecord
  belongs_to :user
  belongs_to :role
end

User 控制器。我不确定我的控制器是否正确:

def new
  @user = User.find_by_id(params[:id])
  @user = @current_user.account.users.new
  @user.build_user_role
end

def create
  @user = User.find_by_id(params[:id])                
  @user = @current_user.account.users.create_with_password(user_params)
    if @user.save
       redirect_to users_path
    else
       render 'new'
    end
end

private
def user_params
  params.require(:user).permit(:id, :email, :password, :password_confirmation, :admin, :owner, user_role_attributes: [:user_id, :role_id])
end

end

下面是新的用户表单:

<%= form_for(@user, remote: true) do |f| %>

<%= f.text_field :email, class: "form-control", autofocus: true, autocomplete: "off" %>
<%= f.check_box :admin, class:"checkbox" %>
<%= f.check_box :owner, class:"checkbox" %>

<%= f.fields_for :user_role do |ff| %>
<%= ff.collection_select :role_id, @roles, :id, :role_name, include_blank: false %>
<% end %>             

<%= f.button "Create",  class: "btn btn-success" %>

<% end %>

user_role的嵌套表格不显示,还请告知User、Role和UserRole之间的关系是否正确。

【问题讨论】:

    标签: ruby-on-rails activerecord nested-forms has-one-through


    【解决方案1】:

    如果用户只能拥有一个角色,那么您首先就不需要user_roles 连接表:

    class User < ApplicationRecord
      belongs_to :role
    end
    
    class Role < ApplicationRecord
      has_many :users
    end
    

    虽然假设您实际上不需要多对多关联似乎很天真,但这实际上更有用。例如:

    class User < ApplicationRecord
      has_many :user_roles
      has_many :roles, through: :user_roles
    end
    
    class Role < ApplicationRecord
      has_many :user_roles
      has_many :users, through: :user_roles
    end
    
    class UserRole < ApplicationRecord
      belongs_to :user
      belongs_to :role
    end
    

    您还陷入了一个常见的初学者陷阱,您将嵌套属性与简单地选择关联混淆了。

    您不需要@user.build_user_role 或f.fields_for :user_role。您只需要一个选择并将role_id 参数列入白名单:

    <%= form_for(@user, remote: true) do |f| %>
      # ...
      <%= f.collection_select :role_id, @roles, :id, :role_name, include_blank: false %>
      # ...
    <% end %>
    

    def new
      # why even do this if you are just reassigning it on the next line?
      @user = User.find_by_id(params[:id]) 
      @user = @current_user.account.users.new
    end
    
    def create
      @user = User.find_by_id(params[:id])
      # Violation of Law of Demeter - refactor!
      @user = @current_user.account.users.create_with_password(user_params)
      if @user.save
        redirect_to users_path
      else
        render 'new'
      end
    end
    
    private
    def user_params
      params.require(:user)
            .permit(
              :id, :email, :password, 
              :password_confirmation, 
              :admin, :owner, 
              :role_id # this is all you really need
            )
    end
    

    【讨论】:

    • 只有当您想在创建用户时动态创建角色时才需要嵌套属性。您也很少需要手动对连接表执行任何操作。只需在模型上使用设置器,ActiveRecord 就会为您创建连接表行。
    • 嗨,max,您的建议真的很有帮助。角色有很多用户,而用户属于角色,它使事情变得简单。到目前为止效果很好!
    猜你喜欢
    • 1970-01-01
    • 2014-10-01
    • 2014-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多