新手问题 [已解决] @comment 的 params 无法获取 :article_id

stardiviner · 2016年02月25日 · 最后由 stardiviner 回复于 2016年02月26日 · 4662 次阅读

我在 article 的 show 里显示 comments:

<%= render @article %>

<h3>Comments</h3>
<div id="comments">
  <p><%= puts "hi" %></p>
  <%= render @article.comments.all %>
  <%#= render Comment.all %>
</div>

<%#= link_to 'New Comment', new_article_comment_path(@article) %>
<%= render file: 'comments/new' %>

comment 的 partial 如下:

<%= div_for comment do %>
  <h3>
    <%= comment.name %> &lt; <%= comment.email %> &gt; said:
    <span class="actions">
      <%= link_to 'Delete', [@article, comment], confirm: 'Are you sure?', method: :delete %>
    </span>
  </h3>
  <%= comment.body %>
<% end %>

-- UPDATE --

这是 comment 的 new.html.erb

<%= form_for([@article, @article.comments.new]) do |f| %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.text_field :email %>
  </div>
  <div class="field">
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </div>
  <div class="actions">
    <%= f.submit 'Add' %>
  </div>
<% end %>

route 里设定了 nested resources:

resources :articles do
  resources :comments  
end

下面是 comments 的 controller:

class CommentsController < ApplicationController
  before_action :load_article

  def create
    @comment = Comment.new(comment_params)
    if @comment.save
      redirect_to @article, notice: 'Thanks for your comment.'
    else
      redirect_to @article, alert: 'Unable to add comment.'
    end
  end

  def destroy
    @comment = @article.comments.find(params[:article_id])
    @comment.destroy
    redirect_to @article, notice: 'Comment deleted.'
  end

  private

  def load_article
    @article = Article.find(params[:article_id])
  end

  def set_comment
    @comment = @article.comments.find(params[:article_id])
  end

  def comment_params
    params.require(:comment).permit(:article_id, :name, :email, :body)
  end
end

创建 comment 的 migration: ( :article_id 在这里面)

class CreateComments < ActiveRecord::Migration
  def change
    create_table :comments do |t|
      t.integer :article_id
      t.string :name
      t.string :email
      t.text :body

      t.timestamps null: false
    end
  end
end

-- UPDATE2 --

下面是 model 添加的关联:

class Article < ActiveRecord::Base
  validates_presence_of :title, :body

  belongs_to :user
  has_many :comments
  has_and_belongs_to_many :categories

  scope :published, lambda { where("articles.published_at IS NOT NULL") }
  scope :draft,     lambda { where("articles.published_at IS NULL") }
  # scope :recent,    lambda { published.where("articles.published_at > ?", 1.week.ago.to_date) }
  scope :where_title, lambda { |term| where("articles.title LIKE ?", "%#{term}%") }
end
class Comment < ActiveRecord::Base
  validates_presence_of :name, :email, :body

  belongs_to :article

  # create a custom validator.
  validate :article_should_be_published

  def article_should_be_published
    errors.add(:article_id, "is not published yet") if article && !article.published?
  end

  # create a callback.
  after_create :notify_article_author

  def notify_article_author
    # ActionMailer::Base.new("")
  end
end

以及 rails server 的输出:

Started GET "/articles/1" for ::1 at 2016-02-25 22:41:50 +0800
Processing by ArticlesController#show as HTML
  Parameters: {"id"=>"1"}
  Article Load (0.4ms)  SELECT  "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT 1  [["id", 1]]
  Rendered articles/_article.html.erb (2.1ms)
hi
  Comment Load (0.2ms)  SELECT "comments".* FROM "comments" WHERE "comments"."article_id" = ?  [["article_id", 1]]
  Rendered collection (0.0ms)
  Rendered comments/new.html.erb (5.8ms)
  Rendered articles/show.html.erb within layouts/application (23.8ms)
Completed 200 OK in 106ms (Views: 96.1ms | ActiveRecord: 0.6ms)


Started GET "/__meta_request/3d47f720-8933-4f70-b1f1-fb67b5c538e7.json" for ::1 at 2016-02-25 22:41:50 +0800


Started GET "/__meta_request/a69162b6-c9a9-4190-8735-57cc295c8964.json" for ::1 at 2016-02-25 22:41:50 +0800

问题是我在添加 comment 后,article 的 show action 无法显示 comments。 我用 chrome 的 rails 插件查看,好像 comment save 的时候没有得到 :article_id ,是 nil. 求大神帮忙找找原因。

你的 form 长成啥样?

@qinfanpeng 已添加 form 的代码,在 --UPDATE-- 下面

model 里面加 关联没?

@pathbox 加了。我添加代码道 -- UPDATE2 -- 里去。

你的 form 和 controller 里都没将二者关联起来,建议在 controller 里修改 @comment = Comment.new(comment_params) ---> @comment = @articile.comments.new(comment_params)

当然了,还是要系统地看书才行。

@qinfanpeng 我修改后还是没有显示添加的 comment。而且提示 "Unable to add comment". 是无法添加 comment,我查看了 rails server 的输出:

Processing by CommentsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"VG73qck/3VCTMRhZpWK3JZg4I5jo0BCzeaZvPzbMjPT0eOWMS+zZZ5tsLCXWi/LXcSaWbjhBg1dEdyMj39y4HA==", "comment"=>{"name"=>"Tucker Freeman", "email"=>"[email protected]", "body"=>"Voluptas tempora sunt, eius est in laboriosam, ut id, atque vitae elit, in sed architecto debitis dolor voluptatibus quaerat sit."}, "commit"=>"Add", "article_id"=>"1"}
  Article Load (0.2ms)  SELECT  "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT 1  [["id", 1]]
   (0.2ms)  begin transaction
   (0.2ms)  rollback transaction
Redirected to http://localhost:3000/articles/1
Completed 302 Found in 31ms (ActiveRecord: 0.6ms)

没看出什么端倪。我查看了 Comment.all 有之前添加的 comment,但是都没有 :article_id. 为啥改了代码之后就无法添加 comment 了呢?

你要去看看 @comment.errors 里到底有啥。

@stardiviner 有项目地址的话能否提供一下 thx

根据 @qinfanpeng 所提示的 @comment.erros,我找到了错误在 comment 的 model 里,于是看了代码,发现错误在 validate :article_should_be_published.

#9 楼 @stardiviner 你嘚自己看看article_should_be_published的情况,另外我好奇的是 comment 的错误为何会来源于名为article_should_be_published的验证。

@qinfanpeng 再次多谢 hint,我找出为啥了,因为 article 用错了,应该用 instance variable @article, @article.published? 问题真正解决了。 下面是在 article model 中的代码片段 published? 定义。

scope :published, lambda { where("articles.published_at IS NOT NULL") }
  scope :draft,     lambda { where("articles.published_at IS NULL") }
  # scope :recent,    lambda { published.where("articles.published_at > ?", 1.week.ago.to_date) }
  scope :where_title, lambda { |term| where("articles.title LIKE ?", "%#{term}%") }
需要 登录 后方可回复, 如果你还没有账号请 注册新账号