1

誰かが私のためにこのアプローチを批判していただければ幸いです。

Wufooのように、ユーザーがいくつかの属性を定義し、ユーザーと共有するフォームを生成できるアプリケーションを構築しています。

これが私のアプローチです。

ユーザー has_many ソース & ソースembeds_many source_attributes

ここでは、すべてのユーザー定義フィールドが SourceAttributes に格納されています。フォームを生成する必要があるときは、このようにオンザフライでモデルを生成します。

#source.rb

def initialize_set
model_name = self.set_name.gsub(' ','').classify

# Unique Class name
klass_name = "#{model_name}#{self.user.id}"
object = self

klass = Class.new do
  include Mongoid::Document

 # Collection names have to be set manually or they don't seem to work
  store_in collection: self.collection_name

 # Pick up attributes from SourceAttribute & define fields here
  object.source_attributes.each do |m|
    field m.field_name.gsub(' ','').underscore, type: object.class.mapping[m.field_type]
  end


  def self.collection_name
    self.name.tableize
  end

 end

 # I get a warning here when the class is re-loaded. Should i worry? I'm considering Object.send :remove_const here
 Object.const_set klass_name, klass

end

このアプローチでは、ユーザーが定義するフォームごとに個別のコレクションを作成します。これはうまくいくようですが、いくつか問題があります。

  • タイプの安全性

上記で生成したフィールドは、タイプ セーフではないようです。文字列を整数フィールドに保存できます。

タイプは正しく設定されているようです。klass でフィールドを呼び出し、options[:type] 属性をチェックすることで、これを再確認しました。

シンプルなフォームを使用していますが、タイプが自動的に認識されません。次のように明示的に言及する必要があります。

  • スケーラビリティ

その場でモデルを生成するという私のアプローチが正しいかどうかはわかりません。これを使っている人を見たことがありません。

別の質問に移動しました。コメントを確認してください。

更新 1:

だから私は間違っていました。私のモデルはタイプ セーフですが、静かに失敗するようです。例外をスローさせる方法はありますか?

# age is correctly defined as an Integer
klass.fields.slice "age"
=> {"age"=>#<Mongoid::Fields::Standard:0xb7edf64 @name="age", @options={:type=>Integer, :klass=>Engineer50bc91a481ee9e19ab000006}, @label=nil, @default_val=nil, @type=Integer>}

# silently sets age to 0
 klass.create!(age: "ABC")
 => #<Engineer50bc91a481ee9e19ab000006 _id: 50cff12181ee9e16f1000003, _type: nil, employee_code: nil, name: nil, age: 0, years: nil, number: nil>

 # returns true when saved
 object = klass.new
 object.age = "ABC"
  => "ABC" 
 object.save
  => true 

PS: mongoid を使うのはこれが初めてです :)

更新 2:

整数検証に関する私の問題は、mongoid ではなく Ruby にある可能性があります。

前回の更新で述べたように、

# silently sets age to 0
klass.create!(age: "ABC")
 => #<Engineer50bc91a481ee9e19ab000006 _id: 50cff12181ee9e16f1000003, _type: nil, employee_code: nil, name: nil, age: 0, years: nil, number: nil>

「ABC」はタイプキャストされていると思います

"ABC".to_i
 => 0 

このように validates_numericality_of を使用して、この問題を克服しようとしました

object.model_attributes.where(field_type: "Number").map(&:field_name).each do |o|
 validates_numericality_of o.gsub(' ','').underscore.to_sym
end

残念ながら、これは存在もチェックします。この回避策を試しました

validates_numericality_of o.gsub(' ','').underscore.to_sym, allow_nil: true

しかし、これは数値検証を完全に無視します。allow_blank も試してみましたが、うまくいきませんでした。

4

0 に答える 0