是否可以仅使用命名范围重写此查询?
Is possible to rewrite this query using only named scopes?
我希望仅使用命名范围来编写此查询。原因很简单,我不想在更改 Client
被视为 active 的方式时到处更改代码(与 User
被视为 可连接)
这是我的代码
client.rb
class Client < ActiveRecord::Base
has_one :user
scope :actives, -> { where(starting_date: a_date, finishing_date: another_date, enabled: true) }
end
user.rb
class User < ActiveRecord::Base
belongs_to :client
scope :connectable, -> { where.not(access_token: nil, instance_url: nil) }
end
在这里您可以找到我编写此查询的尝试:
# What I would like to write
User.eager_load(:client).connectable.where("client is in :actives scope")
# Current options
# 1 - (but this violates dry)
User.eager_load(:client).connectable.where(['clients.starting_date = ? AND clients.finishing_date = ? AND clients.enabled = ?', a_date, another_date, true).references(:client)
# 2 - My best attempt so far
User.connectable.where(client_id: Client.actives.pluck(:id))
还有一个link给GIST供参考
我不确定这个想法有多好,但只要您确保您的列名称的名称间隔正确(即,您不能在客户端和用户中都使用 'foo'在 table 名称前加上前缀)那么这应该有效:
User.eager_load(:client).connectable.where(Client.active.where_values.map(&:to_sql).join(" AND "))
一定有更好的方法,但上面的方法对我有用:
课程模型:
scope :valid, -> { enabled.has_country }
scope :has_country, -> { where.not(country_id:nil) }
Rails 控制台:
> Course.where(Course.valid.where_values.map(&:to_sql).join(" AND ")).to_sql
=> "SELECT \"courses\".* FROM \"courses\"
WHERE (\"courses\".\"is_enabled\" = 't'
AND \"courses\".\"country_id\" IS NOT NULL)"
您要查找的是 ARel 的 merge
方法。 (An article on this here.)
试试这个:
User.connectable.includes(:client).merge(Client.actives).references(:clients)
includes(:client)
将引入来自 User 的 :client 关系,这将使 .merge(Client...)
作用域起作用。 Rails 4+ 要求 .references
明确说明 includes
语句将引用哪个 table。
我希望仅使用命名范围来编写此查询。原因很简单,我不想在更改 Client
被视为 active 的方式时到处更改代码(与 User
被视为 可连接)
这是我的代码
client.rb
class Client < ActiveRecord::Base
has_one :user
scope :actives, -> { where(starting_date: a_date, finishing_date: another_date, enabled: true) }
end
user.rb
class User < ActiveRecord::Base
belongs_to :client
scope :connectable, -> { where.not(access_token: nil, instance_url: nil) }
end
在这里您可以找到我编写此查询的尝试:
# What I would like to write
User.eager_load(:client).connectable.where("client is in :actives scope")
# Current options
# 1 - (but this violates dry)
User.eager_load(:client).connectable.where(['clients.starting_date = ? AND clients.finishing_date = ? AND clients.enabled = ?', a_date, another_date, true).references(:client)
# 2 - My best attempt so far
User.connectable.where(client_id: Client.actives.pluck(:id))
还有一个link给GIST供参考
我不确定这个想法有多好,但只要您确保您的列名称的名称间隔正确(即,您不能在客户端和用户中都使用 'foo'在 table 名称前加上前缀)那么这应该有效:
User.eager_load(:client).connectable.where(Client.active.where_values.map(&:to_sql).join(" AND "))
一定有更好的方法,但上面的方法对我有用:
课程模型:
scope :valid, -> { enabled.has_country }
scope :has_country, -> { where.not(country_id:nil) }
Rails 控制台:
> Course.where(Course.valid.where_values.map(&:to_sql).join(" AND ")).to_sql
=> "SELECT \"courses\".* FROM \"courses\"
WHERE (\"courses\".\"is_enabled\" = 't'
AND \"courses\".\"country_id\" IS NOT NULL)"
您要查找的是 ARel 的 merge
方法。 (An article on this here.)
试试这个:
User.connectable.includes(:client).merge(Client.actives).references(:clients)
includes(:client)
将引入来自 User 的 :client 关系,这将使 .merge(Client...)
作用域起作用。 Rails 4+ 要求 .references
明确说明 includes
语句将引用哪个 table。