如何在ajax button_to上正确设置路由?

时间:2011-12-02 18:10:47

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

我已经实现了一个基于ajax的按钮,用于从用户的“愿望清单”中添加和删除日历事件。该按钮表现为切换开关。如果事件已经在他们的愿望清单上,它将删除它;如果不是,则会添加它。

我的问题是,首次加载页面时按钮正常工作,但点击它并通过AJAX将其替换为新的button_to后,它就不再有效了。

我看了this post,但他的架构略有不同,如果我能避免的话,我不打算完全重构。我有一个单独的模型用于保存的事件。这里有三种模式:用户,事件和saved_events。用户和事件之间存在多对多关系,表示为saved_event。以下是模型中的相关代码。

user.rb:

  has_many :saved_events
  has_many :events, :through => :saved_events

event.rb:

  has_many :saved_events
  has_many :watchers, :class_name => "User", :through => :saved_events, :source => :user

saved_event.rb:

  belongs_to :event
  belongs_to :user

我配置了非常标准的路线。

routes.rb中:

  resources :saved_events, :only => [:index,:create,:destroy]
  resources :users
  resources :events

我最初希望看到此按钮成为事件的页面,因此我将其添加到事件的show.html.erb中。 (我意识到这还不是很干 - 我等到它能正常工作才能将它变成部分干扰)

事件/ show.html.erb:

  <% if !@is_watched %>
    <%= button_to "Add to Wishlist", { :action => 'create', :controller => 'saved_events', :id => @event.id }, :remote => true %>
  <% else %>
    <%= button_to "Remove from Wishlist", saved_event_path(@event), :remote => true, :method => 'delete' %>
  <% end %>

events_controller.rb:

  def show
    @event = Event.find(params[:id])
    @is_watched = @event.watchers.exists?(current_user) if !current_user.nil?

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @event }
      format.json { render :json => @event }
    end
  end

saved_events_controller.rb:

  def create
    logger.debug params.to_yaml

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

    if !current_user.events.exists?(params[:id])
      current_user.events << @event
    end

    respond_to do |format|
      format.js
    end
  end

  def destroy
    logger.debug params.to_yaml

    @event = current_user.events.find(params[:id])
    current_user.events.delete(@event)

    respond_to do |format|
      format.js
    end
  end

我使用ajax的目标只是将删除表单替换为添加表单(反之亦然)。所以我有一个create.js.erb和一个destroy.js.erb,它只使用来自events / show.html.erb的相同代码。

saved_events / create.js.erb:

$(".button_to").html("<%= escape_javascript button_to "Remove from Wishlist", saved_event_path(@event), :remote => true, :method => 'delete' %>");

saved_events / destroy.js.erb:

$(".button_to").html("<%= escape_javascript (button_to "Add to Wishlist", { :action => 'create', :controller => 'saved_events', :id => @event.id }, :remote => true) %>");

如果第二个按钮点击是“删除”

,这就是我在日志中看到的内容
Started DELETE "/saved_events?id=1" for 127.0.0.1 at 2011-12-02 11:56:58 -0600

ActionController::RoutingError (No route matches [DELETE] "/saved_events"):

如果第二个按钮点击是“添加”

,这就是我在日志中看到的内容
Started POST "/saved_events/1" for 127.0.0.1 at 2011-12-02 11:59:12 -0600

ActionController::RoutingError (No route matches [POST] "/saved_events/1"):

在初始加载页面时,添加按钮有“/ saved_events?id = 1”作为其动作,所以我很困惑为什么第二次按钮点击它将是“/ saved_events / 1”。

1 个答案:

答案 0 :(得分:1)

似乎问题来自我的jquery。我需要将表单包装在div中,然后在该div上调用jquery.html()而不是表单本身。我在控制器中做了一些其他的重构,为了简洁,我不会在这里发布,但这里是我的新js.erb文件:

create.js.erb:

<% button_html = button_to( 'Remove from Wishlist', { :action => 'destroy', :id => @saved_event.id }, :remote => true, :method => 'delete' ) %>
$("#toggle_wishlist").html("<%= escape_javascript( button_html ) %>");

destroy.js.erb:

$("#toggle_wishlist").html("<%= escape_javascript( button_to("Add to Wishlist", { :action => 'create', :controller => 'saved_events' }, :remote => true)) %>");
$("#toggle_wishlist .button_to").append("<%= escape_javascript( hidden_field_tag :event_id, @event.id ) %>");