【发布时间】:2013-11-29 17:36:18
【问题描述】:
我有一张朋友桌。它的构建类似于http://railscasts.com/episodes/163-self-referential-association。现在我想以最有效的方式获得所有关系,它们是由双方建立的(正常和反向友谊)。
在 MySQL 中应该是这样的:
SELECT * FROM Friendship as f1, Friendship as f2 WHERE f1.user_id = f2.friend_id AND f1.friend_id = f2.user_id
在railscast 的评论中,有人构建了mutual_friends 部分的扩展。但是这三行在我的情况下不起作用:
设计用户模型:
class User < ActiveRecord::Base
has_many :features
has_and_belongs_to_many :tags
has_many :friendships
has_many :friends, through: :friendships
has_many :inverse_friendships, class_name: 'Friendship', foreign_key: 'friend_id'
has_many :inverse_friends, through: :inverse_friendships, source: :user
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :first_name, :last_name, :email, :password, :date_of_birth, :gender, :password_confirmation
validates_inclusion_of :gender, :in => ['female', 'male'], message: 'Kein Geschlecht ausgewaehlt'
validates :first_name, presence: true
validates :last_name, presence: true
validates_date :date_of_birth, :on_or_before => lambda { Date.current }
def mutual_friends
inverse_friends.where('user_id in (?)', friend_user_ids)
end
end
设计用户迁移:
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
t.string :reset_password_token
t.datetime :reset_password_sent_at
t.datetime :remember_created_at
t.integer :sign_in_count, :default => 0
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
t.string :first_name
t.string :last_name
t.datetime :date_of_birth
t.string :gender
t.integer :tag_id
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
end
end
友谊模型
class Friendship < ActiveRecord::Base
attr_accessible :user_id, :friend_id
belongs_to :user
belongs_to :friend, class_name: 'User'
end
友谊迁移
class CreateFriendships < ActiveRecord::Migration
def self.up
create_table :friendships do |t|
t.integer :user_id
t.integer :friend_id
t.timestamps
end
end
def self.down
drop_table :friendships
end
end
这个解决方案的错误是:
undefined local variable or method `friend_user_ids' for #<User:0x007fcb93e86de8>
Railscast评论中的原始星座是:
朋友模型
class Friend < ActiveRecord::Base
belongs_to :profile
belongs_to :friend, :class_name => 'Profile'
end
个人资料模型
class Profile < ActiveRecord::Base
has_many :friends
has_many :friend_profiles, :through => :friends, source: :friend
has_many :friended_by, class_name: "Friend" , :foreign_key => "friend_id"
has_many :friended_by_profiles, :through => :friended_by, source: :profile
def mutual_friends
friended_by.where('profile_id in (?)', friend_profile_ids)
end
def mutual_friend_profiles
Profile.where('id in (?)', mutual_friends.pluck(:profile_id))
end
def requesting_friends
friended_by.where('profile_id not in (?)', friend_profile_ids)
end
def requesting_friend_profiles
Profile.where('id in (?)', requesting_friends.pluck(:profile_id))
end
def pending_friends
friends.where('friend_id not in (?)', friended_by_profile_ids)
end
def pending_friend_profiles
Profile.where('id in (?)', pending_friends.pluck(:friend_id))
end
end
感谢您的帮助!
【问题讨论】:
-
您显示的代码是来自 Railcast 还是您的程序?您需要发布您的代码,以便任何人能够帮助您。
-
现在是我的用户模型中的代码,抱歉之前的版本
-
仍然没有足够的信息。 User#mutual_friends 引用了friend_user_ids。它在哪里定义?您是否在迁移中将其添加到 User 类中?
-
在我的案例中没有定义它,但我无法找到,在哪里以及如何定义它。添加了有关我的星座和用户在 railscast 上发布的星座的更多信息。
标签: ruby-on-rails performance activerecord