byroot / activerecord-typedstore

ActiveRecord::Store but with type definition
MIT License
439 stars 57 forks source link

Add example for usage with Postgres jsonb columns #44

Open Jurawa opened 8 years ago

Jurawa commented 8 years ago

Just wanted to let you know I had some issues getting this setup when using a Postgres jsonb column...

My first implementation did not include a custom coder, and when updating a typed_store attribute, I got this error:

ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR:  invalid input syntax for type json
DETAIL:  Token "-" is invalid.
CONTEXT:  JSON data, line 1: -...
: UPDATE "companies" SET "settings" = $1, "updated_at" = $2 WHERE "companies"."id" = $3

Which is because it was using the default yaml coder.

However, when I added the DumbCoder, I got a TypeError: can't cast Hash to error.

It was all solved by just using the JSON coder:

typed_store :settings, coder: JSON do |s|
    s.boolean :foo, default: true, null: false
end

I think this would be useful to add to the readme...

Cheers!

rainerborene commented 6 years ago

+1 @rafaelfranca

dinatih commented 6 years ago

But the json string seems escaped with coder: JSON :/

rafaelfranca commented 6 years ago

I'm not a PostgreSQL user. I'm fine with adding it, but to be fair I don't know the solution for the problem so I'd rely on someone sending a PR.

jcw- commented 5 years ago

The following JSONB example includes:

# won't need to do this require in the next release of `activerecord-typedstore`
require 'active_record/typed_store/identity_coder'

class Foo < ApplicationRecord
  typed_store :details, coder: ActiveRecord::TypedStore::IdentityCoder do |s|
    s.boolean :public, default: false, null: false
    s.string :email
    s.datetime :publish_at
    s.integer :age, null: false

    # You can define array attributes like in rails 4 and postgres
    s.string :tags, array: true, default: [], null: false

    # In addition to prevent null values you can prevent blank values
    s.string :title, blank: false, default: 'Title'

    # If you don't want to enforce a datatype but still like to have default handling
    s.any :source, blank: false, default: 'web'
  end

  # You can use any ActiveModel validator
  validates :age, presence: true
end

Migration: bin/rails generate migration CreateFoo details:jsonb

Using the class from a console (mine has a name field and timestamps, you can ignore them): image