【问题标题】:Ruby on Rails / How to automatically add foreign key to my "comment" model?Ruby on Rails / 如何自动将外键添加到我的“评论”模型中?
【发布时间】:2023-04-03 15:13:02
【问题描述】:

我生成了 3 个模型:“用户”、“文章”和“评论”,“评论”模型有外键“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

cmets_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 添加到 cmets 表中。但这不是一个好方法。

<% @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 %>

【问题讨论】:

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


    【解决方案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
    

    #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
    

    【讨论】:

    • 您应该将它用于您的表单(考虑到您使用的是我建议的嵌套路由):&lt;%= form_for[:articles, @comment] do |f| %&gt;
    • F:/RailsProject/project/gamespace/app/views/cmets/_comment_form.html.erb:2:语法错误,意外的keyword_do_block,期待keyword_end ...orm_for[:articles, @comment]做 |f| @output_buffer.safe_conc ... ... ^ F:/RailsProject/project/gamespace/app/views/cmets/_comment_form.html.erb:13:语法错误,意外的keyword_ensure,期待$end
    • 嗯 - 你能用你的新表单代码更新你的问题吗?
    • 没问题!代码看起来不错(也许你可以在&lt;%= form_for [:admin, @comment] 之间尝试一个空格。你确定你已经正确定义了@comment 吗?
    • 好的,我做对了
    【解决方案2】:

    你需要的东西

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

    使用&lt;&lt; 代替=
    阅读thisabout has_many

    【讨论】:

      猜你喜欢
      • 2014-08-19
      • 2016-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-19
      相关资源
      最近更新 更多