has_many: через with: primary_key в таблице соединений не работает - PullRequest
1 голос
/ 16 июля 2011

В моем проекте на Rails 3 у меня есть пользовательская модель с самоссылочным соединением через следующую модель.Я хочу использовать эту таблицу соединений, чтобы найти действия, связанные с последующим пользователем.У меня почти все настроено правильно, за исключением того, что запрос, сгенерированный соединением, полностью игнорирует параметр: primary_key в модели соединения.

Вот соответствующая схема для соответствующих моделей:

  create_table "users", :force => true do |t|
    t.string   "email",                                 :default => "",    :null => false
    t.string   "first_name"
    t.string   "last_name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "follows", :force => true do |t|
    t.integer  "user_id"
    t.integer  "followed_user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "activities", :force => true do |t|
    t.integer  "user_id"
    t.text     "body"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

Вот ассоциации в моделях

class User < ActiveRecord::Base
    has_many :follows
    has_many :followed_users, :through => :follows
  has_many :followed_activities, :through => :follows
    has_many :activities
end
class Follow < ActiveRecord::Base
    belongs_to :user
    belongs_to :followed_user, :class_name => "User"
    has_many :followed_activities, :primary_key => :followed_user, :foreign_key => :user_id, :class_name => "Activity"
end

Следующая работа просто отлично работает:

u = User.first
u.follows # returns corresponding records from the follows table
u.followed_users # returns all users that u is following
u.followed_users.first.activities # returns all activity records corresponding to the first person the user is following
Follow.first.activities # same as the previous

Однако следующее просто возвращает пустой массив:

u.followed_activities

Вот sql, сгенерированный из последнего оператора:

  Activity Load (0.2ms)  SELECT `activities`.* FROM `activities` INNER JOIN `follows` ON `activities`.user_id = `follows`.id WHERE ((`follows`.user_id = 1))

Причина, по которой он не работает, заключается в том, что он пытается объединить использование «следует ».id в качестве первичного ключа, а не«follow'.followed_user.

Это ошибка, или мне нужно повторить объявление: primary_key где-нибудь в пользовательской модели?Я не могу найти упоминаний ни в API Rails, ни где-либо еще в сети.

Версия Rails: 3.0.7

Ответы [ 2 ]

1 голос
/ 16 июля 2011

Я нахожу, что интуитивно понятно связывать гирляндные цепочки с гемом 'nested_has_many_through', http://rubygems.org/gems/nested_has_many_through, который будет стандартной частью рельсов 3.1 и может дать вам еще один инструмент для решения проблемы здесь

Это позволит вам сделать что-то вроде этого:

class Author < User
  has_many :posts
  has_many :categories, :through => :posts, :uniq => true
  has_many :similar_posts, :through => :categories, :source => :posts
  has_many :similar_authors, :through => :similar_posts, :source => :author, :uniq => true
  has_many :posts_of_similar_authors, :through => :similar_authors, :source => :posts, :uniq => true
  has_many :commenters, :through => :posts, :uniq => true
end

class Post < ActiveRecord::Base
  belongs_to :author
  belongs_to :category
  has_many :comments
  has_many :commenters, :through => :comments, :source => :user, :uniq => true
end

Это упростило мои запросы и коллекции. Надеюсь, вы найдете ответ на свой вопрос, он сложный!

0 голосов
/ 16 июля 2011

Джастин, у вас есть 2 ассоциации под названием "follow_activities".конечно, они имеют разный контекст (разные модели), но я бы хотел попросить вас попробовать метод внутри блока ассоциации следующим образом:

has_many :followed_users, :through => :follows do
  def activities
  end
end
...