2013-03-04 70 views
0

我是新来的铁轨,并试图准确理解如何做关联,如果我做得正确。我已阅读rails guide on associations并搜索了网络并找到了一些资源,但我不确定。简单轨道3协会 - has_many,belongs_to和has_and_belongs_to_many

你可以在这里看到我的项目:majorfinder.com在我的应用程序将有专业,学校和职业。我希望能够为每个评论添加评论。由于我刚刚开始,我刚刚开始为专业添加评论。

这里是我的协会:

型号/ review.rb

belongs_to :user 
has_and_belongs_to_many :majors 

型号/ user.rb

has_many :reviews 

型号/ major.rb

has_and_belongs_to_many :reviews 

我第一个问题是,这是否看起来像创建协会的好方法?

我知道该怎么做在大满贯赛控制器简单的关联关系:

@reviews = Review.includes(:user) 

,并与我可以告诉检讨我的主要控制器:

<div class="row"> 
    <% @reviews.each do |review| %> 
    <div> 
     <h3><%= link_to review.review, 
     :controller => "reviews", :action => "show", :id => review.id %></h3> 
     <small>Posted on <%= review.created_at %> by 
     <a href="#"><%= review.user.profile_name %></a></small> 
    </div> 
    <% end %> 
</div> 

,但我不知道怎么样使这个连接到我正在看的特定专业。

我的评论数据库模式有review(text),user_id(integer)和major_id(integer)。

最后一个问题是,如何在主要控制器显示页面内发布与该特定主要连接的评论?

回答

1

首先,您确定要reviewsmajors之间的has_and_belongs_to_many关系吗?我假设每次审查只适用于某一个特定专业(或学校/职业),如果是一对多的关系,则您需要使用has_manybelongs_to。其次,由于您最终还想将评论添加到其他模型,因此您可能希望将其设置为polymorphic association,这样可以让您为所有其他三种模型使用相同的review模型。要做到这一点你要改变你的协会如下:

# In review.rb 
belongs_to :reviewable, polymorphic: true 

# In major.rb (and later also in school.rb and career.rb) 
has_many :reviews, as: :reviewable 

你还需要改变你的评价模型,然后让而不是有major_id属性,它有一个reviewable_idinteger属性和reviewable_typestring财产。

在如何你要显示他们而言,你可能会想包括reviewuser模型时首先加载你的专业(假设你想显示所有的评论,虽然你可能最终想要看分裂他们成页,如果有很多人):

# In majors_controller.rb (or whatever it's named) 
def show 
    @major = Major.includes(:reviews => :user).find(params[:id]) 
    ... 
在您看来,您可以将用户的 @majorreviews方法来访问他们

然后(记住,协会也add a bunch of methods到模型上做它更容易使用它们)

# In /app/views/majors/show.html.erb 
<div class="row"> 
    <% @major.reviews.each do |review| %> 
    ... 
    <% end %> 
</div> 

,或者更方便,你可以使用一个部分(如果你想显示在每个页面上以同样的方式评语列表),并使用快捷渲染的集合:

# /app/views/reviews/_review.html.erb 
<div> 
    <h3><%= link_to review.review, 
    :controller => "reviews", :action => "show", :id => review.id %></h3> 
    <small>Posted on <%= review.created_at %> by 
    <a href="#"><%= review.user.profile_name %></a></small> 
</div> 

# In /app/views/majors/show.html.erb 
<div class="row"> 
    <%= render @major.reviews %> 
</div> 
+0

非常感谢你Zaid!这非常有帮助!我遇到了一个错误:在MajorsController中的NoMethodError#显示未定义的方法'包括'为#,在我的majors_controller.rb文件中,虽然我有:def show @major = Major.find_by_slug(params [:id])。包括(:reviews =>:user)end – lflores 2013-03-05 13:57:48

+1

这是我的错,'.includes()'应该放在'.find()'之前,所以'@major = Major.includes(:reviews =>:user) .find_by_slug(params [:id])'应该工作。 – 2013-03-05 22:07:13

+0

它呢,谢谢你! – lflores 2013-03-07 02:10:09

0

至于至于这些是否是适当的关联,这一切都取决于你想要达到的目标以及这些关系在“真实”世界中的实际状况。

从它看起来像,在你的应用程序中你有用户,谁可以创建(或有)许多不同的评论,你有专业,其中每个专业可以有很多评论相关的,你有评论,其中每个单独的评论都与许多不同的专业相关(即一篇评论可以写几个不同的专业)。

这是正确的吗?如果是这样,那么你试图创建的关联似乎是合适的。

但是,我不确定你在那里的执行情况。

评论属于用户,因此它具有user_id列是合适的,但它不应该有一个major_id列(否则您将每个评论限制为仅属于一个主要)。

取而代之的是专业和评论之间的关系是通过一个连接表(例如major_reviews)进行管理的,然后它会有major_id和review_id列。你有没有创建这个连接表?

一旦您将关联设置正确,您将有权访问多个rails方法,以便在运行查询时让您的生活更轻松。

例如,为了获得给定用户的所有评论,你可以做@user.reviews。同样,要获得相关专业的个人审查,你可以做@review.majors,或获得一个给定的专业的所有评论,你可以做@major.reviews

您可以在Rails指南http://guides.rubyonrails.org/association_basics.html#the-has_and_belongs_to_many-association的第4.4.1节中看到@major@review可用方法的更多示例。

+0

我其实确实希望每个评论只涉及一个专业。这听起来像我可能已经正确设置了它。谢谢!! – lflores 2013-03-05 02:25:31

+0

在这种情况下,has_and_belongs_to_many可能不合适,正如Zaid在下面提到的,使用has_many和belongs_to来更好地使用专业和评论之间的关系。您的数据库模式已经为此设置,但您需要在模型中进行更改。 – simonb83 2013-03-05 02:50:34