Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Aug 11th, 2012  |  syntax: None  |  size: 1.88 KB  |  hits: 5  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. Rails 3 query matching attribute of has_one association that is a subset of has_many association
  2. class Car < ActiveRecord::Base
  3.   has_many :statuses, class_name: 'CarStatus', order: "timestamp DESC"
  4.   has_one :latest_status, class_name: 'CarStatus', order: "timestamp DESC"
  5.  
  6.   delegate :location, :timestamp, to: 'latest_status', prefix: 'latest', allow_nil: true
  7.  
  8.   # ...
  9. end
  10.        
  11. loc = Car.first.latest_location   # Location object (id = 1 for example)
  12. loc.name                          # "Miami, FL"
  13.        
  14. # car.rb
  15. def self.by_location_id(id)
  16.   ids = []
  17.   find_each(include: :latest_status) do |car|
  18.     ids << car.id if car.latest_status.try(:location_id) == id.to_i
  19.   end
  20.   where("id in (?)", ids)
  21. end
  22.        
  23. def by_location_name(loc)
  24.   ids = []
  25.   find_each(include: {latest_status: :location}) do |car|
  26.     ids << car.id if car.latest_location.try(:name) =~ /#{loc}/i
  27.   end
  28.   where("id in (?)", ids)
  29. end
  30.        
  31. select *
  32. from (
  33.   select cars.id as car_id, statuses.id as status_id, statuses.location_id, statuses.created_at, row_number() over (partition by statuses.id order by statuses.created_at) as rn
  34.   from cars join statuses on cars.id = statuses.car_id
  35. ) q
  36. where rn = 1 and location_id = ?
  37.        
  38. def self.by_location(loc)
  39.   joins(
  40.     self.escape_sql('join (
  41.     select *
  42.     from (
  43.       select cars.id as car_id, statuses.id as status_id, statuses.location_id, statuses.created_at, row_number() over (partition by statuses.id order by statuses.created_at) as rn
  44.       from cars join statuses on cars.id = statuses.car_id
  45.     ) q
  46.     where rn = 1 and location_id = ?
  47.     ) as subquery on subquery.car_id = cars.id order by subquery.created_at desc', loc)
  48.   )
  49. end
  50.        
  51. class ActiveRecord::Base
  52.   def self.escape_sql(clause, *rest)
  53.     self.send(:sanitize_sql_array, rest.empty? ? clause : ([clause] + rest))
  54.   end
  55. end
  56.        
  57. def self.by_location_name(name)
  58.  loc = Location.find_by_name(name)
  59.  by_location(loc)
  60. end