Cra*_*aig 4 hash json ruby-on-rails street-address ruby-on-rails-4
我是rails的新手,也是一个简单的应用程序.我的ERD中有一个名为Client的模型,并希望保存每个客户端的地址.
我最初的想法是将地址保存为单独的字段,即:
rails g model Client address_first:string address_second:string city:string ...
Run Code Online (Sandbox Code Playgroud)
但这似乎效率很低.我确定必须有一种方法来保存地址哈希,数组或者JSON?我已经阅读过并且人们一直在指使用"序列化",但我不确定是否以及如何为地址字段实现此功能.
非常感激任何的帮助.
谢谢
这取决于您使用的数据库--MySQL和Postgres都有JSON列类型 - Postgres也有一个名为hstore的哈希类型.
它们在hash/json列中也有不同的查询选项.虽然这些数据类型非常适合动态数据 - 但没有真正的性能提升(实际上可能更慢).
而且你不能对存储在hstore/json列中的属性使用对象映射,验证等所有的轨道优点.
当涉及到地址时,每个人都天真地将其置于用户(或客户端或客户)模型中,仅发现在现实世界中您需要多个地址.
# == Schema Information
#
# Table name: clients
#
# id :integer not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
#
class Client < ActiveRecord::Base
has_many :addresses
end
# == Schema Information
#
# Table name: addresses
#
# id :integer not null, primary key
# address_first :string
# address_second :string
# street :string
# city :string
# country :string
# client_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class Address < ActiveRecord::Base
belongs_to :client
end
Run Code Online (Sandbox Code Playgroud)
为了进一步Max's提出建议,我想补充一点,如果需要,您可以在单个模型中包含地址信息。
拥有多个模型很酷,但如果您确定您只需要某些属性Client,您可以努力将选项散列保存到其中的列中。
要直接回答你的问题,并就最大的建议阐述,也有可以使用几种列类型,取决于你使用的SQL的变种。
PostgreSQL(Heroku 使用它)具有hstore和json列类型。
这两个都为您提供了一个列,允许您存储单个序列化对象,允许您使用序列化数据填充此对象:
我以前从未使用过此功能PGSQL,因此您最好阅读这篇关于如何在HSTORE和JSON列类型之间进行选择的博文。
——
从 MySQL 5.7.8 开始,MySQL 支持原生 JSON 数据类型,可以有效访问 JSON(JavaScript Object Notation)文档中的数据。与将 JSON 格式的字符串存储在字符串列中相比,JSON 数据类型具有以下优势:
这似乎与其 PGSQL 兄弟的工作方式相同。
如果您确实选择其中之一(您可以使用以下设置):
#clients
#id | name | email | address (json) | created_at | updated_at
Run Code Online (Sandbox Code Playgroud)
...它将使您能够将 JSON 格式的对象插入到address列中。
现在,正如 所指出的Max,这将阻止您validations在address列上运行和其他属性级逻辑。它会阻止您通过 ActiveRecord 查找此列,并且将很难以任何其他方式使用此数据,而不仅仅是存储它。
因此,如果您绝对确定要以这种方式存储它,则可以使用以下方法来做到这一点:
#app/models/client.rb
class Client < ActiveRecord::Base
serialize :address
end
#app/controllers/clients_controller.rb
class ClientsController < ApplicationController
def new
@client = Client.new
end
def create
@client = Client.new client_params
@client.save
end
private
def client_params
params.require(:client).permit(:name, :email, address:{})
end
end
#app/views/clients/new.html.erb
<%= form_for @client do |f| %>
<%= f.text_field :name %>
<%= f.email_field :email %>
<%= f.fields_for :address, OpenStruct.new(f.object.address || {}) do |address| %>
<%= address.text_field :street %>
<%= address.text_field :other_data %>
<% end %>
<%= f.submit %>
<% end %>
Run Code Online (Sandbox Code Playgroud)
fields_for此处可用:如何编辑表单中的 Rails 序列化字段?
正如 Max 所指出的,另一种方法是使用多个模型。
这虽然看起来不错,但实际上是一个非常微妙的过程。许多人开始为所有内容插入模型,很快您的应用程序就充满了不做任何事情的模型。
如果您想使用模型,最好使用以下方法:
#app/models/client.rb
class Client < ActiveRecord::Base
#columns id | name | email | etc | created_at | updated_at
has_one :address
before_create :build_address, unless: Proc.new { |client| client.address }
end
#app/models/address.rb
class Address < ActiveRecord::Base
#columns id | client_id | your | address | columns | here | created_at | updated_at
belongs_to :client
end
Run Code Online (Sandbox Code Playgroud)
如果您希望地址在应用程序中发挥重要作用,我只会推荐这个(IE,如果他们要运送到它等)。
如果您以任何其他不重要的形式使用该地址,我会将其保留为序列化哈希。