如何设计应允许用户创建多个字段的模型?

时间:2016-01-23 22:45:48

标签: ruby-on-rails forms ruby-on-rails-4

我有一个Review模型。我的用户应该能够撰写评论。 Review#New的视图应该是管理员事先创建的带有文本字段的表单。

换句话说,我的admin-user应该能够创建具有不同字段的Review模型的多个实例,甚至可能是不同的输入类型(字符串,整数等)。这样,当普通用户登录时,他们会看到管理员用户为数据收集指定的不同表单字段。

当然,所有这些都应存储在数据库中,以便在存储的上下文中进行检索(也就是特定模型)。

在Rails中处理此问题的最佳方式是什么?

将其视为调查表和调查表构建者。

如果我能用简单形式做到这一点会很好,但这并不是一个要求。

修改1

以下是他们应该能够添加到评论中的字段类型的示例:

enter image description here

2 个答案:

答案 0 :(得分:3)

根据我的经验,通过简单地找到正确的名称来帮助数据库设计的很大一部分。在你的情况下,我认为你正在考虑调查或测验的正确轨道。

查看survey gem的想法。其中基础模型是Surveys。调查有很多问题。问题有很多选项。调查也有许多尝试,回答调查。尝试然后有很多答案。

因此,您的必然结果可能是评论/评估(由管理员创建)可能有许多标准/查询(可能有不同类型,但我们会在一分钟内完成)。然后,您的用户将创建属于特定评论/评估的响应/评估,并有许多答案/回复。

对于不同的问题类型(简答,李克特评分,1-10,标签列表等),您可以在条件/查询中使用多态。

希望我用过的其中一些名字会对你有所帮助。随意使用词库获得更多灵感。

EDIT Re:Polymorphism

免责声明:根据您的应用程序,多态性可能过度。

当然,我会扩展一些。不完全是。如果您还没有,请查看polymorphism上的导轨指南。我想你想要的是

class Criterion < ActiveRecord::Base
  belongs_to :askable, polymorphic: true
end

然后我会为每个问题/标准类型制作一个模型。例如:

class ShortAnswer < ActiveRecord::Base
  has_many :criteria, as: :askable
end
class Likert < ActiveRecord::Base
  has_many :criteria, as: :askable
end

旁注:如果rails没有正确地将条件多元化为条件,则可能需要将以下内容添加到config / initializers / inflections.rb文件中

ActiveSupport::Inflector.inflections do |inflect|
  inflect.irregular 'criterion', 'criteria'
end

答案 1 :(得分:2)

Scratch solution。

根据我的经验,最简单的解决方案是使用hstorejsonjsonb类型的字段。 这个解决方案适用于Postgresql数据库。 要实现此方法,您需要在Review模型中添加字段。

迁移:

# Reviews
def change
  add_column :reviews, :structure, :json
end

# Answers
def change
  add_column :answers, :values, :hstore
end

然后你可以定义模型ReviewStructure普通红宝石类,在这里你可以使用Virtus gem来轻松地序列化它:

class ReviewStructure
  include Virtus.model
  attribute :fields, Array[Field]

  class Field
    include Virtus.model

    attribute :name
    attribute :type
  end
end

然后在Review中定义结构字段的序列化:

class Review < ActiveRecord::Base
  ...
  serialize :structure, ReviewStructure
end

然后,您可以使用review.structure.fields访问评论的结构字段。

在视图中,您可以使用简单的表单

<% simple_form_for @answer do |f| %>
  <% @review.structure.fields.each do |field|  %>
    <% f.input "values[#{field.name}]", as: field.type %>
  <% end %>
<% end %>

要访问答案结果,只需使用:

answer.values.each do |field_name, value|
  ...
end

注意:

至于管理员,最好在客户端(使用js)处理审核结构的创建,并通过API发布纯JSON结构。

通过这种方法,您将能够创建具有不同类型字段的测验。

注意:

请记住,当前实施将一个评论连接到一个答案,假设答案模型包含用户响应的所有值。