【问题标题】:User-Generated Models in RailsRails 中的用户生成模型
【发布时间】:2015-12-17 03:29:53
【问题描述】:

我正在尝试创建一个数据库来跟踪用户的项目。

例如,用户可能想要跟踪他们的汽车及其颜色、品牌和年份。他们将首先创建一个汽车“模型”,现在他们可以根据需要添加任意数量的新车。当他们制造汽车时,系统会提示他们输入颜色、品牌和年份以及通用项目信息。

用户可能还想跟踪他们的猫。但是猫“模型”与汽车“模型”有不同的领域。也许他们需要跟踪他们的猫的体重和品种。当他们想将 cat 类型的项目添加到数据库中时,我会提示他们输入重量和品种,而不是颜色、品牌和年份。

我对 Rails 或 SQL 不是很有经验,但我在想,当用户告诉我他们想要跟踪汽车时,我可以创建一个带有颜色品牌和年份的汽车表。当他们输入汽车时,我会将汽车存储为通用项目,并保留对汽车表的引用,我将在其中存储颜色品牌和年份。虽然不太确定我将如何实施,所以我对任何新想法持开放态度。在此先感谢您的帮助。

【问题讨论】:

  • 您正在寻找多表继承。有几个 gem 可以使其更容易实现:github.com/hzamani/acts_as_relation
  • @BroiSatse 我查看了自述文件,看起来如果我想添加一种新型产品(即:“笔”),我需要在后端创建类。我希望有一种方法可以通过用户输入来创建产品类型。
  • 啊,我明白了。在这种情况下,SQL 数据库在这里并不好,因为它需要具有固定模式的表。您正在寻找 NoSQL,mongo 可能是一个不错的选择 - 它允许您在单个索引中创建具有不同模式的记录。您可以尝试在 SQL 中实现它,但这需要大量工作。
  • Broistatse 如果你用多表的东西回答,我会为你投票

标签: ruby-on-rails


【解决方案1】:

您非常正确,您需要为汽车和猫创建一个表,每个表都有自己的列。 Rails 带有 Active Record 以方便创建数据库。活动记录真的很容易使用并且有一些很棒的documentation。 例如,要为汽车创建表,您必须首先创建汽车模型。 要让 Active Record 创建模型,您只需在终端中使用以下命令:

$ rails g model Car color:string make:string year:integer

这个模型存储在 app/models.创建模型后不要忘记迁移数据库。 为了让用户输入实例的属性,您需要使用 form_for。可以在 here 找到 form_for 的文档。要使用 form_for,您需要声明要更改的模型的实例以及提交表单后要使用的方法。然后,您使用一些与实例的属性相关联的输入字段进行跟进。文档中的示例是一个非常好的示例。

<%= form_for @article, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
    <%= f.text_field :title %>
    <%= f.text_area :body, size: "60x12" %>
    <%= f.submit "Create" %>
<% end %>

【讨论】:

  • 这很好地解释了如何在 Rails 中制作模型和表单。但是,当用户想要在后端创建新的项目类型时,我不想生成新模型。我希望允许用户通过应用程序本身指定他们的项目类型的属性(即:颜色、品牌、型号)。然后,这些将允许他们在未来保存新项目。
【解决方案2】:

我一直在玩一个叫做Meta 模型的东西——你有app/models/meta.rb,它允许你调用用户在数据库中定义的模型。

我已经运行了这个,但它不是超级有效。

我会告诉你的;也许它会给你一些想法......

--

每个模型都可以精简为一组 2 个通用属性 - titlevalue

#app/models/node.rb
class Node < ActiveRecord::Base
   # columns id | type | title | value | created_at | updated_at
end

这是您希望使用的模型的非常基础(car / cat 等)。

例如,您可以让node 具有以下统计信息:

# id | type      | title | value            | created_at | updated_at
# 1  | Meta::Cat | Greg  | A new cat we got | 15/12/2015 | 15/12/2015
# 2  | Meta::Cat | Pip   | A little kitten  | 16/12/2015 | 16/12/2015
# 3  | Meta::Car | F480  | The red Ferrari  | 10/12/2015 | 10/12/2015

这将为您提供一组基本数据,然后您可以将不同的关联附加到这些数据上。

是的,新的关联也可以存储在node 数据表中。

所以事实上,你可以有以下几点:

#app/models/meta.rb
class Meta
    classes = %w(cat car)
    if classes.any?
        classes.each do |klass| #-> "class" is reserved
            self.const_set klass.titleize, Class.new(Node) do
                belongs_to :user
            end
        end
    end
end

这将以编程方式创建CatCar 类,可以根据需要使用Meta::Cat 等调用。

我想这就是您获得不同“基础”模型的方法。

如果您想为其添加额外的关联,则必须有额外的数据以确保您知道每个模型具有哪些关联。

我还没有这样做,但正如你在上面看到的,你可以调用一个块,它基本上允许你在伪类中定义不同的东西:

--

因此,如果您有另一个名为 Option 的元类,您可以使用它来设置其他类的关联:

# 2  | Meta::Option | association | has_many :x   | 16/12/2015 | 16/12/2015
# 3  | Meta::Option | association | belongs_to :y | 10/12/2015 | 10/12/2015

我仍然需要考虑它如何匹配关联,但简而言之,您将能够执行以下操作:

#app/models/meta.rb
class Meta
    classes = %w(cat car)
    if classes.any?
        classes.each do |klass| #-> "class" is reserved
            self.const_set klass.titleize, Class.new(Node) do
                #-> Node.where(name: "association").pluck(:value)
            end
        end
    end
end

这被称为metaprogramming(或者它可能是伪编程)并且是可以完成的;它是否有效完全是另一个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 2013-04-18
    • 2014-04-12
    • 2011-05-08
    • 1970-01-01
    • 2015-06-23
    相关资源
    最近更新 更多