Элегантные Advanced Rails Queries - PullRequest
       2

Элегантные Advanced Rails Queries

1 голос
/ 03 августа 2010

У меня проблемы с тем, чтобы обернуть голову вокруг более продвинутых методов запросов Rails.В этом случае у меня есть три таблицы: пользователи, дружба и события.

Я настроил его следующим образом в моделях для каждого

Пользователь->: has_many =>: Friendship,: has_many =>: Items

Friendship->:own_to =>: пользователь

Событие-> Proper_to =>: пользователь

Дружба - это просто два столбца: «user_id» и «friend_id», поэтому каждая новая дружба создаст две новые строки.*

Вот запрос, который я использую, чтобы найти «первые четыре события, принадлежащие другу current_user с датой start_date позже, чем сейчас».

find_by_sql(["SELECT DISTINCT e.id
              FROM events e
              WHERE e.start_date > ?
              AND e.user_id IN(
              SELECT f.user_id
              FROM friendships f
              WHERE f.friend_id = ?)
              LIMIT 0,4", Time.zone.now,current_user.id])

Что такоеправда и элегантный способ сделать что-то подобное в Rails?У меня такое ощущение, что это тоже крайне неэффективно ...

1 Ответ

5 голосов
/ 03 августа 2010

Вы должны быть в состоянии использовать :join и :conditions

time_range = (Time.now.midnight - 4.days)..Time.now.midnight
Event.all :joins => :friendships, :conditions => 
   {'start_date' => time_range, 'friendships.friend_id' => current_user.id}, :limit => 4

На самом деле я не выполнил много сложных запросов, как это, но я собрал это воедино из примеров здесь:http://guides.rubyonrails.org/active_record_querying.html

Редактировать: Возможно, вам придется добавить к событию:

has_many :friends, :through => :friendships

Редактировать2: Похоже, вам придется использовать вложенное объединение:

Event.all :joins => {:user => :friendships }, :conditions => {'start_date' => time_range, 'friendships.friend_id' => current_user.id }

Вот код модели, который я использовал:

class User < ActiveRecord::Base
  has_many :events, :foreign_key => "user_id"
  has_many :friendships
  has_many :friends, :through => :friendships, :source => :user, :uniq => true
end

class Event < ActiveRecord::Base
  belongs_to :user
  has_many :friendships, :through => :user
end

class Friendship < ActiveRecord::Base
  belongs_to :user
end

И некоторые примеры вывода, если это вообще может быть полезно:

>> Event.all :joins => {:user => :friendships }, :conditions => {'happens_on' => time_range, 'friendships.user_id' => 1 }
Event.all :joins => {:user => :friendships }, :conditions => {'happens_on' => time_range, 'friendships.user_id' => 1 }
=> [#<Event id: 1, happens_on: "2010-08-06 00:42:37", title: "Jims party", description: "Happy Birthday", created_at: "2010-08-03 00:42:37", updated_at: "2010-08-03 00:42:37", user_id: 1>]
>> jim = User.find(1)
jim = User.find(1)
=> #<User id: 1, name: "Jim", bio: "Loves Rails", age: 30, created_at: "2010-08-03 00:30:51", updated_at: "2010-08-03 00:30:51">
>> crystal = User.find(2)
crystal = User.find(2)
=> #<User id: 2, name: "Crystal", bio: "Loves writing", age: 26, created_at: "2010-08-03 00:31:14", updated_at: "2010-08-03 00:31:14">
>> jim.events
jim.events
=> [#<Event id: 1, happens_on: "2010-08-06 00:42:37", title: "Jims party", description: "Happy Birthday", created_at: "2010-08-03 00:42:37", updated_at: "2010-08-03 00:42:37", user_id: 1>]
>> event1 = jim.events[0]
event1 = jim.events[0]
=> #<Event id: 1, happens_on: "2010-08-06 00:42:37", title: "Jims party", description: "Happy Birthday", created_at: "2010-08-03 00:42:37", updated_at: "2010-08-03 00:42:37", user_id: 1>
>> event1.user
event1.user
=> #<User id: 1, name: "Jim", bio: "Loves Rails", age: 30, created_at: "2010-08-03 00:30:51", updated_at: "2010-08-03 00:30:51">
>> event1.friendships
event1.friendships
=> [#<Friendship user_id: 1, friend_id: nil, created_at: "2010-08-03 00:57:31", updated_at: "2010-08-03 00:57:31">]
>> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...