2013-08-22 20 views
0

我有以下SQL查询:Rails的ActiveRecord的连接查询的条件

SELECT campaigns.* , campaign_countries.points, offers.image 
FROM campaigns 
JOIN campaign_countries ON campaigns.id = campaign_countries.campaign_id 
JOIN countries ON campaign_countries.country_id = countries.id 
JOIN offers ON campaigns.offer_id = offers.id 
WHERE countries.code = 'US' 

这工作得很好。我想它的轨道的活动记录版本的一些事情,如:

Campaign.includes(campaign_countries: :country).where(countries: {code: "US"}) 

上面的代码运行或多或少正确的查询(没有尝试,包括报价表),问题是返回的结果是运动的集合对象,因此这显然不包括点

我的表是:

campaigns --HAS_MANY--< campaign_countries --BELONGS_TO--< countries 
campaigns --BELONGS_TO--> offers 

写这个SQL的AR版本有什么建议?我不想在我的代码中使用SQL语句。

回答

0

如果您有活动,您可以使用campaign.campaign_countries获取关联的campaign_countries,并从中获取积分。

> campaign.campaign_countries.map(&:points) 
=> [1,2,3,4,5] 

同样您将能够从优惠关系中获得图片。

编辑:

好吧,我想现在我知道发生了什么事。您可以使用joinsselect从连接表中获取附加字段的对象。

cs = Campaign.joins(campaign_countries: :country).joins(:offers).select('campaigns.*, campaign_countries.points, offers.image').where(countries: {code: "US"}) 

你可以通过自己的名字Campaign对象

cs.first.points 
cs.first.image 

但可以肯定比引用其他字段,额外的列名不与一些主表的字段或对象的方法重叠。

编辑2:

一些调查研究后,我来到了结论,我的第一个版本是针对这种情况实际上是正确的。我将使用我自己的控制台作为例子。

> u = User.includes(:orders => :cart).where(:carts => { :id => [5168, 5167] }).first 
> u.orders.length # no query is performed 
=> 2 
> u.orders.count # count query is performed 
=> 5 

,所以当你在国内使用includes与条件,在campaign_countries只存储campaign_countries是满足您的条件。

+0

我需要的积分只针对国家 – Rakesh

+0

我认为我的答案现在应该满足您,但这不是我想的Railish方式。 –

+0

现在(第二次编辑后)我很确定这是你在找什么 –

0

试试这个:

Campaign.joins([{ :campaign_countries => :countries}, :offers]).where('`countries`.`code` = ?', "US") 
+0

加入时出现的结果与包含 – Rakesh

+1

两者不同。 Checkout [rails-include-vs-joins](http://stackoverflow.com/questions/1208636/rails-include-vs-joins)和[railscast](http://railscasts.com/episodes/181-include- VS-联接) – manoj2411

1

我一些如何得到这个工作没有SQL,但肯定它的穷人的解决方案:

在我的控制器

我:

campaigns = Campaign.includes(campaign_countries: :country).where(countries: {code: country.to_s}) 
render :json => campaigns.to_json(:country => country) 

在战役模式:

def points_for_country country 
    CampaignCountry.joins(:campaign, :country).where(countries: {code: country}, campaigns: {id: self.id}).first 
    end 

    def as_json options={} 
    json = { 
     id: id, 
     cid: cid, 
     name: name, 
     offer: offer, 
     points_details: options[:country] ? points_for_country(options[:country]) : "" 
    } 
    end 

和campaign_countries模型:

def as_json options={} 
    json = { 
     face_value: face_value, 
     actual_value: actual_value, 
     points: points 
    } 
    end 

为什么这不是很好的解决方案?因为它会调用太多的查询: 1.它执行第一次加入时调用查询以获取特定于国家/地区的活动列表 2.对于在第一个查询中找到的每个活动,它将在campaign_countries表上调用另一个查询以获取运动和国家。

这是坏的,坏的和坏的解决方案。任何建议,以改善这一点?