У меня есть несколько моделей:
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
с правильным языком, он ничего не вернет (как и должно быть).Я хотел бы сделать две вещи:
- Если нет
option_detail
с правом locale
, используйте запасной языковой стандарт (например, en-US). - Если есть
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