Как метод Arel # extract используется в рельсах? - PullRequest
3 голосов
/ 15 марта 2012

Я пытаюсь использовать метод 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.Вот пример того, как он используется в тестовом наборе arel.

Ответы [ 2 ]

1 голос
/ 13 октября 2014

extract - это метод узла, вы можете привести его к любому столбцу (например, users [: id]), но не к экземпляру Arel :: Table.

Итак, для построения вашего запроса вам нужно:

  • get Arel :: Table instance users = Arel::Table.new(:users) или если вы используете ActiveRecord - users = User.arel_table
  • установите оператор SELECT для Arel :: Table экземпляра с project метод: 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"
0 голосов
/ 03 января 2017

Мне пришлось выполнить извлечение DOW для экземпляра Arel :: Nodes :: NamedFunction, который не предоставляет метод #extract (по состоянию на Arel 6.0). Мне удалось добиться этого, вручную создав экземпляр Arel::Nodes::Extract. Вот что сработало для меня, на случай, если у кого-то возникнет похожая проблема:

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

Вы можете использовать узел Arel непосредственно с #where ActiveRecord вместо построения полного запроса через 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.

...