Model.find() 调用不同的模型

Model.find() calling a different model

我有3个模特用户,微博,点赞

我关注了 Ruby Michael Hartl 的 Rails 教程 https://rails-4-0.railstutorial.org/book

现在我正在添加新功能并尝试添加一个赞按钮,但经过一些更改后我的微博删除按钮现在不起作用。

#micropost_controller   
def destroy
        Micropost.find(params[:id]).destroy
        redirect_to root_url
      end

#_micropost.html.erb
<%= link_to "delete", micropost, method: :delete,
                                   data: { confirm: "You sure?" },
                                   title: micropost.content %>

即使我正在调用 Micropost.find Active Record 搜索喜欢 table 并给出错误

ActiveRecord::StatementInvalid in MicropostsController#destroy
SQLite3::SQLException: no such column: likes.micropost_id: SELECT "likes".* FROM "likes" WHERE "likes"."micropost_id" = ?

当我尝试删除用户时会发生类似的事情。所以基本上无论我试图调用它的哪个销毁都会被重定向到类似模型

PS: 执行

后出现问题
ActiveRecord::Base.connection.execute("BEGIN TRANSACTION; END;")

因为我得到 BusyException: database is locked: commit transaction

型号

#like.rb
class Like < ApplicationRecord
    belongs_to :microposts, optional: true
    belongs_to :users, optional: true
    validates :src_user_id, presence: true
    validates :des_user_id, presence: true
    validates :post_id, presence: true
end


#micropost.rb
class Micropost < ActiveRecord::Base
  belongs_to :user
  default_scope -> { order('created_at DESC') }
  validates :content, presence: true, length: { maximum: 140 }
  validates :user_id, presence: true
  has_many :likes, dependent: :destroy

  # Returns microposts from the users being followed by the given user.
  def self.from_users_followed_by(user)
    followed_user_ids = "SELECT followed_id FROM relationships
                         WHERE follower_id = :user_id"
    where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
          user_id: user.id)
  end

  def self.search(search)
    where("content LIKE ?", "%#{search}%")
  end

end


#user.rb
class User < ActiveRecord::Base

  has_many :microposts, dependent: :destroy

  has_many :relationships, foreign_key: "follower_id", dependent: :destroy
  has_many :followed_users, through: :relationships, source: :followed
  has_many :reverse_relationships, foreign_key: "followed_id",
                                 class_name:  "Relationship",
                                 dependent:   :destroy
  has_many :followers, through: :reverse_relationships, source: :follower

  has_many :likes, foreign_key: "src_user_id", dependent: :destroy
  has_many :liked_by_users, through: :likes, source: :likes

  scope :starts_with, -> (name) { where("name like ?", "#{Example User}%")}

  before_save { self.email = email.downcase }
  before_create :create_remember_token
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }, unless: Proc.new { |user| user.password.nil? }
  validates :password_confirmation, presence: true, unless: Proc.new { |user| user.password.nil? }
  validates :birthday, presence: true
  validate :email_verification, on: :update

end

正确的联想是

#user.rb

has_many :microposts, dependent: :destroy
has_many :likes, through: :microposts, foreign_key: "post_id"


#micropost.rb
belongs_to :user
has_many :likes, dependent: :destroy, foreign_key: "post_id"


#like.rb
belongs_to :micropost, optional: true

这之后就正常了

class User
  has_many :microposts, dependent: :destroy
   # You never have to specify foreign key for indirect assocations
  has_many :likes, through: :microposts
end

class Micropost
  belongs_to :user
  has_many :likes, dependent: :destroy, foreign_key: "post_id"
end


class Like
  # You must specify the foreign key if it cannot be derived from the name of the association
  # `belongs_to :micropost` will use micropost_id
  belongs_to :micropost, optional: true, foreign_key: "post_id"
  belongs_to :user # you have to add a `likes.user_id` column
end

虽然我真的很怀疑你是否要为用户点赞和微博点赞使用相同的table/model。它真的只会让事情变得更加复杂,你最终会得到一个带有大量空值的 table 。如果这是这本书的一部分,我真的很想知道作者是怎么想的,因为它是一个非常糟糕的设计。

您可以将其设置为:

# app/models/users/like.rb
# table name is users_likes
module Users
  class Like
    belongs_to :src_user, class_name: 'User', optional: false
    belongs_to :des_user, class_name: 'User', optional: false
  end
end

class User
   has_many :likes_as_src, 
     class_name: 'Users::Like',
     foreign_key: :src_user
   has_many :likes_as_des, 
     class_name: 'Users::Like',
     foreign_key: :src_user
end

# app/models/users/like.rb
# table name is microposts_likes
module Microposts
  class Like
    belongs_to :user, optional: false
    belongs_to :micropost, optional: false, foreign_key: 'post_id'
  end
end

class User
  has_many :micropost_likes, class_name: 'Microposts::Like'
  has_many :liked_microposts, through: :micropost_likes, source: :micropost
end

这为您提供了两个具有不可空外键和良好索引的简单联接 table。它还使验证非常简单。