ruby-on-rails – 如何使用ActiveRelation编写UNION链?

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 如何使用ActiveRelation编写UNION链?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要使用ActiveRelation连接UNION的任意数量的子选项.

我有点混淆了这个的AREL,因为它似乎假定UNION是一个二进制操作.

然而:

  1. ( select_statement_a ) UNION ( select_statement_b ) UNION ( select_statement_c )

是有效的sql.这是否可能没有做恶心的字符串替换?

解决方法

你可以比亚当·拉斯克(Adam Lassek)在正确的轨道上提出的更好一些.我刚刚解决了一个类似的问题,试图从社交网络模型中获得一个朋友列表.朋友可以通过各种方式自动获取,但我希望有一个ActiveRelation友好的查询方法可以处理进一步的链接.所以我有
  1. class User
  2. has_many :events_as_owner,:class_name => "Event",:inverse_of => :owner,:foreign_key => :owner_id,:dependent => :destroy
  3. has_many :events_as_guest,:through => :invitations,:source => :event
  4.  
  5. def friends
  6.  
  7.  
  8. friends_as_guests = User.joins{events_as_guest}.where{events_as_guest.owner_id==my{id}}
  9. friends_as_hosts = User.joins{events_as_owner}.joins{invitations}.where{invitations.user_id==my{id}}
  10.  
  11. User.where do
  12. (id.in friends_as_guests.select{id}
  13. ) |
  14. (id.in friends_as_hosts.select{id}
  15. )
  16. end
  17. end
  18.  
  19. end

这充分利用了Squeels子查询支持.生成sql

  1. SELECT "users".*
  2. FROM "users"
  3. WHERE (( "users"."id" IN (SELECT "users"."id"
  4. FROM "users"
  5. INNER JOIN "invitations"
  6. ON "invitations"."user_id" = "users"."id"
  7. INNER JOIN "events"
  8. ON "events"."id" = "invitations"."event_id"
  9. WHERE "events"."owner_id" = 87)
  10. OR "users"."id" IN (SELECT "users"."id"
  11. FROM "users"
  12. INNER JOIN "events"
  13. ON "events"."owner_id" = "users"."id"
  14. INNER JOIN "invitations"
  15. ON "invitations"."user_id" =
  16. "users"."id"
  17. WHERE "invitations"."user_id" = 87) ))

您需要一个可变数量的组件的替代模式通过稍微修改上述代码来进行演示

  1. def friends
  2.  
  3.  
  4. friends_as_guests = User.joins{events_as_guest}.where{events_as_guest.owner_id==my{id}}
  5. friends_as_hosts = User.joins{events_as_owner}.joins{invitations}.where{invitations.user_id==my{id}}
  6.  
  7. components = [friends_as_guests,friends_as_hosts]
  8.  
  9. User.where do
  10. components = components.map { |c| id.in c.select{id} }
  11. components.inject do |s,i|
  12. s | i
  13. end
  14. end
  15.  
  16.  
  17. end

这是对OP的确切问题的解决方案的粗略猜测

  1. class Shift < ActiveRecord::Base
  2. def self.limit_per_day(options = {})
  3. options[:start] ||= Date.today
  4. options[:stop] ||= Date.today.next_month
  5. options[:per_day] ||= 5
  6.  
  7. queries = (options[:start]..options[:stop]).map do |day|
  8.  
  9. where{|s| s.scheduled_start >= day}.
  10. where{|s| s.scheduled_start < day.tomorrow}.
  11. limit(options[:per_day])
  12.  
  13. end
  14.  
  15. where do
  16. queries.map { |c| id.in c.select{id} }.inject do |s,i|
  17. s | i
  18. end
  19. end
  20. end
  21. end

猜你在找的Ruby相关文章