octojson 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7f942e2da4cb45bfacb5affe69154c4431b85a61d1d99c98740daf71af0a4442
4
+ data.tar.gz: 4b8c165ef9fb600bfb99a43f6dd5559fcebb31f40869371fdc99bd5127baf72e
5
+ SHA512:
6
+ metadata.gz: a26204c160edda006f5a3a49a8bc1b8fc5c83887119dafd063d30460ff1a5e00f2ae86d25d584fccd8a757cf4ab015e2f95f6e3f29e1372fda3b637012d9165e
7
+ data.tar.gz: cfaea459b9959e537f6ebc49b43d822bf3cbcd2ed6847cb3bf23512a74c41cb87727b1a257c44a781c9d3918884c02cf582078bf1831a557939aadf3496222b6
@@ -0,0 +1,20 @@
1
+ Copyright 2020 Chris Bacon
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Octojson'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ Bundler::GemHelper.install_tasks
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'lib'
23
+ t.libs << 'test'
24
+ t.pattern = 'test/**/*_test.rb'
25
+ t.verbose = false
26
+ end
27
+
28
+ require "standalone_migrations"
29
+ StandaloneMigrations::Tasks.load_tasks
30
+
31
+ task default: :test
@@ -0,0 +1,71 @@
1
+ require 'active_record'
2
+
3
+ module ActiveRecord
4
+ module Octojson
5
+ extend ActiveSupport::Concern
6
+
7
+ class_methods do
8
+ def octojson(json_attribute, schema, schema_key)
9
+ schema.each do |attribute,data|
10
+ data.each do |key,value|
11
+ define_method("#{json_attribute}_#{attribute}_#{key}") do
12
+ self[json_attribute][key.to_s]
13
+ end
14
+
15
+ if value[:validates]
16
+ validates "#{json_attribute}_#{attribute}_#{key}", value[:validates].merge(if: -> { send(schema_key.to_s) == attribute.to_s })
17
+ end
18
+ end
19
+ end
20
+
21
+ after_initialize do
22
+ if new_record? && has_attribute?(json_attribute) && instance_eval(schema_key.to_s)
23
+ field_types = schema[instance_eval(schema_key.to_s).to_sym]
24
+ write_attributes(json_attribute, field_types) unless field_types.nil?
25
+ end
26
+ end
27
+
28
+ before_validation do
29
+ if has_attribute?(json_attribute)
30
+ field_types = schema[instance_eval(schema_key.to_s).to_sym]
31
+ write_attributes(json_attribute, field_types) unless field_types.nil?
32
+ end
33
+ end
34
+
35
+ define_method("#{json_attribute}_strong_params") do
36
+ if has_attribute?(json_attribute)
37
+ field_types = schema[instance_eval(schema_key.to_s).to_sym]
38
+
39
+ return nil if field_types.nil?
40
+
41
+ field_types.map do |k,v|
42
+ v[:type] == :json ? { k => v[:nested_attributes] } : k
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def write_attributes(json_attribute, field_types)
52
+ if self.send("#{json_attribute}_changed?") && !self.send("#{json_attribute}_change")[0].blank?
53
+ self[json_attribute] = self.send("#{json_attribute}_change")[0].merge(self[json_attribute])
54
+ end
55
+
56
+ self[json_attribute] = {} if self[json_attribute].blank?
57
+ new_settings = {}
58
+ field_types.each do |key,value|
59
+ if self[json_attribute][key.to_s] == nil
60
+ new_settings[key] = value[:default]
61
+ else
62
+ new_settings[key] = self[json_attribute][key.to_s]
63
+ end
64
+ end
65
+
66
+ self[json_attribute] = new_settings
67
+ end
68
+ end
69
+ end
70
+
71
+ ActiveRecord::Base.include(ActiveRecord::Octojson)
@@ -0,0 +1,5 @@
1
+ module ActiveRecord
2
+ module Octojson
3
+ VERSION = "0.0.2"
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ default: &default
2
+ adapter: postgresql
3
+ database: octojson
4
+
5
+ development:
6
+ <<: *default
7
+
8
+ test:
9
+ <<: *default
@@ -0,0 +1,8 @@
1
+ class BuildTestDb < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :posts do |t|
4
+ t.string :post_type
5
+ t.jsonb :settings
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,23 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # This file is the source Rails uses to define your schema when running `rails
6
+ # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(version: 2020_04_07_031737) do
14
+
15
+ # These are extensions that must be enabled in order to support this database
16
+ enable_extension "plpgsql"
17
+
18
+ create_table "posts", force: :cascade do |t|
19
+ t.string "post_type"
20
+ t.jsonb "settings"
21
+ end
22
+
23
+ end
@@ -0,0 +1,22 @@
1
+ class Post < ActiveRecord::Base
2
+ SCHEMA = {
3
+ type_one: {
4
+ title: { type: :string, default: 'Title -- one' },
5
+ text_one: { type: :string, default: 'something cool -- one' },
6
+ boolean_one: { type: :boolean, default: false },
7
+ number_one: { type: :integer, default: 3, validates: { numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 5 } } },
8
+ json_one: { type: :json, default: {}, nested_attributes: [:nested_one, :nested_two, :nested_three] },
9
+ },
10
+ type_two: {
11
+ title: { type: :string, default: 'Title -- two' },
12
+ text_two: { type: :string, default: 'something cool -- two' },
13
+ boolean_two: { type: :boolean, default: true },
14
+ },
15
+ type_three: {
16
+ title: { type: :string, default: 'Title -- three' },
17
+ text_three: { type: :string, default: 'something cool -- three' }
18
+ }
19
+ }.freeze
20
+
21
+ octojson :settings, SCHEMA, :post_type
22
+ end
@@ -0,0 +1,97 @@
1
+ require 'test_helper'
2
+
3
+ class OctojsonTest < ActiveSupport::TestCase
4
+
5
+ test '#new with defaults' do
6
+ post = Post.new(post_type: 'type_one')
7
+
8
+ assert_equal post.settings['title'], 'Title -- one'
9
+ assert_equal post.settings['text_one'], 'something cool -- one'
10
+ assert_equal post.settings['boolean_one'], false
11
+ assert_equal post.settings['number_one'], 3
12
+ assert_equal post.settings['json_one'], {}
13
+
14
+ post_two = Post.new(post_type: 'type_two')
15
+
16
+ assert_equal post_two.settings['title'], 'Title -- two'
17
+ assert_equal post_two.settings['text_two'], 'something cool -- two'
18
+ assert_equal post_two.settings['boolean_two'], true
19
+ assert_nil post_two.settings['text_one']
20
+ end
21
+
22
+ test '#new with attributes' do
23
+ post = Post.new(post_type: 'type_one', settings: { title: 'Not default' })
24
+ assert_equal post.settings['title'], 'Not default'
25
+ end
26
+
27
+ test '#new with attributes not in schema' do
28
+ post = Post.new(post_type: 'type_one', settings: { something: 'Not default' })
29
+ assert_nil post.settings['something']
30
+ end
31
+
32
+ test '#create' do
33
+ post = Post.create(post_type: 'type_one', settings: { title: 'Created title' })
34
+ assert_equal post.settings['title'], 'Created title'
35
+ assert_equal post.settings['text_one'], 'something cool -- one'
36
+ end
37
+
38
+ test '#save with defaults' do
39
+ post = Post.new
40
+ post.post_type = 'type_one'
41
+ post.save
42
+
43
+ assert_equal post.settings['title'], 'Title -- one'
44
+ assert_equal post.settings['text_one'], 'something cool -- one'
45
+ assert_equal post.settings['boolean_one'], false
46
+ assert_equal post.settings['number_one'], 3
47
+ assert_equal post.settings['json_one'], {}
48
+
49
+ post_two = Post.new
50
+ post_two.post_type = 'type_two'
51
+ post_two.save
52
+ assert_equal post_two.settings['title'], 'Title -- two'
53
+ assert_equal post_two.settings['text_two'], 'something cool -- two'
54
+ assert_equal post_two.settings['boolean_two'], true
55
+ assert_nil post_two.settings['text_one']
56
+ end
57
+
58
+ test '#update' do
59
+ post = Post.create(post_type: 'type_one')
60
+ assert_equal post.settings['title'], 'Title -- one'
61
+
62
+ post.update(settings: { title: 'testing 123' })
63
+ assert_equal post.settings['title'], 'testing 123'
64
+ end
65
+
66
+ test '#update should use default if assigning nil' do
67
+ post = Post.create(post_type: 'type_one', settings: { title: 'testing' })
68
+ assert_equal post.settings['title'], 'testing'
69
+
70
+ post.update(settings: { title: nil })
71
+ assert_equal post.settings['title'], 'Title -- one'
72
+ end
73
+
74
+ test '#{json_attribute}_strong_params' do
75
+ post = Post.new
76
+ post.post_type = 'type_one'
77
+ post.save
78
+
79
+ assert_equal post.settings_strong_params, [
80
+ :title,
81
+ :text_one,
82
+ :boolean_one,
83
+ :number_one,
84
+ { :json_one=> [:nested_one, :nested_two, :nested_three] }
85
+ ]
86
+ end
87
+
88
+ test 'valid on initialize' do
89
+ post = Post.new(post_type: 'type_one')
90
+ assert_equal post.valid?, true
91
+ end
92
+
93
+ test 'invalid when settings attribute out of range' do
94
+ post = Post.new(post_type: 'type_one', settings: { number_one: 99 })
95
+ assert_equal post.valid?, false
96
+ end
97
+ end
@@ -0,0 +1,16 @@
1
+ testdir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift testdir unless $LOAD_PATH.include?(testdir)
3
+
4
+ libdir = File.dirname(File.dirname(__FILE__)) + '/lib'
5
+ $LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
6
+
7
+ require "rubygems"
8
+ require "octojson"
9
+ require "minitest/autorun"
10
+ require "minitest/unit"
11
+ require "pry"
12
+
13
+ Dir[File.join(__dir__, 'fixtures', 'models', '*.rb')].each { |file| require file }
14
+
15
+ dbconfig = YAML.load(File.open(File.join(__dir__,'db','config.yml')))
16
+ ActiveRecord::Base.establish_connection(dbconfig["test"])
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: octojson
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Chris Bacon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-10-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 6.0.3.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 6.0.3.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: pg
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.18.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.18.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: standalone_migrations
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Set a schema, defaults, and validations for your json attributes
98
+ email:
99
+ - chris@crispybacon.io
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - MIT-LICENSE
105
+ - Rakefile
106
+ - lib/octojson.rb
107
+ - lib/octojson/version.rb
108
+ - test/db/config.yml
109
+ - test/db/migrate/20200407031737_build_test_db.rb
110
+ - test/db/schema.rb
111
+ - test/fixtures/models/post.rb
112
+ - test/octojson_test.rb
113
+ - test/test_helper.rb
114
+ homepage: https://github.com/baconck/octojson
115
+ licenses:
116
+ - MIT
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubygems_version: 3.1.2
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: Set a schema, defaults, and validations for your json attributes
137
+ test_files:
138
+ - test/octojson_test.rb
139
+ - test/db/schema.rb
140
+ - test/db/migrate/20200407031737_build_test_db.rb
141
+ - test/db/config.yml
142
+ - test/fixtures/models/post.rb
143
+ - test/test_helper.rb