У меня есть древовидная модель, в которой в всех ситуациях, кроме одной, я хочу ограничить результаты так, чтобы возвращались только корни.
class Licence < ActiveRecord::Base
default_scope :conditions => { :parent_licence_id, nil }
belongs_to :parent_licence, :class_name => 'Licence'
has_many :nested_licences, :class_name => 'Licence',
:foreign_key => 'parent_licence_id', :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :licences
end
Использование default_scope
показалось отличной идеей, потому что различные модели, которые связаны с License (их около 4), а также любой код, использующий find (), не должны делать ничего особенного. Причина, по которой это не прекрасная идея, заключается в том, что область действия по умолчанию также применяется к has_many
, что приводит к тому, что дочерние элементы никогда не обнаруживаются. Но has_many
- это единственное место, которое нужно вырвать из области видимости, поэтому, что касается поведения "по умолчанию", я думаю, что это default_scope
вполне разумно.
Так есть ли хороший способ обойти эту конкретную проблему?
Вот тот, который мне не очень нравится, потому что он использует SQL для почти тривиального запроса:
has_many :nested_licences, :class_name => 'Licence', :dependent => :destroy,
:finder_sql => 'SELECT l.* FROM licences l WHERE l.parent_licence_id = #{id}',
:counter_sql => 'SELECT COUNT(l.*) FROM licences l WHERE l.parent_licence_id = #{id}'
В качестве альтернативы, есть ли способ применить именованную область видимости к ассоциации из модели? например что-то вроде этого бессмысленного кода:
class Licence < ActiveRecord::Base
named_scope :roots, :conditions => { :parent_licence_id, nil }
belongs_to :parent_licence, :class_name => 'Licence'
has_many :nested_licences, :class_name => 'Licence',
:foreign_key => 'parent_licence_id', :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :licences, :scope => :roots # a :scope option doesn't really exist
end
Я знаю, что тоже могу это сделать:
class Licence < ActiveRecord::Base
named_scope :roots, :conditions => { :parent_licence_id, nil }
belongs_to :parent_licence, :class_name => 'Licence'
has_many :nested_licences, :class_name => 'Licence',
:foreign_key => 'parent_licence_id', :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :licences, :conditions => { :parent_licence_id, nil }
end
Но это действительно не очень СУХОЕ. На самом деле необходимость выполнять каждый запрос через Licence.roots.find()
вместо Licence.find()
тоже не очень СУХОЙ, если честно. Он просто просит об ошибке, когда область не используется.