【问题标题】:Route to the wrong URL路由到错误的 URL
【发布时间】:2015-11-24 00:15:04
【问题描述】:

我来了

ActionView::Template::Error(没有路由匹配 {:action=>"to_approve", :controller=>"microposts", :id=>nil} 缺少必需的键:[:id]):

没有路线匹配 {:action=>"to_approve", :controller=>"microposts", :id=>nil} 缺少必需的键:[:id]

但这没有意义,因为我正在路由到不同的路由

路由.rb

  match '/microposts/:id/approve',  to: 'microposts#to_approve'  , via: [:get, :post], as: 'approve_micropost'
  match '/microposts/to_approve',  to: 'microposts#approve'  , via: :get

controller.rb

def show
  @tag = Tag.find(params[:id])
  @microposts = @tag.microposts
end

show.html.rb

<%= render @microposts %>

_micropost.html.rb - 这是显示错误的行

  <% if is_an_admin? %>
    <%= link_to "Approve", approve_micropost_path(micropost.id) %>
  <% end %>

micropost_controller.rb

  def approve
    @microposts = Micropost.unapproved
  end

  def to_approve
    micropost = Micropost.unapproved_by_id(params[:id])
    if micropost.update_attributes(approved: true)
      flash[:success] = "Approved!"
    else
      flash[:error] = "Not approved!"
    end

    redirect_back_or microposts_to_approve_path
  end

微博.rb

  default_scope { where(approved: true).order('microposts.created_at DESC')}

  def self.unapproved
    self.unscoped.all.where(approved: false).order('microposts.created_at DESC')
  end

  def self.unapproved_by_id(id = nil)
    self.unscoped.all.where(id: id)
  end

你可以看到它试图用:id创建microposts_to_approve_path,这显然不存在,但我写了approve_micropost_path。

我错过了什么?

另外,在microposts_to_approve_path 的路由中,我允许[:get, :post] 虽然我只想允许通过on_click 事件(发布?)访问to_approve 方法并且没有视图。我应该如何重写这个?

rake routes:

       microposts POST     /microposts(.:format)             microposts#create
        micropost DELETE   /microposts/:id(.:format)         microposts#destroy
approve_micropost GET|POST /microposts/:id/approve(.:format) microposts#to_approve
microposts_to_approve GET      /microposts/to_approve(.:format)  microposts#approve

在错误页面,参数:

Request

Parameters:

{"id"=>"4",
 "name"=>"tag name"}

解决方案

问题是因为我使用了default_scope,而我正在使用的对象不正常。

修复前

@microposts = @tag.microposts        #@microposts is CollectionProxy

之后

@microposts = @tag.microposts.all    #@microposts is AssociationRelation

一旦我更改为.all,问题就解决了。

顺便说一句,这是一个错误吗?在我看来,default_scope 不应该改变默认行为..

【问题讨论】:

  • 显示你的rake routes结果
  • 请出示您的参数。

标签: ruby-on-rails ruby-on-rails-4 actionview


【解决方案1】:

如果您希望它只回复帖子,请尝试更改您的链接以使用“帖子”方法。

<% if is_an_admin? %>
  <%= link_to "Approve", approve_micropost_path(micropost.id), method: :post %>
<% end %>

相反,如果您希望它在 get 上路由到 microposts#to_approve,则让您的链接显式调用 get。

<% if is_an_admin? %>
  <%= link_to "Approve", approve_micropost_path(micropost.id), method: :get %>
<% end %>

然后你应该被路由到 microposts#to_approve 使用 POST。但是,由于您允许执行任一操作,请确保在您的 to_approve 操作中,您必须检查请求类型。如:

#microposts controller

def to_approve
  if request.post?
    # Do post related things
  else
    # Do get related things
  end
end

旁注*** 在approve url 上使用to_approve 操作,并在to_approve url 上使用approve 操作是令人困惑的,您可能会忘记为什么-you-did-what-you-当你在 6 个月后查看代码时会这样做。

编辑

另一种方法可能是将路由分开,这样您就不会在控制器中调用if 语句。

route.rb

post '/microposts/:id/approve',  to: 'microposts#approve', as: 'approve_micropost'
get '/microposts/:id/to_approval', to: 'microposts#to_approve', as: 'micropost_approvals'
resources :microposts

【讨论】:

  • 这让我想到是否需要将这里重构为其他东西。但这就是我想的方式,如果您有建议,欢迎您写它;)另外请注意,您只提到了第二个问题而不是第一个问题(错误)
  • 啊,我测试了你的代码,对我来说它取决于你的路线在 route.rb 中的位置。路线是自上而下处理的,因此您需要确保匹配线高于资源 :microposts 线。此外,在链接本身中添加method 会强制其行为正确而不是错误。
  • 我已将匹配项放在资源之前,并将method: :post 放在link_to 中,但仍然出现相同的错误。你能不能也把你在编辑中写的清楚,我没有跟着,我的控制器里没有if。
  • 什么版本的ruby和什么版本的rails?也许我缺少一些东西。您可以发布您的代码(github、bitbuckets 等)吗?
  • 如果不查看或测试您的代码,我很难说 - 我已经为您创建了这个代码示例,说明什么是有效的,请随时告诉我为什么这不是什么你需要,我可以更有帮助。 ::: github.com/trh/microposts_test_app
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-06
  • 2015-06-01
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 2011-11-24
相关资源
最近更新 更多