将id设置为rails中的默认外键

时间:2015-02-23 20:28:56

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

我遇到了挑战,要为当前用户分配用户正在创建的团队中的角色。我想为创建团队的用户分配队长的角色,以后可以更改  我目前正在使用has_one关系附带的create_asociation方法,因为这会实例化关联模型的值,我希望将其与当前用户实例化,但会收到错误Can't mass assign protected attribute: captain。 Captain是一个与用户的自我联接模型,因为我想使用captain.teammatesteam.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这样的宝石来创建基于角色的授权。感谢

1 个答案:

答案 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