3

User と Relations という 2 つのモデルがあります。リレーションにはユーザー間のリレーションが格納されます。リレーションにはさまざまな種類があります。現時点では、フレンドとフレンドリクエストの 2 つのタイプを実装しようとしています。

ここに私のクラスの関連付けがあります:

class Relation < ActiveRecord::Base
  belongs_to :owner, class_name: "User"
  validates :owner, presence: true
  validates :character, presence: true
end

class User < ActiveRecord::Base

  has_many :characters, dependent: :destroy
  has_many :relations, foreign_key: "owner", dependent: :destroy
  has_many :friends, -> { where reltype: "friend" }, through: :relations, source: "character"

  has_many :reverse_relations, foreign_key: "character", class_name: "Relation", dependent: :destroy
  has_many :friend_requests, -> { where reltype: "freq" }, through: :reverse_relations, source: :owner

  .
  .
  .
end

IRB で、生成されるはずの User.friends 配列を使用しようとすると、次のエラーがスローされます。

Loading development environment (Rails 4.0.0)
irb(main):001:0> user = User.find(1)
  User Load (12.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]]
=> #<User id: 1, name: "melv", email: "melv@mx.org", password_digest: "$2a$10$g3FjyVP9ya/L.j1iWAzYH.YFOjYOyxUGp3KIt6ajic
Jf...", verified: nil, reg_ip: nil, last_ip: nil, character_limit: 3, characters: nil, created_at: "2013-10-31 19:10:36"
, updated_at: "2013-11-02 11:05:14", remember_token: "4e883d6ec84b5c142882cc084c14bc101a06350f", playchar: 0>
irb(main):002:0> user.friends
ActiveRecord::HasManyThroughSourceAssociationNotFoundError: Could not find the source association(s) :character in model
 Relation. Try 'has_many :friends, :through => :relations, :source => <name>'. Is it one of :owner?
        <...stack trace...>
irb(main):003:0>

私は何か間違ったことをしていますか?


要求された私のスキーマ:

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

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

  create_table "characters", force: true do |t|
    t.integer  "accountid"
    t.string   "username"
    t.integer  "roundles"
    t.integer  "gems"
    t.integer  "rank"
    t.integer  "tier"
    t.datetime "tiertime"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "permission_ranks", force: true do |t|
    t.string   "label"
    t.integer  "badge"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "relations", force: true do |t|
    t.integer  "owner"
    t.integer  "character"
    t.string   "reltype"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "relations", ["character"], name: "index_relations_on_character", using: :btree
  add_index "relations", ["owner", "character"], name: "index_relations_on_owner_and_character", unique: true, using: :btree
  add_index "relations", ["owner"], name: "index_relations_on_owner", using: :btree

  create_table "tickets", force: true do |t|
    t.string   "title"
    t.text     "desc"
    t.integer  "sender"
    t.integer  "assigned"
    t.text     "addinfo"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "users", force: true do |t|
    t.string   "name"
    t.string   "email"
    t.string   "password_digest"
    t.boolean  "verified"
    t.string   "reg_ip"
    t.string   "last_ip"
    t.integer  "character_limit"
    t.integer  "characters"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "remember_token"
    t.integer  "playchar"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
  add_index "users", ["name"], name: "index_users_on_name", unique: true, using: :btree
  add_index "users", ["remember_token"], name: "index_users_on_remember_token", using: :btree

end
4

1 に答える 1

4

OK、問題はネーミングにあると思います。アソシエーションと列に同じ名前を付けることはお勧めできません。可能であれば、関係の列の名前を変更することから始めます。

owner     => owner_id
character => character_id

または、関連付けの名前を変更できます。

owner     => user_owner
character => user_character

私が目にするもう1つのことは、あなたの個別のキャラクターテーブルです。Your Relation モデルから文字テーブルを参照したいようですが (間違っている場合は訂正してください)、決して実行しないでください。

belongs_to :user_character, foreign_key: "character"

今あなたの主な質問に。私があなたのことを正しく理解していれば、ユーザーで定義された友達の関連付けを使用して、文字のリストを取得したいと考えています。この場合、行は次のようになります。

has_many :friends, -> { where reltype: "friend" }, through: :relations, source: "user_character", class_name: "Character"

更新しました

著者は、関連付けを通じて User モデルを参照したいと本当に思っていると説明しましたfriends

# relation.rb
belongs_to :user_character, foreign_key: "character", class_name: "User"

# user.rb
has_many :friends, -> { where reltype: "friend" }, through: :relations, source: "user_character"

更新2

関連条件に問題がありました。特に、テーブルを明示的に指定する必要があります。

has_many :friends, -> { where("relations.reltype" => "friend") }, through: :relations, source: "user_character"
于 2013-11-02T12:27:31.667 に答える