我遇到了挑战,要为当前用户分配用户正在创建的团队中的角色。我想为创建团队的用户分配队长的角色,以后可以更改
我目前正在使用has_one关系附带的create_asociation方法,因为这会实例化关联模型的值,我希望将其与当前用户实例化,但会收到错误Can't mass assign protected attribute: captain
。 Captain是一个与用户的自我联接模型,因为我想使用captain.teammates
和team.captain
。
以下是涉及的模型。
用户和队长模型
class User < ActiveRecord::Base
has_one :profile
has_many :teammates, :class_name => "User", :foreign_key => "captain_id"
belongs_to :captain, :class_name => "User"
belongs_to :team
# before_create :build_profile
after_create :build_default_profile
accepts_nested_attributes_for :profile
attr_accessible :email, :password, :password_confirmation, :profile_attributes, :captain_id
def build_default_profile
Profile.create(user_id: self.id)
end
has_secure_password
before_save { email.downcase! }
before_save :create_remember_token
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }
validates :password_confirmation, presence: true
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
团队模型
class Team < ActiveRecord::Base
has_many :profiles, through: :users
has_one :captain, :class_name => "User", foreign_key: :captain_id
has_one :result, as: :result_table
attr_accessible :teamname, :color, :result_attributes, :captain_attributes
after_create :build_result_table
after_create :build_default_captain
accepts_nested_attributes_for :profiles
accepts_nested_attributes_for :captain
accepts_nested_attributes_for :result
def build_result_table
Result.create(result_table_id: self.id, result_table_type: self.class.name)
end
def build_default_captain
# Team.captain = User
# Captain.create(team_id: self.id, captain_id: user.id)
end
end
用户控制器
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update, :destroy]
before_filter :correct_user, only: [:edit, :update]
before_filter :admin_user, only: :destroy
def new
@user = User.new
end
def create
@user = User.new(params[:user])
if @user.save!
sign_in @user
flash[:success] = "Welcome to the JHDC Mini Olympics Web Application; Thanks for singing Up"
redirect_to user_profile_path(@user, @profile)
else
flash[:error_messages]
render 'new'
end
end
def show
@user = User.find(params[:id])
end
def index
@users = User.paginate(page: params[:page])
end
def edit
@user = User.find(params[:id])
end
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
flash[:success] = "Profile Updated"
redirect_to user_profile_path(@user, @profile)
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted."
redirect_to users_url
end
private
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_path) unless current_user?(@user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
end
团队控制员
class TeamsController < ApplicationController
def new
@team = Team.new
end
def create
@team = Team.new(params[:team])
@captain = @team.create_captain(captain: current_user)
if current_user.admin?
if @team.save!
flash[:success] = "Team created."
redirect_to @team
else
flash[:error_messages]
render 'new'
end
else
flash[:error] = "Sorry, you don't have the authority to create a Team"
redirect_to current_user
end
end
def index
@teams = Team.paginate(page: params[:page])
end
def show
@team = Team.find(params[:id])
end
def edit
if current_user.admin?
@team = Team.find(params[:id])
else
flash[:error] = "Sorry you dont have the authourity to edit a Team"
redirect_to current_user
end
end
def update
@team = Team.find(params[:id])
if @team.update_attributes(params[:team])
flash[:success] = "Team Updated"
redirect_to @team
else
render 'edit'
end
end
def destroy
Team.find(params[:id]).destroy
flash[:success] = "Team is deleted."
redirect_to teams_url
end
private
def team_params
params.require(:team).permit(:teamname, :color)
end
end
管理员目前是我用来限制可以创建团队的用户的方式,但我打算使用像declarative authorization
这样的宝石来创建基于角色的授权。感谢
答案 0 :(得分:0)
您获得的错误是因为属性:captain未声明为attr_accessible
在User模型的attr_accessible列表中设置属性:captain,或者更改代码形式
Captain.create(team_id: self.id, captain_id: user.id)
到
captain = Captain.new
captain.team_id = self.id
captain.captain_id = user.id
captain.create
通过这种方式,该属性不会通过质量分配来设置,并且不会引发错误
被修改
在检查了你的代码两次之后,我们意识到你没有船长模型,实际上:船长是用户的关系以及团队与用户之间的关系。
所以在团队模型上,取下build_default_captain的东西和after_create:build_default_captain,我会说用
之类的东西替换after_save :set_default_captain
def set_default_captain
if captain_id_changed?
profiles.each do |user|
user.captain = captain
user.save
end
end
end
所以每次captain_id更改模型时,都会更改其所有配置文件(用户)的captain_id
然后在Team控制器上,在动作创建上,而不是
@team = Team.new(params[:team])
@captain = @team.create_captain(captain: current_user)
做类似
的事情@team = Team.new(params[:team])
@team.captain = current_user
if current_user.admin?
if @team.save!
current_user.update_attribute(:team_id, @team.id)
flash[:success] = "Team created."
redirect_to @team
else
flash[:error_messages]
render 'new'
end
else
flash[:error] = "Sorry, you don't have the authority to create a Team"
redirect_to current_user
end
所以在代码的最后一部分,你将团队的队长设置为当前用户,并在保存后将用户团队设置为当前团队,你也可以使用current_user.build_team改进代码以避免保存current_user .update_attribute