Rails 4 link_to方法::post和remote:真正的奇怪行为

Posted

技术标签:

【中文标题】Rails 4 link_to方法::post和remote:真正的奇怪行为【英文标题】:Rails 4 link_to method: :post and remote: true strange behavior 【发布时间】:2016-07-31 02:03:31 【问题描述】:

我有一个活动管理页面,其中包含两个部分,一个包含尚未受邀参加活动的合作伙伴,一个包含受邀参加活动的合作伙伴。可以将合作伙伴添加到活动(other_partners 集合)或删除(current_partners 集合)。

取决于动作顺序的奇怪行为

删除然后创建 => 一切正常,我可以无限添加和删除

页面加载后,我可以毫无问题地删除合作伙伴(方法::delete),合作伙伴从 current_partners 集合(部分)中消失,并出现在 other_partners 集合(部分)中。如果尝试添加合作伙伴,它会起作用,并且合作伙伴会添加到 current_partners 集合并从 other_partners 集合中删除

Create then GET 500 ERROR => Rails 似乎忽略了 ujs

加载页面后,如果我单击 other_partner 部分内的合作伙伴以将其添加(方法::发布)到事件中,rails 会忽略 method: :post 并获取提供的 url,这会导致 500 错误,因为操作show 不在我的控制器中(仅创建和销毁)

这是我的代码:

_other_partner.html.erb

是一个包含未参与该事件的用户合作伙伴的部分。单击合作伙伴时,它会添加到事件中,从 other_partners 集合中消失并出现在 current_partners 集合中。

请注意,网址类似于 /events/1/manage_partners?id=21。 我将合作伙伴的 ID 作为附加参数传递,以创建事件和合作伙伴之间的链接。我没有使用按钮,因为部分已经在较大的表单中。

  <%= div_for partner, class: "partner__current",
                       data:  behavior: "partner", id: partner.id  do %>

    <%= link_to event_manage_partners_path(event, id: partner.id),
                method: :post,
                data:  behavior: "create-partner" ,
                remote: true,
                class: "link--primary" do %>
        <%= content_tag :div, nil, class: "icon icon__add_circle--black" %>
    <% end %>

  <% end %>

-

_current_partner.html.erb

是参与活动的所有合作伙伴的部分列表。单击合作伙伴时,它会从事件中删除,从 current_partners 集合中消失并出现在 other_partners 集合中。

  <%= div_for partner, class: "partner__current",
                       data:  behavior: "partner"  do %>

    <%= link_to event_manage_partner_path(event, partner),
                method: :delete,
                remote: true,
                class: "link--primary" do %>
        <%= content_tag :div, nil, class: "icon icon__cancel_circle--black" %>
    <% end %>

  <% end %>

-

event.html.erb

<%= render partial: 'partners/other_partner',
                     collection: @event_facade.other_partners,
                     as: :partner,
                     locals:  event: @event_facade.event ,
                     cached: true %>
<% end %>

<%= render partial: 'partners/current_partner',
                     collection: @event_facade.current_partners,
                     as: :partner,
                     locals:  event: @event_facade.event ,
                     cached: true %>
<% end %>

-

create.js 和 destroy.js(两者相似)

$("[data-behavior='new-partner']").html("<%= j render partial: 'partners/other_partner', collection: @event_facade.other_partners, as: :partner, locals:  event: @event_facade.event , cached: true %>");

$("[data-behavior='current-partners']").html("<%= j render partial: 'partners/current_partner', collection: @event_facade.current_partners, as: :partner, locals:  event: @event_facade.event , cached: true %>");

-

事件/manage_partner_controller.rb

module Events
  class ManagePartnersController < ApplicationController
    before_action :set_event

    def create # (url looks like /events/1/manage_partners?id=21)
      @event_facade = EventFacade.new(@event)
      EventPartnerService.new(@event).join_event(params[:id])
      respond_to do |format|
        format.html  redirect_to edit_event_url(@event) 
        format.js #  render layout: false 
      end
    end

    def destroy
      @event_facade = EventFacade.new(@event)
      EventPartnerService.new(@event).leave_event(params[:id], current_user)
      respond_to do |format|
        format.html  redirect_to edit_event_url(@event) 
        format.js #  render layout: false 
      end
    end

    private

    def set_event
      @event = current_user.events.find(params[:event_id])
    end

  end
end

-

布局/application.html.erb

<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>

-

assets/javascript/application.js(bower 加载的 jquery-ujs)

//= require jquery/dist/jquery.min
//= require jquery.turbolinks
//
//= require jquery-ujs/src/rails
//= require turbolinks

-

routes.rb

resources :users, only: [:index, :show], concerns: :paginatable do
  resources :events, except: :new, concerns: :paginatable do
    resources :manage_partners, controller: 'events/manage_partners', only:[:create, :destroy]
  end
end

-

rake 路由输出

event_manage_partners POST (/:locale)/events/:event_id/manage_partners(.:format) events/manage_partners#create :locale=>/en-US|fr-FR/

event_manage_partner DELETE (/:locale)/events/:event_id/manage_partners/:id(.:format) events/manage_partners#destroy :locale=>/en-US|fr-FR/

这是 500 错误:

ActionController::RoutingError (No route matches [GET] "/events/81/manage_partners"):

当我特别要求 POST 时,Rails 会尝试 GET。 manage_partners_controller.rb 不包含显示操作,仅包含 #create 和 #destroy,因此会出现错误。

同样,除了method: :post 之外,一切正常,在第一页加载后单击链接时会被忽略。 奇怪的行为,我在这里很无知。请帮忙。谢谢!

【问题讨论】:

您列出了所有内容,但出现的错误除外。 你说得对,我把它添加到问题中 让我们看看你的 routes.rb 为那条路线。 另外,我以前从未见过//= require jquery-ujs/src/rails。通常只是//= require jquery-ujs 您的浏览器是否启用了Javascript?饼干? 【参考方案1】:

可能是因为您嵌套的级别太深,您不应将资源嵌套超过一层。看看这个http://guides.rubyonrails.org/routing.html#nested-resources

把它放在我的页面标题中,它解决了 turbolink 的问题

  if(typeof Turbolinks != 'undefined') 
    $(document).on("page:change", function()
      myFunction();
    );
  
  else 
    $(document).ready(function ()
      myFunction();
    ); 
  

【讨论】:

我用 jquery-ujs 做了一些实验,尝试了不同的组合(有 gem、有凉亭、有和没有表格、需要树等)。似乎有些东西使 /assets/javascript/application.js 中的 turbolinks+bower jquery-ujs+require 树破坏了一些东西。还在挖 我之前遇到过 turbolinks 和 jquery 的问题,我会用为我修复的内容更新我的评论。可能有助于指导哟等 好的,所以我重新安装了所有凉亭和组件,干净的石板。现在当我删除 require_tree 时。从 application.js 清单文件中,它可以工作。当我让它时,它失败了。我必须有一个静默失败的文件,我不知道如何识别它,除了激活/停用(评论 //= 要求 ...)一个一个。 您可能会从 2 个不同的地方调用 javascript 两次,这可能会覆盖。 我仔细检查过,但似乎并非如此。但是,我检查了所有内容并更新了所有内容。一旦我使用 require_tree .,第一次加载时将忽略 post 方法。我现在会坚持手动声明所有要求,但不知道为什么会中断,这让我很困扰。

以上是关于Rails 4 link_to方法::post和remote:真正的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

如果 JS 可能被禁用,Rails 4 link_to :delete 的最佳方法是啥?

Rails 4:使用 link_to 切换布尔值

Rails 的 link_to 方法:GET 啥时候应该 DELETE

如何从 Rails 中的控制器混入和调用 link_to?

Rails link_to 方法: :delete

Rails:禁用link_to链接不起作用但隐藏link_to工作