Project

octojson

0.0
No commit activity in last 3 years
No release in over 3 years
Set a schema, defaults, and validations for your json attributes
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

Runtime

>= 6.0.3.1
>= 0.18.1
 Project Readme

Octojson

Supercharge jsonb attributes with defaults and schemas based on another ActiveRecord attribute. Inspired by jsonb_accessor

Installation

Add to your Gemfile:

gem 'octojson'

Then you can add octojson to your model(s):

class Post < ActiveRecord::Base
  YOUR_SCHEMA = { 
    type_one: {
      title: { type: :string, default: 'Title -- one' },
      text_one: { type: :string, default: 'something cool -- one' },
      boolean_one: { type: :boolean, default: false },
      number_one: { type: :integer, default: 3, validates: { numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 5 } } },
      json_one: { type: :json, default: {}, nested_attributes: [:nested_one, :nested_two, :nested_three] },
    },  
    type_two: {
      title: { type: :string, default: 'Title -- two' },
      text_two: { type: :string, default: 'something cool -- two' },
      boolean_two: { type: :boolean, default: true },
    },
    type_three: {
      title: { type: :string, default: 'Title -- three' },
      text_three: { type: :string, default: 'something cool -- three' }
    }
  }.freeze

  octojson :settings, YOUR_SCHEMA, :post_type
end

post = Post.new(post_type: 'type_one')
post.save
post.settings['title'] # => "Title -- one"
post.settings['text_one'] # => "something cool -- one"
post.settings['boolean_one'] # => false
post.settings['number_one'] # => 3
post.settings['json_one'] # => {}

post = Post.new(post_type: 'type_two')
post.save
post.settings['title'] # => "Title -- two"
post.settings['text_two'] # => "something cool -- two"
post.settings['boolean_two'] # => true
post.settings['text_one'] # => nil

Usage

Validations are cool too! Use Rails validations as you would on directly on record's attributes.

class Post < ActiveRecord::Base
  YOUR_SCHEMA = { 
    type_one: {
      count: { type: :integer, default: 3, validates: { numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 5 } } },
    },  
    type_two: {
      count: { type: :integer, default: 10, validates: { numericality: { only_integer: true, greater_than_or_equal_to: 5, less_than_or_equal_to: 15 } } },
    }
  }.freeze

  octojson :settings, YOUR_SCHEMA, :post_type
end

Sometimes you don't need support for different attributes values. _default can be used instead to get the benefits of a schema with defaults and enforced nested_attributes.

class Post < ActiveRecord::Base
  OPTIONS_SCHEMA_AS_DEFAULT = { 
    _default: {
      title: { type: :string, default: 'default title' },
      number_default: { type: :integer, default: 3, validates: { numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 5 } } },
      sub_options: { type: :array, default: [], nested_attributes: [:name, :type] }
    }
  }.freeze

  octojson :options, OPTIONS_SCHEMA_AS_DEFAULT
end

Use JSONB_ATTRIBUTE_strong_params with your controller strong params

class PostsController < ActiveController::Base
  
  def set_post
    @post = @post.find(params[:id])
  end

  def post_params
    params.require(:post).permit(settings: @post.settings_strong_params)
  end
end

Dependencies

Tests

Run bin/setup to install dependencies.

$ rake test

** ensure postgres is running

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Add tests and changes (run the tests with rake)
  4. Commit your changes (git commit -am 'Add some feature')
  5. Push to the branch (git push origin my-new-feature)
  6. Create a new Pull Request