Группа ActiveRecord с псевдонимом - PullRequest
3 голосов
/ 13 января 2020

Первый вопрос, который когда-либо был здесь, и довольно новый для кодирования полных приложений / Rails.

Я создавал метод, позволяющий рассчитывать количество названий по автору, и заметил, что если автор распределен по-разному, он будет считаться разными авторами. Я хотел разместить какую-то проверку / проверку, чтобы игнорировать корпус и посчитать его вместе. Я не забочусь о расположении названий книг в этом конкретном случае.

Итак, у меня есть такая таблица:

Author                Book Title                               Year    Condition
William Shakespeare   Hamlet                                   1599    Poor
Stephen King          The Shining                              1977    New
Edgar Allen Poe       The Raven                                1845    Good
JK Rowling            Harry Potter and the Sorcerer's Stone    2001    New
edgar allen poe       The Tell-Tale Heart                      1843    Good
JK Rowling            Fantastic Beasts and Where to Find Them  2001    New

Я хочу вывести это:

Author                 Count
William Shakespeare    1
Stephen King           1
Edgar Allen Poe        2                              
JK Rowling             2 

Мой метод изначально был примерно таким:

  def self.book_counts
    distinct_counts = []
    Book.group(:author).count.each do |count|
      distinct_counts << count
    end
    distinct_counts
  end

Чтобы игнорировать регистр, я ссылался на эту страницу и придумал это, что, к сожалению, не сработало:

1) С этим я получаю "undefined method lower ":

    Book.group(lower('author')).count.each do |count|
      distinct_counts << count

2) Это выполняется, но с помощью метода select в целом, я получаю кучу результатов ActiveRecord / ID записи: nil. Я использую Rails 6, и он дополнительно отмечает «ПРЕДУПРЕЖДЕНИЕ ОБ УСТРОЙСТВЕ: Опасный метод запроса (метод, аргументы которого используются как raw SQL), вызываемый с неатрибутивным аргументом (ами) ... Аргументы без атрибута будут запрещены в Rails 6.1 . Этот метод не должен вызываться с предоставленными пользователем значениями, такими как параметры запроса или атрибуты модели. Известные безопасные значения могут быть переданы путем переноса их в Arel. sql (). (Вызывается из irb_binding at (irb): 579 ) ":

Book.select("lower(author) as dc_auth, count(*) as book_count").group("dc_auth").order("book_count desc")

3) Я даже пытался протестировать другую, упрощенную функцию, чтобы увидеть, будет ли она работать, но я получил" ActiveRecord :: StatementInvalid (PG :: GroupingError: ERROR: column ") books.author "должен появляться в предложении GROUP BY или использоваться в статистической функции)":

    Book.pluck('lower(author) as dc_auth, count(*) as book_count')

4) Я пробовал другие способы, с дополнительными различными ошибками, например, "неопределенная локальная переменная" или метод 'dc_auth' "," неопределенный метод "группа" Вы имели в виду group_by? "и" неправильное количество аргументов (задано 1, ожидается 0) "(с group_by) и т. д. c.

Thi s запрос работает именно так, как я хочу в postgresql. Синтаксис фактически заполняется в терминале, когда я запускаю # 2, но, как уже упоминалось, к сожалению, из-за ActiveRecord не правильно выводит в Rails.

SELECT lower(author) as dc_auth, count(*) as book_count FROM books GROUP BY dc_auth;

Есть ли способ запустить то, что я хочу через Rails ??

Ответы [ 3 ]

1 голос
/ 13 января 2020

Вы можете выполнить свой запрос, используя ActiveRecord. И я предложу go с SQL блоком

book_count_query = <<-SQL 
       SELECT lower(author) as dc_auth, count(*) as book_count
       FROM books
       GROUP BY dc_auth;
SQL

1- result = ActiveRecord::Base.connection.execute(book_count_query)

or 
2- result = ActiveRecord::Base.connection.exec_query(book_count_query)

Какая разница между строкой 1 и строкой 2?

exec_query возвращает ActiveRecords :: Результат объекта, который имеет удобные методы, такие как .columns и .rows для доступа к заголовкам и значениям.

Массив хэшей из .execute может быть проблематичным, и он дал мне избыточные результаты, когда я работал с предложением SUM GROUP BY.

Если вам нужно узнать больше об этой топи c

У этого ресурса есть пример для запроса и вывода.

1 голос
/ 13 января 2020

Может быть, вы можете попробовать

Book.group("LOWER(author)").count
0 голосов
/ 13 января 2020

Почему вы храните авторов в одной таблице с книгами. Лучшее решение - добавить отдельную таблицу для авторов и добавить внешний ключ в таблицу author_id - books. С помощью counter_cache вы можете легко подсчитать количество книг для каждого автора.

Вот руководство с books и authors примерами https://guides.rubyonrails.org/association_basics.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...