Как связать запросы Arel с методами ActiveRecord? - PullRequest
0 голосов
/ 17 марта 2019

Я открываю для себя Arel и немного озадачен тем, как вернуться к объектам ActiveRecord, используемым по умолчанию в моем приложении RoR 5.2.

Первоначально мой набор данных индекса бизнес-правил был определен как:

@business_rules = BusinessRule.pgnd(current_playground_scope). 
search(params[:criteria]).order("hierarchy ASC").
paginate(page: params[:page], :per_page => paginate_lines)

Теперь столбцы Name и Description предоставляются таблицей Translations, что делает запросы немного более сложными. Вот где приходит Арель:

names = Translation.arel_table.alias('tr_names')
descriptions = Translation.arel_table.alias('tr_descriptions')
rules = BusinessRule.arel_table
translated_rules = rules.
join(names, Arel::Nodes::OuterJoin).on(rules[:id].eq(names[:document_id]).and(names[:language].eq(user_language).and(names[:field_name].eq('name')))).
join(descriptions, Arel::Nodes::OuterJoin).on(rules[:id].eq(descriptions[:document_id]).and(descriptions[:language].eq(user_language).and(descriptions[:field_name].eq('description'))))

rules_extract = translated_rules.project(Arel.star)
sql = rules_extract.to_sql
@rules_index = ActiveRecord::Base.connection.execute(sql)

#suggestions for better organising Arel's tree are welcome

Метод to_sql предоставляет удовлетворительный запрос SQL, но результат метода execute возвращает класс PG :: Result, где я ожидаю ActiveRecord_Relation.

Читая вокруг, я многое узнал о возможностях Арела, но мне все еще не хватает ссылки, чтобы вернуть ее на работу в моем индексном представлении.

Спасибо за помощь!

1 Ответ

0 голосов
/ 19 марта 2019

На самом деле, Arel предоставляет фрагменты запроса в стандартный интерфейс запросов ActiveRecord. Это позволяет мне переписать исходный запрос индекса Rails и дважды добавить связанную таблицу с псевдонимами:

def index
  names = Translation.arel_table.alias('tr_names')
  descriptions = Translation.arel_table.alias('tr_descriptions')
  rules = BusinessRule.arel_table
  translated_rules = rules.
    join(names, Arel::Nodes::OuterJoin).on(rules[:id].eq(names[:document_id]).and(names[:language].eq(user_language).and(names[:field_name].eq('name')))).
    join(descriptions, Arel::Nodes::OuterJoin).on(rules[:id].eq(descriptions[:document_id]).and(descriptions[:language].eq(user_language).and(descriptions[:field_name].eq('description')))).
    join_sources

  @business_rules = BusinessRule.joins(translated_rules).order("hierarchy ASC, major_version, minor_version").paginate(page: params[:page], :per_page => paginate_lines)

  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @business_rules }
  end
end

Теперь я готов к умному рефакторингу моих запросов и извлечению переведенных полей из таблицы переводов!

...