【问题标题】:Rails form_for has_many through association using AJAX not workingRails form_for has_many 通过使用 AJAX 的关联不起作用
【发布时间】:2014-05-03 02:18:01
【问题描述】:

我遇到了用于建立关联的 form_for 的问题。我有一个事件模型、一个用户模型和一个参加者模型。模型代码如下:

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

在一个事件的显示页面上,我有一个按钮来加入该事件,它创建了用户和事件之间的关联。

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

join_event 和 leave_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 %>

离开事件:

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

上面部分中的@event在events_controller的show方法中:

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

attendees_controller中的create和destroy方法如下:

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

问题是,当我单击“加入事件”按钮时,会发生这种情况。在“网络”标签下的 Chrome 开发工具中显示的错误是:

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 %>

突出显示的行是“current_user.activities.find_by(event_id:@event.id)”的第一行。当我检查数据库(我使用的是 PostgreSQL)时,关联已创建,如果我点击刷新按钮,则呈现 leave_event 部分。所以问题似乎是使用 AJAX 我无法访问事件显示页面的 id。当我尝试单击“离开事件”按钮时,也会出现同样的问题。什么都没有发生,并且在“网络”标签下的 Chrome 开发工具中显示的错误说:

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 %>

关联被破坏,但“加入事件”按钮未呈现,因为 form_for 似乎无法从 url 访问 id(在这种特殊情况下,url 是 localhost:3000 /events/34 )

所以我的问题是,我怎样才能让 form_for 访问 url 中的事件 id?只要我点击浏览器上的刷新按钮,就会创建关联并呈现正确的表单,但我无法使用 AJAX 让它工作。

以防万一,create.js.erb 和 destroy.js.erb 文件(位于“views/attendees”中)是:

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

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

【问题讨论】:

  • @event 为零。这个实例值应该在控制器中创建,它不应该从 url 中获取。您可以先在没有remote: true 的情况下对其进行调试,然后再将其添加回来。
  • form_for中的@event不是引用events_controller中show方法中的@event吗?我从 url 获取 id 的意思是参考传递给 Event.find()params[:id]。参数哈希中的 id 不是来自 url 吗?当我第一次加载页面时,@event 不是 nil,所以我很困惑为什么单击“加入事件”按钮后它变为 nil。
  • 另外,它可以在没有remote: true 的情况下工作。直到我添加了 AJAX,我才开始遇到问题。
  • 导轨是什么样的?单击“加入事件”按钮后,它会调用创建操作,但不会再次调用显示操作。所以它将为零。在create方法中把@user_event改成@event怎么样?
  • 我在 create 方法中将 @user_event 更改为 @event 并使其正常工作。对于destroy 方法,我必须添加一个实例变量来获取事件ID——@event = Event.find(@user_event.event_id)。感谢您的帮助!

标签: javascript jquery ruby-on-rails ajax


【解决方案1】:

我相信问题是你从部分调用@event,而你应该使用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| %>

【讨论】:

  • 我在原帖下的 cmets 中详细说明了它的工作原理。我尝试按照您的建议进行操作,看看它是否也可以工作,但我遇到了与最初得到的错误相同的错误:nil 类的未定义方法“id”。有没有办法在 js.erb 文件中使用本地变量?由于渲染调用来自那些可能有效的文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
  • 2012-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多