Ruby activerecord внешнее объединение двух таблиц с помощью ActiveRecord

#ruby #activerecord

#ruby #activerecord

Вопрос:

Я новичок в Ruby и Activer Record, но мне трудно ответить на этот вопрос. У меня есть две таблицы: арендаторы и квартиры Вот определения:

 CREATE TABLE tenants(
  id serial PRIMARY KEY,
  name varchar(50) NOT NULL,
  age integer NOT NULL,
  gender varchar(10) NOT NULL,
  apartment_id integer NOT NULL
);

CREATE TABLE apartments(
  id serial PRIMARY KEY,
  address varchar(50) NOT NULL,
  monthly_rent decimal(12,2) NOT NULL,
  sqft integer  NOT NUlL,
  num_beds integer NOT NULL,
  num_baths integer NOT NULL
);
  

Вопрос, который мне задают, заключается в:

Выполните итерацию по каждой квартире, для каждой квартиры отобразите ее адрес и всех ее арендаторов

Я зашел в psql и могу найти ответ с помощью этого запроса: выберите.address, b.name из квартир a, жильцы b, где a.id = заказ b.apartment_id по a.address;

Я могу выполнить итерацию по каждой квартире, а затем перебрать арендаторов и найти ответ таким образом, но это не слишком удобно, и мне все еще нужен способ не распечатывать адрес, если во внутреннем цикле нет совпадений. Вот этот код:

 Apartment.find_each { |user|
   puts "-Outer Address #{user.address}"
   Tenant.find_each { | tenant|
    puts "-inner Tennant #{tenant.name}" if tenant.apartment_id==user.id
   } # tenant where
} #apartment.find
  

Я уверен, что должен быть метод для вызова, который объединит два цикла, но я просто не могу понять это.. Спасибо.

Ответ №1:

Вы можете использовать includes для поиска ассоциаций загрузки, а затем перебирать их:

 Apartment.includes(:tenants).find_each do |apartment|
    apartment.tenants.each do |tenant|
        # print tenant details
    end
end
  

Комментарии:

1. Спасибо! Вот мой измененный код: Apartment.includes(:tenants).find_each do |apartment| address_printed = true apartment.tenants.each do |tenant| # print tenant details puts "Address: #{apartment.address}" if address_printed puts " Tennant: #{tenant.name}" address_printed=false end end я заметил, что вы используете do ends not {} Это проблема стиля?

2. Соглашение Ruby заключается в использовании {} для однострочных блоков и выполнении ..end для многострочных блоков.

3. В вашем коде вы можете переместить puts "Address: #{apartment.address}" внешнюю часть внутреннего цикла и избавиться от address_printed проверки.