Rails 4 – 将地址保存为数据库中的一列

我是rails的新手,也是一个简单的应用程序。 我的ERD中有一个名为Client的模型,并希望保存每个客户端的地址。

我最初的想法是将地址保存为单独的字段,即:

rails g model Client address_first:string address_second:string city:string ... 

但这似乎效率很低。 我确定必须有一种方法来保存地址哈希,数组或者JSON? 我已经阅读过并且人们一直在指使用“序列化”,但我不确定是否以及如何为地址字段实现此function。

非常感激任何的帮助。

谢谢

这取决于您使用的数据库–MySQL和Postgres都有JSON列类型 – Postgres也有一个名为hstore的哈希类型。

它们在hash / json列中也有不同的查询选项。 虽然这些数据类型非常适合动态数据 – 但没有真正的性能提升(实际上可能更慢)。

而且你不能对存储在hstore / json列中的属性使用对象映射,validation等所有的轨道优点。

当涉及到地址时,每个人都天真地将其放入用户(或客户端或客户)模型中,以发现在现实世界中您需要多个地址。

 # == 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 

为了进一步提出Max's建议,我想补充一点,如果需要, 可以在单个模型中包含地址信息。

拥有多个模型很酷,但如果您确定只需要Client某些属性,则可以尝试将选项的散列保存到其中的列中。


SQL

要直接回答您的问题,并详细说明Max的建议,您可以使用多种列类型,具体取决于您使用的SQL的变体。

PostgreSQL (Heroku使用它)具有hstorejson列类型。

这两个都为您提供了一个列,允许您存储单个序列化对象,允许您使用序列化数据填充此对象:

在此处输入图像描述

我以前从未在PGSQL上使用过这个function,所以你最好阅读这篇关于如何在HSTOREJSON列类型之间进行选择的博客文章 。

大多数人使用的MYSQL也具有存储JSON的能力:

从MySQL 5.7.8开始,MySQL支持本机JSON数据类型,可以有效访问JSON(JavaScript Object Notation)文档中的数据。 与在字符串列中存储JSON格式字符串相比,JSON数据类型具有以下优势:

这似乎与PGSQL兄弟的工作方式相同。


如果你选择其中一个(你可以使用以下设置):

 #clients #id | name | email | address (json) | created_at | updated_at 

…它将使您能够将JSON格式的对象插入address列。

现在,正如Max所指出的,这将阻止您在address列上运行validations和其他属性级逻辑。 它将阻止您通过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 %> 

fields_for here: 如何编辑表单中的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 

如果您希望地址在应用程序中发挥重要作用(IE,如果它们将要发送到它等),我只会推荐这个。

如果您使用任何其他非重要forms的地址,我会将其保留为序列化哈希。