Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ruby on rails jsonb column default value

I have a model ProjectKeyword where I use jsonb datatype in the column :segemnted_data

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 

Migration

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 

My problem is when I create new project_keyword instance the default value of the segmented_data is a string not a hash and I cannot update this field or merge with another hash For example

[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)>' 

But when I asign hash value to the field segmented_data before update then update method works fine.

For example

[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 

The question is how to make default value of segmented_data to be a Hash class not a String so method update then will work straight away on this field, after object just was created.

like image 540
arthur-net Avatar asked Jun 23 '16 09:06

arthur-net


People also ask

Is Jsonb faster than JSON?

Json processes input faster than jsonb as there is no conversion involved in this. Jsonb converts the JSON data into the binary form so it has slightly slower input due to the binary conversion overhead. There is no change in the Schema design while working with JSON.

What is Jsonb format?

The JSONB data type stores JSON (JavaScript Object Notation) data as a binary representation of the JSONB value, which eliminates whitespace, duplicate keys, and key ordering. JSONB supports GIN indexes.

Should I use JSON or Jsonb?

In general, most applications should prefer to store JSON data as jsonb , unless there are quite specialized needs, such as legacy assumptions about ordering of object keys. RFC 7159 specifies that JSON strings should be encoded in UTF8.

How is Jsonb stored?

JSONB objects are stored as a decompressed binary as opposed to "raw data" in JSON, where no reparsing of data is required during retrieval. JSONB also supports indexing, which can be a significant advantage.


1 Answers

This has worked for me on several projects:

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

(not a string, a ruby hash)

I seem to recall this not working on Rails 3, but it should be fine in Rails 4.

like image 95
Paul A Jungwirth Avatar answered Sep 19 '22 09:09

Paul A Jungwirth