简体   繁体   中英

Rails form_for has_many through association using AJAX not working

I'm having issues with a form_for that builds an association. I have an Event model, a User model and a Attendee model. The code for the models are as follows:

class User < ActiveRecord::Base
    has_many :activities, class_name: "Attendee", dependent: :destroy
    has_many :events, through: :activities

class Event < ActiveRecord::Base
    has_many :attendees, dependent: :destroy
    has_many :users, through: :attendees

class Attendee < ActiveRecord::Base
    belongs_to :user
    belongs_to :event

On the show page for an event I have a button to join the event which creates the association between a user and event.

<div id="join_event">
    <% if current_user.events.include?(@event) %>
        <%= render 'leave_event' %>
    <% else %>
        <%= render 'join_event' %>
    <% end %>
</div>

The join_event and leave_event partials are:

join_event:

<%= form_for(current_user.activities.build(event_id: @event.id), remote: true) do |f| %>
    <%= f.hidden_field :event_id %>
    <%= f.submit "Join event" %>
<% end %>

leave_event:

<%= form_for(current_user.activities.find_by(event_id: @event.id), html: { method: :delete }, remote: true) do |f| %>
    <%= f.submit "Leave event" %>
<% end %>

The @event in the partials above is in the show method in the events_controller:

def show
    @event = Event.find(params[:id])
end

The create and destroy methods in the attendees_controller are as follows:

def create
    @user_event = Event.find(params[:attendee][:event_id])
    current_user.events.push(@user_event)
    respond_to do |format|
        format.html { redirect_to event_path(@user_event) }
        format.js
    end
end

def destroy
    @user_event = Attendee.find(params[:id])
    current_user.activities.destroy(@user_event)
    respond_to do |format|
        format.html { redirect_to root_path }
        format.js
    end
end

The issue is that when I click the "Join event" button noting happens. The error that shows up in the Chrome dev tools under the 'Network' tab says:

undefined method `id' for nil:NilClass
Extracted source (around line #1):
    <%= form_for(current_user.activities.find_by(event_id: @event.id), html: { method: :delete }, remote: true) do |f| %>
        <%= f.submit "Leave event" %>
    <% end %>

The highlighted row is the first row with the "current_user.activities.find_by(event_id: @event.id)". When I check the database (I'm using PostgreSQL) the association has been created and if I hit the refresh button the leave_event partial is rendered. So the issue seems to be that using AJAX I am unable to access the id of the event show page. The same issue presents itself when I try to click the "Leave event" button. Nothing happens and the error that shows up in the Chrome dev tools under the 'Network' tab says:

undefined method `id' for nil:NilClass
Extracted source (around line #1):
    <%= form_for(current_user.activities.build(event_id: @event.id), remote: true) do |f| %>
        <%= f.hidden_field :event_id %>
        <%= f.submit "Join event" %>
    <% end %>

The association is destroyed but the "Join event" button isn't rendered because the form_for doesn't seem to be able to access the id from the url (in this particular case the url is localhost:3000 /events/34)

So my question is, how can I get the form_for to access the event id which is in the url? The association is created and the correct form renders as long as I hit the refresh button on the browser, but I'm unable to get it to work using AJAX.

Just in case it's needed, the create.js.erb and destroy.js.erb files(located in 'views/attendees') are:

$("#join_event").html("<%= escape_javascript(render('events/leave_event')) %>")

$("#join_event").html("<%= escape_javascript(render('events/join_event')) %>")

I believe the problem is you're calling @event from a partial, when you should be using locals :

<%= render partial: "join_event", locals: { event: @event } %>

#app/views/controller/_join_event.html.erb
<%= form_for(current_user.activities.build(event_id: event.id), remote: true) do |f| %>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM