简体   繁体   English

HABTM或在Rails 3中具有多次通过模型设计

[英]HABTM or Has Many Through Model design in Rails 3

I am designing a certification model for the following purpose. 我正在设计用于以下目的的认证模型。 A user will have a set of certifications say [A,B,C,D]. 用户将获得一组证明,例如[A,B,C,D]。 An article will have a set of certifications as well, say [B,D]. 文章也将具有一组认证,例如[B,D]。 I want to be able to find articles where their certifications are some subset (read: any subset) of a user's certifications. 我希望能够找到其认证是用户认证的某些子集(阅读为:任何子集)的文章。 That is, if the article were to have certs [A,B,E] it would not be returned but if it had [A] or [A,D] or whatever it would return fine. 也就是说,如果商品要具有证书[A,B,E],则不会退货,但是如果商品具有[A]或[A,D],则它会退还罚款。 Really the way I envision doing it is taking the user.certs intersection with art.certs and ensuring the resulting set equals art.certs.size. 实际上,我设想的做法是将user.certs与art.certs相交,并确保结果集等于art.certs.size。 I implemented this as a HABTM as I dont really need to access the join object, but am having trouble working out the logic. 我确实将其实现为HABTM,因为我确实不需要访问联接对象,但是在制定逻辑时遇到了麻烦。 I ended up doing something like this: 我最终做了这样的事情:

@certs = @user.certifications.collect{|c| c.id}
Article.all(:joins=>:certifications, 
         :group=>Article.attributes_for_sql, 
         :select=>'articles.*', 
         :conditions => ['certifications.id in (?)', @certs], 
         :having=> "count(articles.id)=(select (count(article_id)) from articles_certifications where article_id = articles.id group by article_id)")

This seems to work but is exceedingly ugly. 这似乎可行,但是非常丑陋。

In any case, how should I design this relationship to make this as easy as possible and what would an example solution look like? 无论如何,我应该如何设计这种关系以使其尽可能简单,示例解决方案将是什么样?

Thanks for any help, I have really been banging my head against the wall on this one. 感谢您的任何帮助,我真的一直把头撞在墙上。

OK, having clarified the situation a bit, here's my official attempt at an answer, :D OK,已经澄清了一些情况,这是我的官方尝试答案:D

From what I gather, you want articles with all the certifications the user has. 根据我的收集,您需要具有用户所有认证的文章。 The certifications are the same record across models so IDs should work fine. 各个型号的认证记录相同,因此ID应该可以正常工作。

Why not try a simple IN statement, like this: 为什么不尝试一个简单的IN语句,像这样:

@user_certs = @user.certifications.all(:select => "id")
Article.all(:conditions => ["certification_id IN ?", @user_certs])

This should pull back any article that has the same certification as the user you're looking at. 这应该撤回所有与您要查找的用户具有相同认证的文章。

I hope I've grokked your question. 希望我能回答您的问题。

The idea is to drop from query all articles which have certificates the user doesn't have. 想法是从查询中删除所有具有用户没有证书的文章。 The SQL is pretty straitforward: SQL是相当严格的:

SELECT *
FROM articles a
WHERE NOT EXISTS
    (SELECT NULL
    FROM articles_certificates ac
    WHERE ac.article_id = a.id AND ac.certificate_id NOT IN
        (SELECT cu.certificate_id
        FROM certificates_users cu INNER JOIN users u ON cu.user_id = u.id
        WHERE u.id = #{user_id})
    )

I'm not an expert in ActiveRelations query, so my query resembles my SQL very much :), sorry 我不是ActiveRelations查询的专家,所以我的查询与SQL非常相似:),对不起

Article.joins(:certificates).
    all(:conditions => "NOT EXISTS (SELECT NULL FROM articles_certificates WHERE articles_certificates.certificate_id NOT IN ? AND articles.id = articles_certificates.article_id)", #{user.certificates})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM