簡體   English   中英

Rails嵌套的模型在沒有自己的表的情況下往返數據庫的轉換

[英]Rails nested model conversion to and from database without its own table

背景:在閱讀了Ruby中的《面向對象的實用設計》之后,我試圖重構我的代碼(很棒),為此,我想引入更多的封裝責任的模型,而不是使用帶有邏輯的單個大文件(和案例說明)。

問題:為了簡化問題說明,我有一個模型Rule ,它“有很多” RuleConditions 但是,數據庫中只有一個表用於規則。 在這里面,我有這類型的條件的欄jsonb (根據並發症RuleCondition )。 但我似乎無法實現這一目標。 具體來說, 我無法弄清楚如何使用嵌套模型實例化模型,並希望ActiveRecord知道如何將模型轉換為jsonb,甚至可能從表轉換回嵌套模型 我也不知道是否可以在沒有表的情況下使用ActiveRecord定義has_many關系。

我的期望:

我希望應該有一些流程(由ActiveRecord和ActiveModel混合定義),以使該流程成為可能

  1. 獲取Rule參數。
  2. 從規則的參數子集創建一個新的RuleConditions數組。
  3. 執行Rule.new(rule) ,其中rule包含:conditions => RuleCondition
  4. rule.save!
  5. 稍后,從表中獲取規則,並期望它使用來自conditions屬性的嵌套RuleConditions模型重建Rule

我嘗試過的

我以為可以讓我半途而廢的是serialize, :conditions, JSON ,但是它很難序列化我的對象。 在那之后,我真的不知道。 我也玩過ActiveModel :: Conversion。 所以我只需要一些指導。

而且,要清透,呼吁as_jsonRuleCondition就像我期待它(打印出所用的是儲存在同一個JSON Rule模型,並嘗試進行重構前的數據庫)。 因此,可能是我不了解serialize (因為除非另有說明,否則應該將serialize YAML,我認為編碼不同於“匹配我的列類型”)

編輯:

目前,我有類似的東西(准系統,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.7ms)插入“規則”(“名稱”,“條件”,“ created_at”,“ updated_at”)值($ 1,$ 2,$ 3,$ 4)返回“ id” [[[“ name”,“ wefw” ],[“ conditions”,“ {#}”],[“ created_at”,“ 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 web.1 | 上下文:JSON數據,第1行:#... 18:13:52 web.1 | :插入“規則”(“名稱”,“條件”,“ created_at”,“ updated_at”)值($ 1,$ 2,$ 3,$ 4)返回“ id” 18:13:52 web.1 | (0.5ms)回滾

請記住,數據庫適配器會為您處理某些序列化任務。 例如:PostgreSQL中的json和jsonb類型將在JSON對象/數組語法與Ruby Hash或Array對象之間透明地轉換。 在這種情況下,無需使用序列化。
-api.rubyonrails.org

不要對本地JSON / JSONB列使用serialize 它的意思是與字符串列一起用作窮人替代。

您試圖做的事情實際上超出了ActiveRecord的范圍-AR是圍繞關系模型構建的,其中模型與表相對應。 而且,您不能指望AR會有任何規定將JSONB列解組為基本標量類型以外的任何內容。 我會考慮,相對於為關系創建一個單獨的表,您所做的工作是否真的值得付出努力?

您正在使用ActiveModel :: Model處於正確的軌道,它將為您的模型提供與常規模型相同的行為,但是您應該看看ActiveRecord如何處理嵌套屬性

class Rule < ApplicationRecord
  def conditions_attributes=(attributes)
    attributes.each do |a|
      # you would need to implement this method
      unless RuleCondition.reject_attributes?(a)
        self.conditions << RuleCondition.new(c)
      end
    end
  end
end

您可以通過創建設置器/獲取器來模仿關聯的其他方面。

但是話又說回來,您可以只創建一個帶有JSONB列和一對多或m2m關聯的rule_conditions表,而實際上將您的時間花在生產上。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM