2014-11-14 133 views
1

在Ruby on Rails中建立Has_Many through关系有各种参考,但关于如何处理关系的信息很少。有很多关系

我有以下变量一个用户表:

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.string "current_sign_in_ip" 
t.string "last_sign_in_ip" 
t.string "confirmation_token" 
t.datetime "confirmed_at" 
t.datetime "confirmation_sent_at" 
t.string "unconfirmed_email" 
t.string "name" 
t.datetime "created_at" 
t.datetime "updated_at" 

然后,我有一个维基表:

t.string "title" 
t.datetime "published_at" 
t.datetime "created_at" 
t.datetime "updated_at" 
t.text  "body" 

而且,我有一个关系表中加入二:

t.integer "wiki_id" 
t.integer "user_id" 
t.boolean "creator_created" 
t.boolean "collaborator" 

关系类属于其他类中的每一个:

belongs_to :users 
belongs_to :wikis 

其它两个具有的has_many,通过代码:

class User < ActiveRecord::Base 

    has_many :relationships 
    has_many :wikis, through: :relationships 

,反之亦然。

所以我的问题是,现在是什么?我怎样才能调用这些不同的类和它们的变量? user.wiki似乎不起作用,或user.relationship.wiki;即使relationship.created_creator也会提取错误信息!

特别是,我希望能够找出用户是否创建了一个wiki,以便该用户可以编辑该wiki。我试着在用户模式来创建一个方法是:

def creator?(wiki, user) 
    Relationship.where(wiki_id: wiki.id, user_id:user.id).creator_created 
end 

当我把它从一个政策文件,我得到的错误:

undefined method `creator_created' for #  <ActiveRecord::Relation::ActiveRecord_Relation_Relationship:0xbb19b84> 

谁能帮助我用我的has_many ,通过关系?我如何可以参考与用户相关的wiki,或与两者相关的creator_created字段?

谢谢!

回答

0

尝试:

Relationship.where(wiki_id: wiki.id, user_id:user.id, creator_created: true) 
2

一个has_many关系返回一个集合。 Rails使用关联名称的复数形式来访问相关对象。

要获得用户的维基,只是做:

user.wikis

要查找用户是否创建了维基,你需要使用的关系:

user.wikis.where(relationships: {creator_created: true})

这展示了如何将范围链接到关联。

这可以通过添加一个范围以Wiki模型进一步简化:

scope :creator_created, -> { where(relationships: {creator_created: true}) }

,其允许:

user.wikis.creator_created

它可以是相当有帮助的添加.to_sql到端的表达式来查看生成的SQL语句。

这在很大程度上是覆盖在滑轨指南Active Record Query Interface

EDIT

错误消息“NameError:未初始化的常数用户::维基”的发生是由于在Relationship模型错误。 belongs_to协会用单数形式指定相关模型,所以他们更改为:

belongs_to :user 
belongs_to :wiki 
+0

谢谢!不幸的是,我仍然收到错误“未初始化的常量User :: Wiki”。在Rails控制台中,我为用户(调用'User.connection'建立连接):Class“得到错误”NoMethodError:undefined method'wikis'。有任何想法吗? –

+0

我意识到我没有指定一个用户,但即使当我(User.last),我得到了错误“NameError:未初始化的常量User :: Wiki” –

+1

你是如此接近:)请参阅我的编辑。 Rails中的整个复数/单数业务非常随意。一旦你了解了惯例,它将成为第二天性。 – zetetic

0

.where(...)返回模型对象的集合

def creator?(wiki, user) 
    # Raises error, as a model instance method (creator_created) is 
    # called on a collection: 
    Relationship.where(wiki_id: wiki.id, user_id:user.id).creator_created 
end 

在上面的代码中,正在尝试调用.creator_created上的收集Relationship对象(被发现假设对象匹配给.where(...)的条件)。

.creator_created是一种方法单个Relationship对象。无法在Relationship的集合上调用它。

修改给予creator?方法考虑到这会给:

def creator?(wiki, user) 
    relationships = Relationship.where(wiki_id: wiki.id, user_id: user.id) 
    if relationships.empty? 
    raise "No matching relationships found for wiki: '#{wiki}'" 
    end 
    # Use the first element from the relationships collection 
    relationship = relationships[0] 
    relationship.creator_created 
end 

然而,因为方法的名字,我怀疑这可能是一个更可读的解决方案:

def creator?(wiki, user) 
    user.relationships.find_by(wiki_id: wiki.id).creator_created 
end 

比较.find_by(...).where(...)find_by只返回单个模型实例(如果找到匹配项)。 .find_by docs.where docs都有示例代码。

+0

嗨艾略特,谢谢你。 。 。我试过了你的最后一个def创造者?,它没有传递任何东西。在rails控制台中,我可以得到一个响应,但它表示结果为'零',即使当我询问关系记录本身时,它也会显示正确的wiki_id和user_id以及creator_created:true的记录。 –