通过关联将Rails多对多 - 不能设置关系

时间:2014-05-31 14:10:52

标签: ruby-on-rails ruby many-to-many ruby-on-rails-4.1

我想创建一个带有邀请系统的应用,用户可以邀请成员加入不同的团队。但我无法让它发挥作用。我有四个模型对象 - UserTeamMember (join table between User & Team)& Invitation - 这些看起来像这样:

#User 

has_many :members
has_many :teams, through: :members
accepts_nested_attributes_for :teams
accepts_nested_attributes_for :members

has_many :sent_invitations, class_name: "Invitation", foreign_key: "sender_id"
has_many :invitations

#Team

has_many :members
has_many :users, through: :members
has_many :invitations

#Invitation

has_one :sender, class_name: "User"
has_one :recipient, class_name: "User"
belongs_to :team

我有ActionMailer向用户发送邀请,每个Invitation对象都有一个令牌。当我创建新用户时,我想以安全的方式将受邀用户添加到正确的团队中。我的用户控制器如下所示:

# GET /users/new
def new
  @user = User.new
  if params[:invitation_token]
    @user.email = Invitation.find_by_token(params[:invitation_token]).recipient_email
    @invitation = Invitation.where(token: params[:invitation_token])
  else
    @team = @user.teams.build
  end
end

# POST /users
# POST /users.json
def create
  @user = User.new(user_params)

  respond_to do |format|
    if @user.save
      sign_in @user

      # Private method for adding users to their teams.
      add_to_team

      [...]


def add_to_team
  if @invitation
    puts "Should add to team" # But never gets called!
    @user.teams << @invitation.team
    @user.invitations << @invitation
    @user.save!
  end
end

似乎add_to_team中的if语句永远不会评估为true。由于某种原因我的@invitation是零,我无法弄清楚原因。

有什么想法吗?

更新

尝试将我的@invitation实例变量改为我的创建操作。像这样:

def create
  @user = User.new(user_params)

  if params[:invitation_token]
    @invitation = Invitation.where(token: params[:invitation_token])
  end

 #And
 def add_to_team
   if @invitation
     # Never gets called
     @user.teams << @invitation.team
     @user.invitations << @invitation
     puts "Invited by team: #{@invitation.team.name}"
     @user.save!
   end
 end

但是if语句中的代码仍然没有被调用。

1 个答案:

答案 0 :(得分:1)

您需要了解的一件重要事情是新操作和创建操作,尽管在同一个控制器中定义会在不同时间调用,因此无法像在Ruby中那样共享任何变量。

共享此类数据有两种方法。一种是向新用户表单添加隐藏字段,并在新操作中将其设置为适当的值。然后从创建操作中访问它。

# new action
@invitation_token = params[:invitation_token]

# in form view
# add hidden field for invitation_token initialized to @invitation_token
# like following
<%= hidden_field_tag :invitation_token, @invitation_token %>

然后,访问params[:invitation_token]的代码将在创建操作中有效。

或者,使用会话变量从新操作传递令牌以创建操作。

# in new action
if params[:invitation_token]
  # other code
  session[:invitation_token] = params[:invitation_token]
else
 # other code
end


# in create action
if session[:invitation_token]
  @invitation = Invitation.where(token: session[:invitation_token])
  session[:invitation_token] = nil
end