Ruby on Rails /如何自动将外键添加到我的“评论”模型?

时间:2013-12-01 09:50:07

标签: ruby-on-rails ruby foreign-keys

我生成了3个模型:“User”,“Article”和“Comment”,而“Comment”模型有外键“user_id”和“article_id”。但是,当我想在视图中为特定文章创建评论时,我无法自动添加“article_id”。

在rails控制台中,我可以使用

成功添加它
comment = Comment.new(:content => "Great post")
comment.user = user
comment.article = Article.find(1)
comment.save

我试图在我的控制器中编写一些代码但是不起作用

articles_controller.rb

class ArticlesController < ApplicationController
  before_filter :signed_in_user, only: [:create, :destroy]
  before_filter :correct_user, only: :destroy 

  def index
    @articles = Article.all
  end

  def show
    @article = Article.find(params[:id])
    @comment = Comment.new()
  end

  def create
    @article = current_user.articles.build(params[:article])
    if @article.save
      flash[:success] = "Article created!"
      redirect_to root_url
    else
      render 'static_pages/home'
    end
  end

  def destroy
    @article.destroy
    redirect_to current_user
  end

  private
    def correct_user
      @article = current_user.articles.find_by_id(params[:id])
      redirect_to root_url if @article.nil?
    end
end

comments_controller.rb

class CommentsController < ApplicationController
  before_filter :signed_in_user, only: [:create, :destroy]
  before_filter :correct_user, only: :destroy 

  def create
    @comment = current_user.comments.build(params[:comment])
    if @comment.save
      flash[:success] = "Comment created!"
      redirect_to articles_url
    else
      render 'static_pages/home'
    end
  end

  def destroy
    @comment.destroy
    redirect_to current_user
  end

  private
    def correct_user
      @comment = current_user.comments.find_by_id(params[:id])
      redirect_to root_url if @comment.nil?
    end
end

在视图文件中 /articles/show.html文件呈现部分文件“_comment_form.html.erb”

_comment_form.html.erb

<%= form_for(@comment) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="field">
    <%= f.text_area :content, placeholder: "Compose your comment..." %>
  </div>
  <%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>

我可以添加一些新行来手动将article_id添加到comments表中。但这不是一个好方法。

<% @comment.article_id = @article.id %>
<%= form_for(@comment) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <%= f.label :article_id %>
  <%= f.text_field :article_id %>
  <div class="field">
    <%= f.text_area :content, placeholder: "Compose your comment..." %>
  </div>
  <%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>

我该怎么办? 非常感谢你。


更改了_comment_form.html.erb

# views/comments/_comment_form.html.erb

<%= form_for[:articles, @comment] do |f| %>
   <%= render 'shared/error_messages', object: f.object %>
   <div class="field">
     <%= f.text_area :content, placeholder: "Compose your comment..." %>
   </div>
   <%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>

错误:

SyntaxError in Articles#show

Showing F:/RailsProject/project/gamespace/app/views/comments/_comment_form.html.erb where line #2 raised:

F:/RailsProject/project/gamespace/app/views/comments/_comment_form.html.erb:2: syntax error, unexpected keyword_do_block, expecting keyword_end
...orm_for[:articles, @comment] do |f| @output_buffer.safe_conc...
...                               ^
F:/RailsProject/project/gamespace/app/views/comments/_comment_form.html.erb:9: syntax error, unexpected keyword_ensure, expecting $end
Extracted source (around line #2):

1: 
2:     <%= form_for[:articles, @comment] do |f| %>
3:        <%= render 'shared/error_messages', object: f.object %>
4:        <div class="field">
5:           <%= f.text_area :content, placeholder: "Compose your comment..." %>

 # comments_controller.rb
 class CommentsController < ApplicationController
  before_filter :signed_in_user, only: [:create, :destroy]
  before_filter :correct_user, only: :destroy 

  def create
    @comment = Comment.new(comment_params)
    @comment.article_id = params[:id]
    if @comment.save
      flash[:success] = "Comment created!"
      redirect_to articles_url
    else
      render 'static_pages/home'
    end
  end

  def destroy
    @comment.destroy
    redirect_to current_user
  end

  private

    def correct_user
      @comment = current_user.comments.find_by_id(params[:id])
      redirect_to root_url if @comment.nil?
    end

    def comment_params
      params.require(:comment).permit(:content).merge(:user_id => current_user.id, :article_id => params[:id])
    end 
end

错误:

TypeError in CommentsController#create

can't convert Symbol into String
Rails.root: F:/RailsProject/project/gamespace

Application Trace | Framework Trace | Full Trace
app/controllers/comments_controller.rb:33:in `comment_params'
app/controllers/comments_controller.rb:7:in `create'
This error occurred while loading the following files:
   comment
Request

Parameters:

{"utf8"=>"✓",
 "authenticity_token"=>"ybkPs+c2068AZIIqCNJz1epBtS4L1zgT/vU9LL2Fs+E=",
 "comment"=>{"content"=>"sdfadfa"},
 "commit"=>"Post",
 "article_id"=>"10"}

----------------------------------------------- --------------------------------


解决方案:

# comments_controller.rb
def create
  comment = current_user.comments.build(params[:comment])
  comment.article = Article.find(params[:article_id])
  comment.save
end

使用hidden_​​field方法

# views/_comments_form.html.erb
<%= form_for [@article, @comment] do |f| %>  
   <%= render 'shared/error_messages', object: f.object %>
   <%= f.hidden_field :article_id, :value => @article.id %>
   <div class="field">
     <%= f.text_area :content, placeholder: "Compose your comment..." %>
   </div>
   <%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>

2 个答案:

答案 0 :(得分:1)

我打算在这里写一篇很长的帖子,但我实际上同意Monk_code - 你最好将foreign_key注入新记录而不是玩弄任何技巧

#app/controllers/comments_controller.rb
def create
    comment = Comment.new(comment_params)
    comment.article_id = params[:id]
    comment.save
end

OR

#app/controllers/comments_controller.rb
def create
    comment = Comment.new(comment_params)
    comment.save
end

private
def comment_params
    params.require(:comment).permit(:content).merge(:user_id => current_user.id, :article_id => params[:id])
end

关联数据

我可以看到的问题是你的模型可能看起来像这样:

#app/models/comment.rb
Class Comment > ActiveRecord::Base
    belongs_to :article
    belongs_to :user
end

如果是这种情况,您必须记住您正在保存依赖于父模型的数据。由于它是一个依赖项,它不会自动知道外键,这意味着你必须自己分配

如果您要保存新的Article,则可以传递accepts_nested_attributes_for,甚至只需创建评论记录after_create


正确设计您的应用程序

我的解决方案是使用您可能使用的params[:id]

resources :articles do
    resources :comments
end

这意味着每个评论都会在文章的页面上创建,从而允许您在创建新记录时使用params[:id]变量


<强>更新

class CommentsController < ApplicationController
  before_filter :signed_in_user, only: [:create, :destroy]
  #before_filter :correct_user, only: :destroy 

  def new
       @comment = Comment.new
  end

  def create
    @comment = Comment.new(comment_params)
    if @comment.save
      flash[:success] = "Comment created!"
      redirect_to articles_url
    else
      render 'static_pages/home'
    end
  end

  def destroy
    @comment.destroy
    redirect_to current_user
  end

  private
    def comment_params
      params.require(:comment).permit(:content).merge(:user_id => current_user.id, :article_id => params[:article_id])
    end 
end

答案 1 :(得分:0)

你需要的东西

comment = Comment.new(:content => "Great post")
comment.user = user
comment.articles << Article.find(1)
comment.save

使用<<代替=
阅读thisabout has_many