【问题标题】:Edited... ActionView::Template::Error (No route matches... missing required keys: [:comment_id])已编辑... ActionView::Template::Error (没有路由匹配...缺少必需的键:[:comment_id])
【发布时间】:2016-07-28 11:41:48
【问题描述】:

当我访问 photos/show.html.erb 视图时,我从 Heroku 日志中收到以下错误:

ActionView::Template::Error(没有路由匹配 {:action=>"index", :comment_id=>nil, :controller=>"cflags", :photo_id=>"100"} 缺少必需的键:[ :comment_id])

我有非常基本的 PhotoComment 模型可以正常工作,然后我构建了一个用于标记 cmets 的 Cflag 模型。我使用@photo.comments 列出photos/show.html.erb 视图中的cmets。

显示:

# photos/show.html.erb

<% @photo.comments.each do |comment| %>
  <%= form_for(comment, url: photo_comment_cflags_path(@photo, comment)) do |f| %>
    <%= f.hidden_field :user_id, value: current_user.id %>
    <%= f.submit "Report Inappropiate" %>
  <% end %>
<% end %> 

Cflags 控制器:

class CflagsController < ApplicationController
before_action :logged_in_user

def new
end

def create
  @comment = Comment.find(params[:comment_id])
  @cflag = @comment.cflags.build(cflag_params)
    if @cflag.save
      if @comment.cflags_count > 1
        @comment.update_attribute(:approved, false)  
        flash[:success] = "Flag created! Comment ##{@comment.id} has been removed for review. Thank you for your feedback"
        redirect_to :back
      else    
        flash[:success] = "Flag created! Thank you for your feedback"
        redirect_to :back
      end
    else
      redirect_to :back, notice: @cflag.errors.full_messages  
    end    
  end    

  private 
    def cflag_params
      params.require(:cflag).permit(:user_id, :comment_id).merge(user_id: current_user.id)
    end
end

路线:

resources :photos do
  resources :comments, only: [:create, :edit, :destroy] do
    resources :cflags, only: :create
  end  
end

铁路路线:

    photo_comment_cflags GET        /photos/:photo_id/comments/:comment_id/cflags(.:format)          cflags#index
                         POST       /photos/:photo_id/comments/:comment_id/cflags(.:format)          cflags#create
 new_photo_comment_cflag GET        /photos/:photo_id/comments/:comment_id/cflags/new(.:format)      cflags#new
edit_photo_comment_cflag GET        /photos/:photo_id/comments/:comment_id/cflags/:id/edit(.:format) cflags#edit
     photo_comment_cflag GET        /photos/:photo_id/comments/:comment_id/cflags/:id(.:format)      cflags#show
                         PATCH      /photos/:photo_id/comments/:comment_id/cflags/:id(.:format)      cflags#update
                         PUT        /photos/:photo_id/comments/:comment_id/cflags/:id(.:format)      cflags#update
                         DELETE     /photos/:photo_id/comments/:comment_id/cflags/:id(.:format)      cflags#destroy

照片控制器:

def show
  @photo = Photo.approved.find(params[:id])
end

评论控制器:

def create
   @photo = Photo.find(params[:photo_id])
   @comment = @photo.comments.build(comment_params)
   @comment.save
   respond_to do |format|
     format.html { redirect_to :back }
     format.js 
   end 
end   

Cflag 模型:

class Cflag < ActiveRecord::Base
  belongs_to :comment, counter_cache: true
  belongs_to :user, counter_cache: true
  validates :user_id, presence: true 
  validates :comment_id, presence: true
  validates :user_id, uniqueness: { 
    scope: [:comment_id],
    message: 'You can only flag a comment once. Thank you for your feedback.'
  }
  default_scope -> { order(created_at: :desc) }
end

架构:

create_table "cflags", force: :cascade do |t|
  t.integer  "comment_id"
  t.integer  "user_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

add_index "cflags", ["comment_id"], name: "index_cflags_on_comment_id"
add_index "cflags", ["user_id"], name: "index_cflags_on_user_id"

在 Heroku 控制台中

p = Photo.find(100) 
p.comments = => #<ActiveRecord::Associations::CollectionProxy [#<Comment id: 309, content: "hi", photo_id: 100, user_id: 1, created_at: "2016-07-24 04:43:17", updated_at: "2016-07-24 04:43:17", approved: true, cflags_count: nil>

【问题讨论】:

  • 您好,如果显示页面中已经报告了评论会怎样?
  • 好吧,我还没有得到要加载表单的页面,但如果它确实加载并且 cflag 已经存在,那么它将触发:else redirect_to :back, notice: @cflag.errors.full_messages,因为模型中的唯一性范围:@987654337 @

标签: ruby-on-rails


【解决方案1】:

将表单操作更改为此, 更新

<% if @photo.comments.any? %>
   <% @photo.comments.each do |comment| %>     
     # you do not have to use comment in form_for, because this form is for creating cflag
     <%= form_for(:cflag, url: photo_comment_cflags_path(@photo, comment), method: "post") do |f| %> 
          <%= f.hidden_field :user_id, value: current_user.id %> 
          <%= f.submit "Report Inappropiate" %> 
     <% end %> 
   <% end %> 
<% end %>

【讨论】:

  • 到目前为止,您使用的是索引操作而不是创建操作,因为 photo_comment_cflags 代表索引操作(注意额外的 s 会更改整个意思)。
  • 我收到以下错误:ActionView::Template::Error (undefined method photo_comment_cflag_path。但是,将其更改为 photo_comment_cflags_path 使其工作。我已将 cflag 路由设置为only: create。太棒了,因为我用相同的代码尝试了 Cflag.new 和 @cflag。我猜:cflag 实际上是代码工作/不工作之间的区别。
  • 你能把new_添加到我的代码中提到的url吗?
  • 现在实际测试并且 Cflag.new 和 :cflag 都可以工作。将继续测试以隔离允许其工作的特定代码。当我将路由更改为new_photo_comment_cflag_path 时,出现以下错误:ActionView::Template::Error (undefined method new_photo_comment_cflag_path'`
  • 您能否在路由中添加 :new 方法,现在它只接受 :create。
【解决方案2】:

根据Rails documentationform_for 方法的预期参数是(record, options = {}, &amp;block)

form_for(record, options = {}, &block) public

创建一个允许用户创建或更新属性的表单 特定模型对象。

该方法可以以几种略有不同的方式使用,具体取决于 你希望在多大程度上依赖 Rails 自动推断 建模应该如何构建表单。对于通用模型对象, 可以通过传递form_for 字符串或符号来创建表单 表示我们关心的对象:

因此,您可能希望删除在form_for 方法中插入的额外[],它应该如下所示:

<% @photo.comments.each do |comment| %>
  <%= form_for(Cflag.new, url: photo_comment_cflags_path(@photo, comment)) do |f| %>
    <%= f.hidden_field :user_id, value: current_user.id %>
    <%= f.submit "Report Inappropiate" %>
  <% end %>
<% end %> 

我建议你试试这样,看看它是否能解决你当前的问题。

【讨论】:

  • 我收到以下错误代码ActionView::Template::Error (No route matches {:action=&gt;"index", :comment_id=&gt;nil, :controller=&gt;"cflags", :photo_id=&gt;"100"} missing required keys: [:comment_id]):
  • @TimmyVonHeiss,我已经更新了我的答案。从表单中您需要一个新的Cflag 而不是评论,对吗?
  • 我仍然遇到同样的错误:ActionView::Template::Error (No route matches {:action=&gt;"index", :comment_id=&gt;nil, :controller=&gt;"cflags", :photo_id=&gt;"100"} missing required keys: [:comment_id]):
  • 您的请求似乎仍由index 操作而不是create 操作处理。虽然这不是必需的,但您可以尝试将表单方法强制为:post 并查看它是否解决了这个问题? &lt;%= form_for(Cflag.new, url: photo_comment_cflags_path(@photo, comment), html: {method: :post}) do |f| %&gt;
  • 不,同样的错误信息。我感到很困惑。当我在 form_for 中有额外的 [ ] 时收到的初始错误消息在错误消息中显示了正确的 url -> {:url=&gt;"/photos/100/comments/309/cflags"}
【解决方案3】:

你的第一个参数是数组,试试这个:

<%= form_for(comment, url: photo_comment_cflags_path(@photo, comment)) do |f| %>

【讨论】:

  • 我收到以下错误代码ActionView::Template::Error (No route matches {:action=&gt;"index", :comment_id=&gt;nil, :controller=&gt;"cflags", :photo_id=&gt;"100"} missing required keys: [:comment_id]):
猜你喜欢
  • 2017-02-13
  • 1970-01-01
  • 2017-03-23
  • 2014-03-09
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
  • 1970-01-01
相关资源
最近更新 更多