ActiveRecord: объединяет таблицу на основе массива атрибутов, но сериализует только первую связанную запись - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть несколько моделей:

class Configuration < ApplicationRecord
  has_many :configuration_screens
end

class ConfigurationScreen < ApplicationRecord
  belongs_to :configuration
  has_many :configuration_options
end

class ConfigurationOption < ApplicationRecord
  belongs_to :configuration_screen
  belongs_to :option
end

class Option < ApplicationRecord
  has_many :option_details, dependent: :destroy, autosave: true
end

class OptionDetail < ApplicationRecord
  belongs_to :option, touch: true
end

Следующий запрос извлекает конфигурацию на основе локали его configuration_screen, а также на основе локали option_detail в файле configuration_screens.

configuration = Configuration.includes(
  configuration_screens: [
    configuration_options: {
      option: :option_details
    }
  ]
).where(
  configuration_screens: {
    locale: locale,
    configuration_options: {
      option: {
        option_details: {
          locale: locale
        }
      }
    }
  }
).find(id)

configuration.as_json(
  include: {
    configuration_screens: {
      include: {
        configuration_options: {
          include: {
            option: {
              include: :option_details
            }
          }
        }
      }
    }
  }
)

Это прекрасно работает, за исключением того, что если нет option_detail с правильным языком, он ничего не вернет (как и должно быть).Я хотел бы сделать две вещи:

  1. Если нет option_detail с правом locale, используйте запасной языковой стандарт (например, en-US).
  2. Если естьoption_detail с правильным языком, включайте только эту запись.Не включайте другие.

Я знаю, что мог бы просто проанализировать configuration JSON и отфильтровать option_details таким образом (например, что-то вроде ниже), но это кажется грязным решением.Есть ли лучший способ сделать это?

Этот код ниже не проверен.Это могло бы работать, но это грязно и жестко.

configuration['configuration_screens'].each do |screen|
  screen.configuration_options.each do |config_option|
    keep = []
    config_option.option.option_details.map do |option_detail|
      keep << option_detail if option_detail.locale == locale
    end

    if keep.present?
      config_option.option.option_details = keep
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...