【问题标题】:How is the Arel#extract method used in rails?Rails 中如何使用 Arel#extract 方法?
【发布时间】:2012-03-14 23:20:31
【问题描述】:

我正在尝试使用 Arel#extract 方法。我在源代码中 test_extract.rb 的测试用例中看到了一个示例,但是当我尝试在我的应用程序中重现它时,我得到未定义的方法。

table = Arel::Table.new :users
puts table[:created_at].extract('hour').to_sql
=> NoMethodError: undefined method `extract' for #<Arel::Attributes::Attribute:0x7..8>

我使用 pg 作为数据库。

更新:

我的目标是在 sql 中得到这个结果:

SELECT users.* FROM users WHERE EXTRACT(HOUR from users."created_at") = '1'

我想查找在等于任何一天的一小时内创建的所有用户。这在 sql 中有效,但我想知道如何在 arel 中创建它。这是一个example,它是如何在 arel 测试套件中使用的。

【问题讨论】:

  • 我没有看到 #extract 是文档中 Arel::Table 类的一部分。你想做什么?从表中检索'date'
  • 我更新了描述来回答你的问题。
  • ActiveRecord 查询是否更适合您? Users.where("Minute(?) = 1", :created_at).all?
  • [抱歉,忘记您在 PG 上] ActiveRecord 查询是否更适合您? Users.where("EXTRACT(hour from ?) = 1", :created_at).all?
  • 我试图避免这种情况,但还是谢谢。问题不在于阿雷尔。仅在 Rails 中使用时。当我更好地理解问题时,我会发布我的发现。

标签: sql ruby-on-rails ruby arel


【解决方案1】:

extract 是 node 的方法,你可以将它投射到任何列上(例如 users[:id]),但不能投射到 Arel::Table 实例上。

所以,要构建您的查询,您需要:

  • 获取 Arel::Table 实例 users = Arel::Table.new(:users) 或者如果您使用 ActiveRecord - users = User.arel_table
  • 使用project 方法在Arel::Table 实例上设置SELECT 语句:users = users.project(Arel.sql('*'))
  • 使用where 方法设置WHERE 语句:users.where(users[:created_at].extract(:hour).eq(1))

在一个区块中:

query = User.arel_table.
             project(Arel.sql('*')).
             where(users[:created_at].extract(:hour).eq(1))
users = User.find_by_sql(query)
# => "SELECT * FROM \"users\"  WHERE EXTRACT(HOUR FROM \"users\".\"created_at\") = 1"

【讨论】:

    【解决方案2】:

    我不得不对 Arel::Nodes::NamedFunction 的一个实例执行提取 DOW,它不公开方法 #extract(从 Arel 6.0 开始)。我设法通过手动创建Arel::Nodes::Extract 的实例来实现这一点。如果有人遇到类似问题,这对我有用:

    Arel::Nodes::Extract.new( Arel::Nodes::NamedFunction.new('some_function_name', [param1, param2, ...]), :dow )

    您可以直接将 Arel 节点与 ActiveRecord 的 #where 一起使用,而不是像 Alexander Karmes 的回答那样通过 Arel 构建完整的查询。所以这里有另一种方式来执行答案所需的查询:

    User.where( Arel::Nodes::Extract.new(User.arel_table[:created_at], :hour).eq(1) )

    产量:

    SELECT "users".* FROM "users" WHERE EXTRACT(HOUR FROM "users"."created_at") = 1

    有了额外的好处,您可以继续链接在 User 模型中定义的其他范围。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多