ActiveRecord奇怪的行为" PG :: UndefinedColumn"用于包含两个users_id

时间:2016-06-16 09:21:38

标签: ruby-on-rails activerecord database-design

我正在使用ActiveRecord面对一个奇怪的行为。首先,这是我的数据库架构:

enter image description here

这是我的schema.rb文件:

ActiveRecord::Schema.define(version: 20160612080318) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "conversations", force: :cascade do |t|
    t.integer  "user1_id"
    t.integer  "user2_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  add_index "conversations", ["user1_id"], name: "index_conversations_on_user1_id", using: :btree
  add_index "conversations", ["user2_id"], name: "index_conversations_on_user2_id", using: :btree

  create_table "interests", force: :cascade do |t|
    t.string   "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "matches", force: :cascade do |t|
    t.integer  "user1_id"
    t.integer  "user2_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  add_index "matches", ["user1_id"], name: "index_matches_on_user1_id", using: :btree
  add_index "matches", ["user2_id"], name: "index_matches_on_user2_id", using: :btree

  create_table "messages", force: :cascade do |t|
    t.text     "content"
    t.integer  "conversation_id"
    t.integer  "user_id"
    t.datetime "read_at"
    t.datetime "created_at",      null: false
    t.datetime "updated_at",      null: false
  end

  add_index "messages", ["conversation_id"], name: "index_messages_on_conversation_id", using: :btree
  add_index "messages", ["user_id"], name: "index_messages_on_user_id", using: :btree

  create_table "user_interests", force: :cascade do |t|
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
    t.integer  "user_id"
    t.integer  "interest_id"
  end

  create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.inet     "current_sign_in_ip"
    t.inet     "last_sign_in_ip"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
    t.string   "first_name"
    t.string   "last_name"
    t.integer  "age"
    t.string   "avatar_url"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree

  add_foreign_key "messages", "conversations"
  add_foreign_key "messages", "users"
  add_foreign_key "user_interests", "interests"
  add_foreign_key "user_interests", "users"
end

为了测试我的模型,我已将这些行添加到seed.rb文件中:

    sarah = User.create!(email: "sarah@happenstance.co", password: "azertyuiop", first_name: "sarah", avatar_url: "http://i.imgur.com/jOGeCVC.jpg")
    alexandre = User.create!(email: "alexandre@happenstance.co", password: "azertyuiop", first_name: "Alexandre", avatar_url: "http://i.imgur.com/2jFvkJu.jpg")
    happbot = User.create!(email: "happbot@happenstance.co", password: "azertyuiop", first_name: "Happbot", avatar_url: "https://pbs.twimg.com/profile_images/659236694575616000/aF21-Wxz.jpg")
    lisa = User.create!(email: "lisa@happenstance.co", password: "azertyuiop", first_name: "Lisa", avatar_url: "https://ph-avatars.imgix.net/175314/original?auto=format&fit=crop&crop=faces&w=220&h=220")

    c1 = Conversation.create!(user1: yoann, user2: sarah)
    c2 = Conversation.create!(user1: yoann, user2: alexandre)
    c3 = Conversation.create!(user1: yoann, user2: happbot)
    c4 = Conversation.create!(user1: sarah, user2: alexandre)
    c5 = Conversation.create!(user1: sarah, user2: happbot)
    c6 = Conversation.create!(user1: alexandre, user2: happbot)
    c7 = Conversation.create!(user1: yoann, user2: lisa)

    m1 = Message.create!(user: yoann, conversation: c1, content: "Hey")
    m2 = Message.create!(user: yoann, conversation: c2, content: "Hello")
    m3 = Message.create!(user: yoann, conversation: c3, content: "What's up?")
    m4 = Message.create!(user: sarah, conversation: c1, content: "Salut Yoann")
    m5 = Message.create!(user: alexandre, conversation: c2, content: "Yo!")
    m6 = Message.create!(user: happbot, conversation: c3, content: "Tu peux pas test")
    m7 = Message.create!(user: sarah, conversation: c4, content: "Salut alexandre")
    m8 = Message.create!(user: sarah, conversation: c5, content: "Salut Happbot")
    m9 = Message.create!(user: alexandre, conversation: c6, content: "Hey!")
    m10 = Message.create!(user: alexandre, conversation: c4, content: "Hello")
    m11 = Message.create!(user: happbot, conversation: c5, content: "Quoi de neuf ?")
    m12 = Message.create!(user: happbot, conversation: c6, content: "Tu fais quoi demain ?")
    m12 = Message.create!(user: yoann, conversation: c7, content: "Yo!")

    i1 = Interest.create!(name: "books")
    i2 = Interest.create!(name: "music")
    i3 = Interest.create!(name: "coffee")

    UserInterest.create!(user: yoann, interest: i1)
    UserInterest.create!(user: yoann, interest: i2)
    UserInterest.create!(user: yoann, interest: i3)

    Match.create!(user1: yoann, user2: lisa)

对于第一个rake db:seed,一切都运作良好但如果我想添加一个匹配并执行另一个rake db:seed,我会遇到此错误:

rake aborted!
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column matches.user_id does not exist
LINE 1: SELECT "matches".* FROM "matches" WHERE "matches"."user_id" ...
                                                ^
HINT:  Perhaps you meant to reference the column "matches.user1_id" or the column "matches.user2_id".
: SELECT "matches".* FROM "matches" WHERE "matches"."user_id" = $1
/Users/yolo/code/happenstance-app/db/seeds.rb:1:in `<top (required)>'
-e:1:in `<main>'
PG::UndefinedColumn: ERROR:  column matches.user_id does not exist
LINE 1: SELECT "matches".* FROM "matches" WHERE "matches"."user_id" ...
                                                ^
HINT:  Perhaps you meant to reference the column "matches.user1_id" or the column "matches.user2_id".
/Users/yolo/code/happenstance-app/db/seeds.rb:1:in `<top (required)>'
-e:1:in `<main>'
Tasks: TOP => db:seed
(See full trace by running task with --trace)

这是我的user.rb文件:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  has_many :user_interests, dependent: :destroy
  has_many :interests, through: :user_interests, dependent: :destroy
  has_many :messages, dependent: :destroy
  has_many :matches, dependent: :destroy

  def conversations
    Conversation.includes(:messages)
                .where("user1_id = :id OR user2_id = :id", id: id)
                .order("messages.created_at DESC")
  end

  def other_user(conversation)
    conversation.users.include?(self) ? conversation.other_user(self) : nil
  end

  def unread_conversations
    conversations.select { |c| c.unread_messages?(self) }
  end

  def unread_conversations_count
    unread_conversations.count
  end

  def unread_conversations?
    unread_conversations_count > 0
  end

  def one_avatar_url
    avatar_url ? avatar_url : "http://placehold.it/64x64"
  end
end

我的match.rb文件:

class Match < ActiveRecord::Base
    belongs_to :user1, class_name: "User"
    belongs_to :user2, class_name: "User"

end

我已经检查了很多答案,但我真的没有看到我的架构或模型出了什么问题。

非常感谢你的帮助!

2 个答案:

答案 0 :(得分:0)

您需要在Match模型中添加foreign_keys,以便ActiveRecord知道哪个用户通过哪个foreign_key。

class Match < ActiveRecord::Base
    belongs_to :user1, class_name: "User", foreign_key: "user1_id"
    belongs_to :user2, class_name: "User", foreign_key: "user2_id"

end

答案 1 :(得分:0)

您必须告诉Rails哪些外键用于has_many :matches, dependent: :destroy模型中的User。默认情况下,这被认为是小写的这个类的名称和后缀“_id”。因此,生成User关联的has_many类会将user_id用作默认:foreign_key。但是你没有user_id,而是user1_iduser2_id

这个AR sql很清楚。

LINE 1: SELECT "matches".* FROM "matches" WHERE "matches"."user_id" ...

我不知道你的用例,但任何一个都会解决这个问题:

has_many :matches, dependent: :destroy, foreign_key: :user1_id
# or
has_many :matches, dependent: :destroy, foreign_key: :user2_id