ruby on rails jsonb列的默认值

时间:2016-06-23 09:04:39

标签: ruby-on-rails postgresql activerecord jsonb

我有一个模型ProjectKeyword,我在:segemnted_data列中使用jsonb数据类型

class ProjectKeyword < ApplicationRecord
  belongs_to :project
  belongs_to :keyword
  has_many :project_keyword_dimensions
  has_many :dimensions, through: :project_keyword_dimensions

  validates :project_id, :keyword_id, presence: true
end

迁移

class AddSegemtnedDataToProjectKeywords < ActiveRecord::Migration[5.0]
  def change
    add_column :project_keywords, :segmented_data, :jsonb, default: '{}'
    add_index  :project_keywords, :segmented_data, using: :gin
  end
end

我的问题是当我创建新的project_keyword实例时,segmented_data的默认值是字符串而不是哈希,我无法更新此字段或与其他哈希合并 例如

[12] pry(#)> new_pr_keyword = ProjectKeyword.new(project_id: 1671333, keyword_id: 39155)
=> #<ProjectKeyword:0x007fd997641090 id: nil, project_id: 1671333, keyword_id: 39155, segmented_data: "{}">
[13] pry(#)> new_pr_keyword.save!
=> true
[14] pry(#)> new_pr_keyword.segmented_data.update({'new_data' => 'some_data'})
NoMethodError: undefined method `update' for "{}":String
from (pry):14:in `block (3 levels) in <top (required)>'

但是,当我在更新之前将hash值设置为字段segmented_data时,update方法可以正常工作。

例如

[15] pry(#)> new_pr_keyword.segmented_data = {'new_data' => 'some_data'}
=> {"new_data"=>"some_data"}
[16] pry(#)> new_pr_keyword.save!
=> true
[17] pry(#)> new_pr_keyword.segmented_data.update({'new_data_2' => 'some_data_2'})
=> {"new_data"=>"some_data", "new_data_2"=>"some_data_2"}
[18] pry(#)> new_pr_keyword.save!
=> true

问题是如何将segmented_data的默认值设置为Hash类而不是String,因此方法更新将在创建对象之后立即在此字段上工作。

1 个答案:

答案 0 :(得分:26)

这在几个项目中对我有用:

add_column :project_keywords, :segmented_data, :jsonb, default: {}

(不是字符串,红宝石哈希)

我似乎记得这不适用于Rails 3,但它在Rails 4中应该没问题。