在数据库中存储列表项详细信息?

时间:2018-01-09 21:41:25

标签: ruby-on-rails schema

所以,这可能更像是一个"软件工程"题。但我正在考虑如何在活动记录中存储Widget的详细信息。

假装小工具A有一个展示页面,在该展示页面中我们有一些手风琴式的样式" FAQS"或者那种效果。在手风琴中有一个列表,其中的子弹点突出显示了Widget A如何工作的不同内容,或者如何使用Widget A.

因为显然我们不想为每个小部件创建单独的页面,所以这些项目需要存储在某个地方。但我们也不想为数据库中的每一个创建10,20或30个单独的字段。那么解决方案是什么?

我的第一个想法是某种哈希或数组,但rails是否允许这样做?特别是如果它们是每个项目的长串。有没有更好的办法?

或者这样做的正确方法是将此声称为模型(如..." faq_item")或其他什么,然后为其需要的Widget提供参考ID? (这样" faq_item"模型/架构只需要几个字段,并且可以将引用ID分配给它所属的Widget。

2 个答案:

答案 0 :(得分:1)

如果每个小部件只有少数" FAQ项目" (或"详细信息",因为我将引用它们),每个细节只不过是一个文本字符串,您可以将小部件的详细信息存储在序列化数组中: / p>

# models/widget.rb
class Widget < ApplicationRecord
  # serialize the `details` attribute as JSON into 
  # the `details` column on the widgets table
  serialize :details, JSON
end

# db/schema.rb
# ...
create_table "widgets", force: :cascade do |t|
  t.string   "name"
  t.text     "details"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

# rails console
wid = Widget.create!(
:name => 
'Wideband, Voltage-Feedback Operational Amplifier With Disable',
:details => [
'Flexible supply range: 5-V to 12-V Single Supply, +/- 2.5-V to 5-V Dual Supply',                       
'Unity-Gain Stable: 500 MHz (G = 1)',
'High Output Current: 190 mA',
'High Slew Rate: 1800 V/us',
'Wideband 5-V Operation: 220 MHz (G = 2)'
])
# => #<Widget ...>
wid.details.first
# => "Flexible supply range: 5-V to 12-V Single Supply, +/- 2.5-V to 5-V Dual Supply"

有关serialize的更多信息,请查看Rails 5 serialization API

但是,如果您需要为每个细节存储更多信息(例如,created_at / updated_at字段),或者每个窗口小部件都包含多个细节,那么为您创建窗口小部件详细信息的新表可能是谨慎的。提示:

# models/widget.rb
class Widget < ApplicationRecord
  has_many :details, :dependent => :destroy
end

# models/widget/detail.rb
class Widget::Detail < ApplicationRecord
  belongs_to :widget
end

# db/schema.rb
# ...
create_table "widget_details", force: :cascade do |t|
  t.integer  "widget_id"
  t.text     "content"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

wid = Widget.create!(
:name => 
'CMOS, 125 MHz Complete DDS Synthesizer',
:details => [
Widget::Detail.create!(:content => '125 MHz Clock Rate'),
Widget::Detail.create!(:content => 'On-Chip High Performance DAC'),
Widget::Detail.create!(:content => '32-Bit Frequency Tuning Word')
])
# => #<Widget ...>
wid.details.first
# => #<Widget::Detail ... content: "125 MHz Clock Rate" ...>

答案 1 :(得分:1)

如果您使用的是Postgres,则可以在数据库中使用JSONB类型字段。使用JSONB数据类型,您将能够获得非结构化数据,同时能够使用Postgres和ActiveRecord查询字段,而无需新表。

像这样:

rails g migration add_fields_to_widgets details:jsonb
rails db:migrate

在rails控制台中测试您的小部件创建。

Widget.create(name: "Widget Foo", details: { "how to use": "Instructions on how to use", "height": "12cm", "width": "100cm" })

如果您想要找到12厘米高的所有小部件,您只需要进行如下查询:

Widget.where("details->>'height' = ?", "12cm")

会返回你原来的Widget Foo对象,然后你就可以在你的前端使用纯JavaScript来操作它。