2012-07-03 2 views
0

Если у меня есть следующие классыИспользование ассоциаций, таких как прицелов

class User 
    has_many :documents 
end 

class Document 
    belongs_to :user 
end 

Я хотел бы быть в состоянии сделать следующее

User.where("id > 200").documents 

, который должен генерировать SQL как

select * from documents 
join users on documents.user_id == users.id 
where users.id > 200 

но activerecord не настолько умный. Разве это необоснованно ожидать, что это возможно из коробки?

== Возможным анти DRY == решение

class User 
    has_many :documents 
    def self.documents 
     Documents.joins(:users).merge(self.scoped) 
    end 
end 

, но это не очень DRY, как это кажется копируют отношения я уже определены.

ответ

0

Попробуйте это:

Document.joins(:user).where('user.id > ?', 200) 
+0

Это будет возвращать пользователям не документы. – bradgonesurfing

+0

@bradgonesurfing Итак, вы можете изменить его. Я скучаю почитать ваш sql. – xdazz

+0

Более сложный пример. Cities.where (["name like '% me%']). Жители.where ([" id> 200 "]). Документы – bradgonesurfing

1

Нет, вы не можете сделать это с ActiveRecord. Правило большого пальца - класс, с которого вы начинаете вызывать методы, является тем, что возвращают объекты. Таким образом, User.whatever всегда будет возвращать объекты User. Это в значительной степени устраняет возможность делать то, что вы хотите.

Если вы хотите получить объекты Document, вам нужно начать запрос для них в классе Document вместо этого. Вы всегда можете определить свои пользовательские области в модели User и повторно использовать их в своей модели Document ради СУХОЙ.

class User < ActiveRecord::Base 
    scope :foo, where("users.id > 200") 
end 

class Document < ActiveRecord::Base 
    belongs_to :user 

    scope :bar, joins(:user).merge(User.foo) 
end 

Это эффективно позволяет использовать область, определенную в User (и которая зависит от пользователя) в вашей модели документа. Я бы также потребовал в этом User.where («id> 200»). Документы имеют меньший смысл, чем Document.where («users.id> 200») (объединение пропускается намеренно).

Так что я лично думаю, что вы просто пытаетесь подойти к этому вопросу с того конца :)

+0

Я понимаю, что по умолчанию я не могу этого сделать. Однако информация для этого есть. Логика ассоциации закодирована в объявлении has_many, и это позволяет вам перейти от экземпляра одного объект в коллекцию другого типа объекта.Я хотел бы знать, есть ли что-то фундаментальное, что помешает вам перейти от коллекции (активного отношения) одного типа к коллекции другого типа с помощью отношения has_many. – bradgonesurfing

+0

Без проверки в коде, я бы сказал, что «Правило большого пальца - класс, с которого вы начинаете вызывать методы, является тем, что возвращают объекты». Это одна из фундаментальных проблем. Для этого кода потребуется довольно немного изменить t o сделать его достаточно умным, чтобы иметь возможность проанализировать последнее отношение AR :: Relation и использовать его как тип объекта. Даже тогда я не согласился бы с этим, так как это затрудняло бы читаемость. User.foo ясно показывает, что вы получаете взамен. User.documents.with_foo.pages.filled.lines.bold_and_italic.letters.bar не делает :) –

0

Для примера классов вы можете просто запросить user_id поле в documents таблице:

Document.where("user_id > 200") 

 Смежные вопросы

  • Нет связанных вопросов^_^