Rails 5 Активный запрос записи не показывает атрибуты left_outer_joins

#ruby-on-rails-5

#ruby-on-rails-5

Вопрос:

Я пытаюсь выполнить внешнее соединение слева, чтобы получить связанные атрибуты, а затем отсортировать по соответствующему атрибуту.

Моя проблема в том, что связанный атрибут pfeature_id отсутствует в выходных данных.

Я не могу найти никаких записей о том, что я могу здесь делать неправильно.

В примерах 1 и 2, приведенных ниже, связанные product_features.pfeature_id не отображаются в списке.

В примере 3 необработанный sql выполняется в sqlite3 или mysql и отображается pfeature_id.

Одна из страниц, на которые я ссылался, была: https://guides.rubyonrails.org/active_record_querying.html#left-outer-joins

Может кто-нибудь сказать, что я делаю не так?

 1.

albe@vamp398:/srv/test/brails/brail484b51$ dc exec web bundle exec rails console
Loading development environment (Rails 5.2.3)

irb(main):002:0>  b=Product.left_joins(:product_feature).select("products.id,
 products.name, product_features.pfeature_id").where("products.id>8").take(2)

  Product Load (0.7ms)  SELECT  products.id, products.name, 
product_features.pfeature_id FROM "products" LEFT OUTER JOIN "product_features" ON 
"product_features"."product_id" = "products"."id" WHERE (products.id>8) 
LIMIT ?  [["LIMIT", 2]]

=> [#<Product id: 9, name: "redKnife">, #<Product id: 10, name: "pf">]

  
 2.

class Product < ApplicationRecord
  has_many :product_feature
  has_many :pfeature, through: :product_feature
  
  def self.pf
    # raw sql select using ...
    Product.find_by_sql 
    <<-SQL
      SELECT  products.id, products.name, product_features.pfeature_id FROM products LEFT OUTER JOIN 
        product_features ON product_features.product_id = products.id 
    SQL
  end
end

irb(main):005:0> b=Product.pf.last(4)
        
SELECT  products.id, products.name, product_features.pfeature_id FROM products
 LEFT OUTER JOIN product_features ON product_features.product_id = products.id

=> [#<Product id: 8, name: "11">, #<Product id: 9, name: "redKnife">, 
#<Product id: 10, name: "pf">, #<Product id: 10, name: "pf">]

  
 3.

Run this sql in sqlite3 or MySQL:

SELECT  products.id, "products".name, product_features.pfeature_id FROM
 "products" LEFT OUTER JOIN "product_features" ON 
"product_features"."product_id" = "products"."id" 
WHERE (products.id>8) LIMIT 2

    id  name      pfeature_id
    9   redKnife  NULL
    10  pf        8
  
 Tables:

  create_table "product_features", force: :cascade do |t|
    t.string "name"
    t.integer "product_id"
    t.integer "pfeature_id"
    ...
  end

  create_table "products", force: :cascade do |t|
    t.string "name"
    ...
  end
  

Ответ №1:

проблема в том, что если столбец в select не является одним из атрибутов модели, для которой select вызывается, тогда эти столбцы не отображаются. Все эти атрибуты по-прежнему содержатся в объектах внутри AR::Relation и доступны как любые другие атрибуты общедоступного экземпляра. Пример:

 products = Product.left_joins(:product_feature).select("products.id, products.name, product_features.pfeature_id").where("products.id > 8").take(2)
products.first.pfeature_id
  

Для проверки просто запустите эти две строки в своей консоли. Вы получите желаемый результат. Поскольку это a LEFT JOIN , вы можете получить вывод, как nil при product отсутствии product_features .

Если вы хотите отсортировать свои выходные данные, имейте в виду, что ваш столбец сортировки должен содержать NOT NULL значения. Пример:

 products = Product.left_joins(:product_feature).select("products.id, products.name, product_features.pfeature_id").where("products.id > 8")

# sort with your desired column
sorted_products = products.sort_by(amp;:name)
# or
sorted_products = products.sort_by(amp;:pfeature_id) # make sure `pfeatured_id` is not null for any product