我在Rails应用程序中编写的一个条件查询有一个问题。目前,如果某些位置(location_north,location_south等)为真,以及某些类型(type_dining,type_unique等)为真,我会查询Stores,但我希望它查询它们是否为两个,而不是所有的都为真。
例如,如果Lead的location_north和location_east设置为true,我想查询所有具有location_north或location_east的Store,Store不需要都设置为true。
类型相同,如果Lead具有store_type_unique true和store_type_dining true,我想查询具有type_unique OR type_dining true的所有商店,商店不需要都设置为true。
我知道我的数据库的组织方式存在问题,但是否可以在当前版本中设置此数据库?感谢您的任何指导,非常感谢!
def build_filters_obj
filters = []
filters.push 'location_north' if @lead.location_north
filters.push 'location_east' if @lead.location_east
filters.push 'location_south' if @lead.location_south
filters.push 'location_west' if @lead.location_west
filters.push 'location_other' if @lead.location_other
return filters
end
def perform(lead_id)
@lead = Lead.find(lead_id)
lead_email = ValidEmail2::Address.new(@lead.email)
UserNotifierMailer.send_signup_email(@lead).deliver if lead_email.valid?
@stores = Store.all
@stores = @stores.where.not(email: [nil, ''])
n = @lead.guests_total.to_i
@stores = @stores.where("capacity_min <= ? AND capacity_max >= ?", n, n)
@stores = @stores.where(:type_unique => true) if @lead.store_type_unique
@stores = @stores.where(:type_dining => true) if @lead.store_type_dining
@stores = @stores.where(:type_hotel => true) if @lead.store_type_hotel
filters = build_filters_obj
filters.each do |filter|
@stores = @stores.where(filter.to_sym => true)
end
@stores = @stores.or(Store.where(:receive_all => true))
@stores.each do |store|
store_email = ValidEmail2::Address.new(store.email)
UserNotifierMailer.send_lead_email(store, @lead).deliver if store_email.valid?
end
end
字符串
3条答案
按热度按时间ki1q1bka1#
我认为这里的挑战是基于@lead的属性动态构建OR查询。下面是perform方法的新方法:
字符串
p8ekf7hl2#
一个非常快速的改变是重写每一行:
字符串
对此:
型
对于
filters
循环中的行也是如此。然后,编写测试以确保得到正确的逻辑。最后,您可以重构以DRY up代码。
u4vypkhs3#
两个想法:
1.至少有一种方法可以让你的应用程序以当前的方式构建/组织。
1.我不会使用它们中的任何一个。这个应用程序需要重构,现在是一个很好的时间去做。
由于Rails
or
方法需要一个以object类为参数的查询,因此您当前的选项有点棘手。看起来您想要有电子邮件地址的商店。这样的查询意味着or正在抓取没有电子邮件地址的商店。字符串
您可以在Store类上定义一个作用域,然后将其应用于两者,即。
型
但是,假设你重构了你的应用程序,这样你就有了一个名为
store_type
的列,而不是每种商店类型的列。我在这里使用enum,但为了简单起见,让我们假设它是一个字符串字段。然后上面的代码就变成了这样:型
这相当于一个
store_type IN ("unique", "dining")
SQL语句。这就是您要查找的内容。此外,如果Lead的位置存储为数组字符串字段,如果您的应用程序使用PostgreSQL数据库,则
@lead.location
将返回类似["east", "north"]
的数组,并且您可以为此废弃build_filters_obj
方法:型
重构会让你的
perform
方法更容易被其他开发人员(包括你自己)阅读和理解。如果你真的走这条路,你需要重构一些数据库数据。有很好的工具可以做到这一点。这两个应用程序本质上都是在后台运行rake任务,你需要这样做来转换你的数据。
1.部署具有并使用新数据库列(即location、store_type)的新代码。
1.使用上述gem之一来转换旧数据以使用新格式和列。
1.部署删除现在失效的数据库列(即location_north、location_west等)的代码。
我通常在一个版本中执行步骤1和步骤2,在下一个版本中执行步骤3,但这都是关于适合您的应用程序的内容以及它的停机能力。