Справочная информация: я пытаюсь реорганизовать свой код после прочтения Практического объектно-ориентированного проектирования в Ruby (это потрясающе), и при этом я хочу представить еще несколько моделей, которые заключают в себе ответственность, а неу меня есть один большой файл с логикой (и операторы case, для этого).
Проблема: Чтобы упростить постановку задачи, у меня есть модель Rule
, которая "имеет много" RuleConditions
.Однако в базе данных есть только одна таблица для правил.В нем у меня есть столбец для условий типа jsonb
(в зависимости от сложности RuleCondition
).Но я не могу этого достичь.В частности, Я не могу понять, как создать экземпляр модели с вложенной моделью, и ожидать, что ActiveRecord будет знать, как преобразовать модель в jsonb и, возможно, из таблицы обратно во вложенную модель .Я также не знаю, смогу ли я определить отношение has_many
без таблицы, поддерживающей его, используя ActiveRecord.
Что я ожидаю:
Я ожидаю, что должен быть какой-то поток (определенныйсмесью ActiveRecord и ActiveModel), которая сделала бы этот поток возможным
- Получить параметры для
Rule
. - Создать новый массив
RuleConditions
из подмножестваparams для правила. - Do
Rule.new(rule)
, где правило содержит: условия => RuleCondition
- Do
rule.save!
- Через некоторое время получить правило изи ожидаем, что он восстановит
Rule
с вложенной моделью RuleConditions
из атрибута conditions
.
Что я пробовал:
Что я думалПолучил бы меня на полпути был serialize, :conditions, JSON
, но он пытается сериализовать мой объект.После этого я действительно не знаю.Я также поиграл с ActiveModel :: Conversion.Поэтому мне просто нужно некоторое руководство.
И, чтобы быть совершенно ясным, вызов as_json
на моем RuleCondition
работает так, как я ожидал (выводит тот же JSON, который раньше хранился в Rule
модель и база данных до попытки рефакторинга).Так что, может быть, я не понимаю serialize
(поскольку предполагается, что это YAML, если не указано иное, я думаю, что кодировка отличается от просто "соответствовать моему типу столбца")
Редактировать:
В настоящее время у меня есть что-то вроде (barebones, 0 проверок / ассоциаций)
class Rule < ActiveRecord::Base
end
class RuleController < ApplicationController
def create
rule = Rule.new(rule_params[:rule]) # conditions are just an attribute in the params
rule.save
end
end
Теперь, с новой моделью, которая определяется как
class RuleCondition
include ActiveModel::Model # (what I'm currently doing to get some of the behavior of a model without the persistence / table backing it, I think)
attr_accessor :noun, :subnoun # etc
end
Я думаю, мне нужно сделать это
def create
rule = rule_params[:rule]
rule["conditions"] = rule["conditions"].map do |c|
RuleCondition.new(c)
end
true_rule = Rule.new(rule)
true_rule.save!
end
Но это не работает, (именно) по этой причине:
18: 13: 52 web.1 |SQL (10,7 мс) INSERT INTO "rules" ("имя", "условия", "made_at", "updated_at") ЗНАЧЕНИЯ ($ 1, $ 2, $ 3, $ 4) RETURNING "id" [["name", "wefw"], ["условия", "{#}"], ["созданный_ат", "2018-12-16 02: 13: 52.938849"], ["updated_at", "2018-12-16 02: 13: 52.938849"]] 18:13:52 web.1 |PG :: InvalidTextRepresentation: ОШИБКА: неверный синтаксис ввода для типа json 18:13:52 web.1 | ДЕТАЛИ: токен "#" недействителен .18:13:52 веб.1 |КОНТЕКСТ: данные JSON, строка 1: # ... 18:13:52 web.1 |: INSERT INTO "rules" ("имя", "условия", "made_at", "updated_at") ЗНАЧЕНИЯ ($ 1, $ 2, $ 3, $ 4) RETURNING "id" 18:13:52 web.1 |(0,5 мс) ROLLBACK