开发者

How do I do a join in ActiveRecord after records have been returned?

I am using ActiveRecord in Rails 3 to pull data from two different tables in two different databases. These databases can not join on each other, but I have the need to do a simple join after-the-fact. I would like to preserve the relation so that I can chain it down the line.

here is a simplified version of what I am doing

browsers = Browser.all # <-- this is fairly small and can reside in memory
events = Event.where(:row_date=>Date.today).select(:name, :browser_id)

So as you can see, I want to join browsers in on the events relation, where browser_id should equal browsers.name. events is a relation and I can still add clauses to it down the line, so I dont want to run the query on the db just yet. How would I accomplish this?

Edit

For those that would like to see 开发者_C百科some code for the answer I accepted below, here is what I came up with:

class EventLog < ActiveRecord::Base
  belongs_to :browser

  def get_todays_events
    Event.where(:row_date=>Date.today).select(:name, :browser_id).includes(:browser)
  end
end

would let me get the browser name in the following manner

get_todays_events.browser.name


I would accomplish this by using an :include. Attempting to do this in Ruby will cause you nothing but grief. You can chain onto an include just fine.


joins does create SQL joins as expected in the current Rails 5:

pry(main)> Customer.joins(:orders).limit(5) Customer Load (0.2ms) SELECT `customers`.* FROM `customers` INNER JOIN `orders` ON `orders`.`customer_id` = `customers`.`id` LIMIT 5 => [#<Customer:0x007fb869f11fe8 ...

This should be vastly faster, because it only requires a single database query, whereas includes will perform 1 + <number of rows in first table> + <number of rows in second table>...

Here's an example where includes requires 1750x as long as joins:

pry(main)> benchmark do
   Order.joins(:address, :payments, :customer, :packages).all.size
> 0.02456 seconds

pry(main)> benchmark do
[14] pry(main)* Order.includes(:address, :payments, :customer, :packages).all.map(&:zip).max
[14] pry(main)*end
=> 35.607257 seconds
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜