Techioz Blog

Rails - 動的フォームを構築するためのアプローチ [終了]

概要

私はユーザーがフォームを「デザイン」できるRailsアプリに取り組んでいます。以下の画像を参照してください。

このために次のモデルがあります。

class ProgramPart < ApplicationRecord
  has_many :block_elements, dependent: :destroy

class BlockElement < ApplicationRecord
  belongs_to :program_part

  enum element_types: {
    rich_content: 0,
    textfield: 1,
    textarea: 2
  }

  has_rich_text :content

動的なフォームをユーザーにどのように表示するのか、どのようなアプローチを使用すればよいのか、よくわかりません。

現在持っているもの:

<%= form_with [how should my form look when inputs are dynamic?] %>
  <% @program_part.block_elements.each do |block| %>
      
    <% if block.element_type == BlockElement.element_types[:rich_content] %>
      <%= block.content %>
    <% elsif block.element_type == BlockElement.element_types[:textfield]  %>

      <%= block.question %>
      <!-- not sure how this should look -->
      <%= @form_builder.text_field(:answer_value)%>
        
    <% elsif block.element_type == BlockElement.element_types[:textarea]  %>
      <!-- textarea -->
    <% end %>

  <% end %>

<% end %>

誰か似たようなことを実装した人、またはそれに関する良いリソースを知っている人はいますか?

解決策

管理者が構成してクライアントが使用できるフォームで同様のことを実装しました。基本は次のとおりです。

次のように、抽象的な Page オブジェクト、抽象的な DOM オブジェクト、そして各 DOM 要素のオブジェクトが必要です。

class PageTemplate
  has_many :dom_objects
end

class DomObject
  self.table_name = 'dom_objects'
  belongs_to :page_template
  
  def dom_type
    nil
  end
end

class TextField < DomObject
  self.table_name = 'dom_objects'

  def dom_type
    'text_field'
  end
end
class TextArea < DomObject
  self.table_name = 'dom_objects'

  def dom_type
    'text_area'
  end
end

dom_type は、レンダリングする必要があるオブジェクトのタイプをシステムに伝えるものになります。もちろん、これも DB に保存する必要がありますが、抽象的なオブジェクトの代わりに text_field オブジェクトを追加する場合は、データベース フィールドに型を自動的に入力するのに役立ちます。ご覧のとおり、すべての静的 dom オブジェクトは抽象 DomObject からネストされています。これは基本的に、作成されたすべての dom オブジェクトのテーブルです。幅、高さ、追加の CSS クラスなどの情報をパラメータとして dom オブジェクト テーブルに追加することもでき、作成されたすべての dom 入力を独自の高度にカスタマイズ可能なエンティティにすることができます。

まとめ

このアプローチはオブジェクト指向であり、設計上複合的です。それぞれの「レンガ」を設定し、JS で動的に「壁」を組み立てるだけで、DB にきれいに保存されます。次に、db からページ オブジェクトを取得し、必要な場所にレンダリングするだけです。

それが役に立てば幸い! :)