Rails has_one、belongs_to、join_table 和嵌套形式
Rails has_one, belongs_to, join_table and nested form
我正在创建用户、角色和用户角色。用户可以创建角色列表,并且从新用户表单中,有一个嵌套表单填充创建的角色列表,然后用户能够 select 角色并与新用户关联。我能够创建角色列表,但在新用户视图文件中创建嵌套表单时遇到问题。
模型如下,关系是否正确,还望指教
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
之间的关系是否正确。
如果用户只能拥有一个角色,那么您实际上并不需要首先 user_roles
加入 table:
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
您还陷入了一个常见的初学者陷阱,您将嵌套属性与简单的 select 关联混淆了。
您不需要 @user.build_user_role
或 f.fields_for :user_role
。您只需要一个 select 并将 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
我正在创建用户、角色和用户角色。用户可以创建角色列表,并且从新用户表单中,有一个嵌套表单填充创建的角色列表,然后用户能够 select 角色并与新用户关联。我能够创建角色列表,但在新用户视图文件中创建嵌套表单时遇到问题。
模型如下,关系是否正确,还望指教
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
之间的关系是否正确。
如果用户只能拥有一个角色,那么您实际上并不需要首先 user_roles
加入 table:
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
您还陷入了一个常见的初学者陷阱,您将嵌套属性与简单的 select 关联混淆了。
您不需要 @user.build_user_role
或 f.fields_for :user_role
。您只需要一个 select 并将 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