![](/img/trans.png)
[英]How do I create a Rails 3 model backed by a database table without having its attributes dynamically generated by ActiveRecord?
[英]Rails nested model conversion to and from database without its own table
背景:在閱讀了Ruby中的《面向對象的實用設計》之后,我試圖重構我的代碼(很棒),為此,我想引入更多的封裝責任的模型,而不是使用帶有邏輯的單個大文件(和案例說明)。
問題:為了簡化問題說明,我有一個模型Rule
,它“有很多” RuleConditions
。 但是,數據庫中只有一個表用於規則。 在這里面,我有這類型的條件的欄jsonb
(根據並發症RuleCondition
)。 但我似乎無法實現這一目標。 具體來說, 我無法弄清楚如何使用嵌套模型實例化模型,並希望ActiveRecord知道如何將模型轉換為jsonb,甚至可能從表轉換回嵌套模型 。 我也不知道是否可以在沒有表的情況下使用ActiveRecord定義has_many
關系。
我的期望:
我希望應該有一些流程(由ActiveRecord和ActiveModel混合定義),以使該流程成為可能
Rule
參數。 RuleConditions
數組。 Rule.new(rule)
,其中rule包含:conditions => RuleCondition
rule.save!
conditions
屬性的嵌套RuleConditions
模型重建Rule
。 我嘗試過的
我以為可以讓我半途而廢的是serialize, :conditions, JSON
,但是它很難序列化我的對象。 在那之后,我真的不知道。 我也玩過ActiveModel :: Conversion。 所以我只需要一些指導。
而且,要清透,呼吁as_json
我RuleCondition
就像我期待它(打印出所用的是儲存在同一個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.