Rails 切换布尔值

Posted

技术标签:

【中文标题】Rails 切换布尔值【英文标题】:Rails switch boolean value 【发布时间】:2021-09-02 03:03:21 【问题描述】:

我的模型“评论”有布尔值 - 最好,它可以是真假。这是我的控制器 cmets_controller.rb 的一部分:

class CommentsController < ApplicationController
  

    before_action :find_comment, only: [:choose_best]
    
      def create
        @post = Post.find(params[:post_id])
        @comment = @post.comments.create(params[:comment].permit(:name, :comment, :user_id, :best))
        respond_to do |format|
          format.html  redirect_to post_path(@post) 
          format.js
        end
      end
    
      def choose_best
        @comment.choose_best!
        redirect_to post_path(@post)
      end
    
      private
    
      def find_comment
        @post = Post.find(params[:post_id])
        @post_id = @post[:post_id]
        @comment = @post.comments.find(params[:id])
      end
    
    end

这里是comment_model.rb:

class Comment < ApplicationRecord
      belongs_to :post
    
      scope :best_comments,     ->  where(best: true) 
      scope :not_best_comments, ->  where(best: false) 
    
      def choose_best!
          ActiveRecord::Base.transaction do
            unless best?
              post.comments.update_all(best: false)
              update!(best: true)
            end
          end
        end
    end

这里是路线:

resources :posts do
    resources :comments do
      resources :answers
      member do
        patch :choose_best
      end
    end
  end

这里是html:

<div id="post-id" data-post-id="<%= @post_id %>"> </div>
       <% if @comment.best? %>
          <h1>best</h1>
          <% else %>
          <h1>not best</h1>
          <% end %>
        <%=link_to 'Best', choose_best_post_comment_path(comment.post, comment), method: :patch, remote: true,
                   class: 'best-answer-btn btn btn-success', id: "best-comment-link-#comment.id"%>
</div>

这是我的 js 文件以获得最佳评论:

<% if @comment.best? %>
$('.comments').html('<%= j render 'posts/form', post: @post.comment %>');
$('.comment-form').on('click', function (e) 
    e.preventDefault();
    $(this).hide();
    var comment_id = $(this).parents('.comment').data('commentID');
    $('#best-comment-link-' + comment_id).hide();
)
<% end %>

所以问题是,当我按下“最佳”按钮时 - 它会切换此评论的布尔值,但当我尝试按下此按钮时,没有任何变化。我试图让 def 只保留每个帖子的最佳评论(用户按下“最佳”按钮,另一个最佳评论值变为假,按下变为真),所以问题可能出在此。

【问题讨论】:

【参考方案1】:

一个更好的解决方案是简单地在帖子表中添加一个额外的外键列:

class AddBestCommentToPosts < ActiveRecord::Migration[6.1]
  def change
    add_reference :posts, :best_comment, null: true, foreign_key:  to_table: :posts 
  end
end
class Post
  has_many :comments
  belongs_to :best_comment, 
    class_name: 'Comment', 
    optional: true
end
def choose_best
  if @post.update(best_comment: @comment)
    head :ok
  else
    head :unprocessable_entity
  end
end

由于这是一个单独的列,您不必担心一个以上的评论可能同时具有“最佳”标志的极端情况。您还可以非常有效地预先加载关联。

【讨论】:

以上是关于Rails 切换布尔值的主要内容,如果未能解决你的问题,请参考以下文章

Rails:我如何验证某个东西是布尔值?

Rails 3 SQLite3 布尔值 false

Rails 数据库布尔值

将 :default => true 添加到现有 Rails 列中的布尔值

Rails 4 的 best_in_place gem 复选框问题(为啥字符串没有转换为布尔值?)

使用 ruby​​ on rails 将布尔值保存到 postgres 数据库