用于事件和用户的rails邀请控制器

时间:2016-04-14 20:29:39

标签: ruby-on-rails ruby-on-rails-4 controller associations

这就是事情。我有用户和活动,我希望他们之间有邀请。那是用户可以邀请其他人参加活动。

我创建了一个Invitations控制器和模型。该模型看起来像这样

 user_id: (user being invited), event_id:(event_to_attend), inviter: (sent_the_invite)

我正在通过转到/邀请/新建并提交表单来从控制器构建我的邀请,但我无法让他们工作。它们是之前创建的,但是我做了一些更改并且没有创建,只是说“邀请已经发送”但是没有在控制台或任何内容中创建邀请。

我知道他们有效,因为我在控制台中

a=User.first
a.invitations.build(event_id: 1, inviter:2)
a.save

然后我可以看到邀请,user_id是创建邀请的人,在这种情况下,我可以看到邀请,并可以通过调用Event中的.invitees方法来获取用户。协会工作。但是我无法通过表单创建它。

这是表格

<%= form_for(@invitation) do |f| %>

<% userArray=User.all.select{|u| u.name unless u==current_user }%>
<% names=userArray.map{|u| u.name} %>
<% events=current_user.attended_events.map{|u| u.description} %>

<%= f.label :event %>
<%= f.select :event, events %>

<%= f.label :user %>
<%= f.select :user, names %>

<%= f.submit "Send" %>

<% end %>

我只使用用户名和UX的事件描述

这是我的邀请函控制器

类InvitationsController&lt; ApplicationController的     包括ApplicationHelper   def new     @邀请= Invitation.new   端

def创建     #Not考虑,重复用户和同一用户使用相同名称的事件。

#user being invited
@user=User.find_by(name: params[:invitation][:user])


#event being invited to
@event=Event.find_by(description: params[:invitation][:event])


#Inviter is current user, invitee is @user
@user.invitations.build(event_id: @event.id, inviter: current_user.id)

#Event not in user.attended_events
if !(@user.attended_events.where(id: @event.id) || \
    @user.invitations.where("user_id=@user.id AND event_id=@event.id") )

    flash.now[:danger]="User is already going to the event"
    render 'foo'
    #render 'new'

elsif @user.save!
    flash[:success]="Invitation was SENT!"
    redirect_to new_invitation_path
else 
    flash.now[:danger]="Please select both options"
    render 'foobar'
    #render 'new'
end
  end

1 个答案:

答案 0 :(得分:0)

你自己做得比自己要困难得多。

您可以先使用rails collection helpers清理表单:

<%= form_for(@invitation) do |f| %>
  <div class="row">
    <%= f.label :event_id %>
    <%= f.collection_select :event_id, Event.all, :id, :name, prompt: true %>
  </div>

  <div class="row">
    <%= f.label :user_id %>
    <%= f.collection_select :user_id, User.where.not(id: @invitation.inviter.id), :id, :name, prompt: true %>
  </div>

  <%= f.submit %>
<% end %>

这假定您使用current_user方法,并且您的事件和用户具有您要用于标签的名称属性(您可以使用您想要的任何属性)。使用的实际值是相关记录的ID。

请注意,我们使用参数键event_iduser_id。使用event会导致错误,因为setter需要一个实际的Event实例,而不仅仅是一个ID。

您可以在控制器中处理此问题,如下所示:

class InvitationsController < ActiveRecord::Base
  def new
    @invitation = current_user.invitations.new
  end

  def create
    @invitation = current_user.invitations.new(invitation_params)
    @invitation.save
    respond_with(@invitation)
  end

  private
    def invitation_params
      params.require(:invitation).permit(:event_id, :user_id)
    end
end

这不能解决通过创建重复邀请的问题。处理此问题的Rails方法是向模型添加唯一性验证:

class Invitation < ActiveRecord::Base
  belongs_to :user
  belongs_to :invitation
  belongs_to :inviter, class_name: 'User'
  validates_uniqueness_of :user_id, 
    scope: 'invitation_id',
    message: 'is already going to the event'
end

如果用户已被邀请并再次呈现@invitation.save视图,则会导致new失败。

Due to the possibility of race conditions您应该使用数据库索引支持验证。

# generate with
# $ rails g migration AddUniqueIndexToInvitation
class AddUniqueIndexToInvitation < ActiveRecord::Migration
  def change
    add_index :invitations, [:user_id, :event_id], unique: true
  end
end