activeadmin和动态存储访问器在新资源上失败

问题描述 投票:0回答:1

我想为具有postgres jsonb列:data的资源生成表单,并且希望将这些表单的模式存储在数据库的表中。经过大量研究,我在那里的占90%,但是我的方法在创建(未更新)时在ActiveAdmin表单中失败。有人可以解释吗?

很抱歉,很长的代码段。这是一个相当复杂的设置,但是我认为这会引起一些兴趣,因为如果这样可以有效地构建动态新的任意模式而无需进行硬编码。

我正在this previous discussion上使用Rails 6和ActiveAdmin 2.6.1和ruby 2.6.5。

我想将Json Schema存储在属于SampleAction的表SampleActionSchema中(使用json-schema gem进行验证)

class SampleActionSchema < ApplicationRecord
  validates :category, uniqueness: { case_sensitive: false }, allow_nil: false, allow_blank: true
  validate :schema_is_json_schema

  private

  def schema_is_json_schema
    metaschema = JSON::Validator.validator_for_name("draft4").metaschema
    unless JSON::Validator.validate(metaschema, schema)
       errors.add :schema, 'not a compliant json schema'
    end
  end
end
class SampleAction < ActiveRecord::Base
  belongs_to :sample

  validate :is_sample_action
  validates :name, uniqueness: { case_sensitive: false }

  after_initialize :add_field_accessors
  before_create :add_field_accessors
  before_update :add_field_accessors

  def add_store_accessor field_name
    singleton_class.class_eval {store_accessor :data, field_name.to_sym}
  end

  def add_field_accessors
    num_fields = schema_properties.try(:keys).try(:count) || 0
    schema_properties.keys.each {|field_name| add_store_accessor field_name} if num_fields > 0
  end


  def schema_properties

    schema_arr=SampleActionSchema.where(category: category)
    if schema_arr.size>0
      sc=schema_arr[0]
      if !sc.schema.empty?
        props=sc.schema["properties"]
      else
        props=[]
      end
    else
      []
    end
  end
  private

  def is_sample_action
    sa=SampleActionSchema.where(category: category)
    errors.add :category, 'not a known sample action' unless (sa.size>0)
    errors.add :base, 'incorrect json format' unless (sa.size>0) && JSON::Validator.validate(sa[0].schema, data)
  end

end

这一切都正常;例如,对于一个名为category:“ cleave”的简单模式,其中:data看起来像data: {quality: "good"},我可以在rails控制台中创建以下资源:

sa=SampleAction.new(sample_id: 6, name: "test0", data: {}, category: "cleave" )
=> #<SampleAction id: nil, name: "test0", category: "cleave", data: {}, created_at: nil, updated_at: nil, sample_id: 6> 

sa.quality = "good"   => true
sa.save => true

为了使该系统以AA形式工作,我用参数调用普通路径(新建或编辑)_admix_sample_action_form:{category:“ cleave”},然后动态生成allow_params:

ActiveAdmin.register SampleAction, namespace: :admix do

  permit_params do
    prms=[:name, :category, :data, :sample_id, :created_at, :updated_at]
    #the first case is creating a new record (gets parameter from admix/sample_actions/new?category="xxx"
    #the second case is updating an existing record
    #falls back to blank (no extra parameters)
    categ = @_params[:category] || (@_params[:sample_action][:category] if @_params[:sample_action]) || nil
    cat=SampleActionSchema.where(category: categ)
    if cat.size>0 && !cat[0].schema.empty?
      cat[0].schema["properties"].each do |key, value|
        prms+=[key.to_sym]
      end
    end
    prms
  end

form do |f|
    f.semantic_errors
    new=f.object.new_record?
    cat=params[:category] || f.object.category
    f.object.category=cat if cat && new
    f.object.add_field_accessors if new
    sas=SampleActionSchema.where(category: cat)
    is_schema=(sas.size>0) && !sas[0].schema.empty?
    if session[:active_sample]
      f.object.sample_id=session[:active_sample]
    end

    f.inputs "Sample Action" do
      f.input :sample_id
      f.input :name
      f.input :category
      if !is_schema
        f.input :data, as: :jsonb
      else
        f.object.schema_properties.each do |key, value|
        f.input key.to_sym, as: :string
        end
      end
    end
    f.actions
  end

如果我正在编辑现有资源(如在上面的控制台中创建的内容,则一切正常。将显示该表单,并在提交后更新所有动态字段。但是在创建新资源时:data具有以下形式的数据:{quality:“ good”}我得到

ActiveModel::UnknownAttributeError in Admix::SampleActionsController#create
unknown attribute 'quality' for SampleAction.

我尝试了两种形式的add_accessors并重写了初始化初始化后添加访问器的新命令(由于ActiveRecord回调似乎在正确的时间完成了工作,因此不需要这些)。>>

def new
  build_resource
  resource.add_field_accessors
  new!
end

以某种方式在AA控制器中创建资源后,即使在控制台中工作正常,似乎也无法存储访问器。有没有人有正确初始化资源的策略?

我想为具有postgres jsonb列:data的资源生成表单,并且希望将这些表单的模式存储在数据库的表中。经过大量研究,我在那里90%...

ruby-on-rails dynamic activeadmin jsonschema jsonb
1个回答
0
投票

解决方案:

© www.soinside.com 2019 - 2024. All rights reserved.