如何在rails中添加条件where子句
Posted
技术标签:
【中文标题】如何在rails中添加条件where子句【英文标题】:How to add conditional where clauses in rails 【发布时间】:2012-07-26 05:53:00 【问题描述】:我是 Rails 新手,正在尝试使用 Rails 对表执行搜索,而我只是使用我的 sql 知识来执行此操作。但这看起来不像是 rails 或 ruby...
有没有更好的方法来做我在下面做的事情? (基本上,只有在填写日期参数时才将日期参数传递给 sql)
def search(begin_date=nil, end_date=nil)
subject = " and created_at "
if !(begin_date.nil? || end_date.nil?)
where_part = subject + "BETWEEN :begin_date AND :end_date"
else if (begin_date.nil? && end_date.nil?)
where_part = ""
else if(begin_date.nil?)
where_part = subject + " <= :end_date"
else if (end_date.nil?)
where_part = subject + " >= :begin_date"
end
end
end
end
User.joins(places: containers: label: :user).where("users.id= :user_id "+where_part, user_id: self.id, begin_date:begin_date, end_date:end_date).group(...).select(...)
end
编辑
用户.rb
has_many :containers
has_many :user_places
has_many :places, through: :user_places
has_many :labels
place.rb
has_many :containers
has_many :user_places
has_many :users, through: :user_places
容器.rb
belongs_to :label
belongs_to :place
belongs_to :user
标签.rb
belongs_to :user
has_many :containers
基本上,我想计算给定用户标签内或与每个位置有直接关系的容器数量,并希望能够按开始和结束日期对其进行过滤。
这两个日期都可能为零,所以我需要在我的“查询”中解决这个问题。
我的问题是:我怎样才能做到这一点?我看了一下http://guides.rubyonrails.org/active_record_querying.html,也许我可以在这里的某个地方使用except命令……但是这种关系模型似乎有点复杂,用ActiveRecord来做这件事……我可以怎么做?,我真的认为我应该使用ActiveRecord ,但是怎么做?
谢谢
【问题讨论】:
[这里是一个很好的例子,说明如何使用活动记录进行连接][1] [1]:***.com/questions/764538/… 嗨,我的问题不在于连接...我只是没有写它们,因为它们不相关。我的事情是条件搜索参数 @itsalltime - 我认为 Bob 想说的是 - 为什么不使用 Active Record 而不是直接编写 SQL? guides.rubyonrails.org/active_record_querying.html 【参考方案1】:我想不出你为什么要在代码中生成 SQL 的一个重要原因。 Active Record 似乎是满足您需求的更有效的解决方案,除非您有理由不能使用它。
Link explaining how to join tables with active record
【讨论】:
我实际上对如何使用连接有一些疑问,但我想我找到了一种方法来解决我想要的问题,因为我在我编辑的答案中发布了。我的东西实际上是条件搜索参数。 哦,像这样的情况:rigelgroupllc.com/blog/2014/09/14/…【参考方案2】:您可以对一个查询应用多个 where
调用,以便构建基本查询:
query = User.joins(...)
.group(...)
.select(...)
.where('users.id = :user_id', :user_id => self.id)
然后根据您的日期间隔添加另一个 where
电话:
if(begin_date && end_date)
query = query.where(:created_at => begin_date .. end_date)
# or where('created_at between :begin_date and :end_date', :begin_date => begin_date, :end_date => end_date)
elsif(begin_date)
query = query.where('created_at >= :begin_date', :begin_date => begin_date)
elsif(end_date)
query = query.where('created_at <= :end_date', :end_date => end_date)
end
每个where
调用都会使用 AND 为您的整体 WHERE 子句添加另一部分,例如:
q = M.where(a).where(b).where(c)
和WHERE a AND b AND c
一样。
【讨论】:
嗨,这个答案很棒。谢谢。看来我不能使用 begin_date .. end_date (并且必须使用空白?而不是 nil),因为我正在从文本字段中收集日期时间并在本地转换它们。if !begin_date.blank? begin_date = DateTime.strptime("#begin_date 00:00:00", "%m/%d/%Y %H:%M:%S").to_datetime end
我最终使用了您的替代建议:or where('created_at between :begin_date and :end_date', :begin_date => begin_date, :end_date => end_date)
@itsalltime:如果begin_date
和end_date
是真正的日期对象,则使用begin_date .. end_date
应该可以工作,但看起来你实际上有字符串。我建议在使用它们之前将它们转换为日期对象,这样您就只需要在一个地方担心日期格式问题。
嗨,我确实使用上面发布的函数转换它们,但即便如此 begin_date .. end_date 不起作用,这就是为什么我不得不选择替代方法
我想这一定是其他错误,因为现在看起来还可以。我现在的问题是“created_at”正在应用于用户表,我希望它应用于容器......我该怎么做?以上是关于如何在rails中添加条件where子句的主要内容,如果未能解决你的问题,请参考以下文章