我喜欢 Rails 的部分原因是我讨厌 SQL——我认为它更像是一种汇编语言,应该使用 ActiveRecord 等更高级的工具来操作。然而,我似乎已经达到了这种方法的极限,而且我对 SQL 的理解不够深入。
我有一个包含很多子记录的复杂模型。我还有一组 30-40 个 named_scopes 来实现来自客户端的业务逻辑。这些范围有条件地链接在一起,这就是为什么我有这些joins_
范围,所以连接不会被破坏。
我有几个不能正常工作,或者至少不是客户希望他们工作的方式。这是模型结构的粗略概念,有几个命名范围(示例并非全部需要)来说明我的方法并指出我的问题。 (请原谅任何语法错误)
class Man < ActiveRecord::Base
has_many :wives
named_scope :has_wife_named lambda { |n| { :conditions => { :wives => {:name => n}}}}
named_scope :has_young_wife_named lambda { |n| { :conditions => { :wives => {:name => n, :age => 0..30}}}}
named_scope :has_yw_named_v2 lambda { |n| { :conditions => ["wives.name = ? AND wives.age <= 30", n]}}
named_scope :joins_wives :joins => :wives
named_scope :has_red_cat :conditions => { :cats => {:color => 'red'}}
named_scope :has_cat_of_color lambda { |c| { :conditions => { :cats => {:color => c}}}}
named_scope :has_7yo_cat :conditions => { :cats => {:age => 7}}
named_scope :has_cat_of_age lambda { |a| { :conditions => { :cats => {:age => a}}}}
named_scope :has_cat_older_than lambda { |a| { :conditions => ["cats.age > ?", a] }}
named_scope :has_cat_younger_than lambda { |a| { :conditions => ["cats.age < ?", a] }}
named_scope :has_cat_fatter_than lambda { |w| { :conditions => ["cats.weight > ?", w] } }
named_scope :joins_wives_cats :joins => {:wives => :cats}
end
class Wife < ActiveRecord::Base
belongs_to :man
has_many :cats
end
class Cat < ActiveRecord::Base
belongs_to :wife
end
我可以找到妻子的猫是红猫和七岁的男人
@men = Man.has_red_cat.has_7yo_cat.joins_wives_cats.scoped({:select => 'DISTINCT men'})
我什至可以找到妻子的猫体重超过 20 磅且超过 6 岁的男人
@men = Man.has_cat_fatter_than(20).has_cat_older_than(5).joins_wives_cats.scoped({:select => 'DISTINCT men'})
但这不是我想要的。我想找到妻子中至少有一只红猫和一只七岁的猫的男人,它们不必是同一只猫,或者找到妻子中至少有一只超过给定重量的猫的男人,并且一只比给定年龄大的猫。
(在随后的示例中,请假设存在适当的joins_
和DISTINCT
)我可以找到有妻子叫以斯帖的男人
@men = Man.has_wife_named('Esther')
我什至可以找到有妻子的男人叫 Esther、Ruth 或 Ada(真甜!)
@men = Man.has_wife_named(['Esther', 'Ruth', 'Ada'])
但我想找到有妻子的男人叫 Esther AND Ruth AND Ada。
哈哈,开个玩笑,其实我需要这个:我能找到老婆30岁以下叫Esther的男人
@men = Man.has_young_wife_named('Esther')
寻找有年轻妻子的男人,名叫 Esther、Ruth 或 Ada
@men = Man.has_young_wife_named(['Esther', 'Ruth', 'Ada'])
但如上所述,我想找到有年轻妻子的男人,名叫 Esther AND Ruth AND Ada。幸运的是,在这种情况下,最小值是固定的,但最好也指定一个最小年龄。
有没有办法用哈希语法测试不等式,还是你总是必须恢复- 注意和
:conditions => ["", n]
之间的区别- 我更喜欢第一个,但范围只适用于有限值。如果您正在寻找一位老太太,我想您可以使用,但是当一位妻子年满 101 岁时,她会放弃搜索。(嗯。她会做饭吗?j/k)has_young_wife_named
has_yw_named_v2
a..100
有没有办法在范围内使用范围?
:has_red_cat
如果可以:has_cat_of_color
以某种方式使用它,或者如果有某种方法可以使用其父项中子记录的范围,我会喜欢它,这样我就可以将与猫相关的范围放入Wife
模型中。
我真的不想在不使用的情况下直接使用 SQL 执行此操作named_scope
,除非还有其他更好的东西 - 对插件的建议和非常感谢的东西,或者指导我需要学习的那种 SQL。一位朋友建议 UNION 或子搜索可以在这里工作,但在 Rails 的上下文中似乎没有太多讨论。我对视图一无所知-它们有用吗?有没有一种让他们满意的方法来制作它们?
谢谢!
当我要去圣艾夫斯时,
我遇到了一个有七个妻子的男人
每个妻子有七个麻袋
每个麻袋有七只猫
每只猫有七个工具
包 工具包,猫,麻袋,妻子
有多少人要去圣艾夫斯?