json_sti 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/json_sti.rb +150 -0
- data/lib/json_sti/class_master_list.rb +77 -0
- data/lib/json_sti/inheritable_seeder.rb +125 -0
- metadata +215 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3624d823ce141fe74222d5ce9d2fe9dd6a07692046db37aeb18fce3a137a5b10
|
4
|
+
data.tar.gz: e6ecba2cb054e9dbab7d69ccba1f0b820125ad8cb8fff80480cd9c0bc12730c1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4682108fa7c68af0dfdf92e7ce35eece47c281cf57421507ff2d5509f945d80f4fa55a299e40386544d6f862afff080eca017cbe7bed9ef8781001ea52efef52
|
7
|
+
data.tar.gz: 861e476792d0fd1da19f14db46aef05c8d646870a8b61eb099cfa34a330fec2e1b288043d732261765cf984e75df3d829a26ea09ed8f2b61563316139fc07449
|
data/lib/json_sti.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
require "zeitwerk"
|
2
|
+
|
3
|
+
loader = Zeitwerk::Loader.for_gem
|
4
|
+
loader.setup
|
5
|
+
|
6
|
+
require_relative "json_sti/class_master_list"
|
7
|
+
require_relative "json_sti/inheritable_seeder"
|
8
|
+
|
9
|
+
module JsonSti
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
def self.initialize_single_table_arel_helpers
|
13
|
+
JsonSti::ClassMasterList.base_class_list.each do |receiving_class_name|
|
14
|
+
receiving_class = receiving_class_name.to_s.camelize.constantize
|
15
|
+
|
16
|
+
next unless ClassMasterList.relations_lookup[receiving_class_name]
|
17
|
+
|
18
|
+
ClassMasterList.relations_lookup[receiving_class_name][:relationships].each do |relationship_to_create|
|
19
|
+
ClassMasterList.relations_lookup[relationship_to_create][:members].each do |relationship_to_create_member|
|
20
|
+
creation_class = "#{relationship_to_create.to_s.camelize}::#{relationship_to_create_member.to_s.singularize.camelize}".constantize
|
21
|
+
|
22
|
+
ar_association = receiving_class.reflect_on_all_associations.detect do |association|
|
23
|
+
association.class_name == relationship_to_create.to_s.camelize
|
24
|
+
end
|
25
|
+
|
26
|
+
receiving_class.class_eval do
|
27
|
+
if ar_association.to_s.downcase =~ /many/
|
28
|
+
# create has_many helper methods for sti subtypes
|
29
|
+
define_method "#{relationship_to_create_member.to_s.pluralize}" do
|
30
|
+
self.send(relationship_to_create.to_s.pluralize).where(type: creation_class.to_s)
|
31
|
+
end
|
32
|
+
|
33
|
+
else
|
34
|
+
# create belongs_to helper methods for sti subtypes
|
35
|
+
define_method "#{relationship_to_create_member.to_s.singularize}" do
|
36
|
+
object = self.send(relationship_to_create.to_s.singularize)
|
37
|
+
return object.class.to_s == creation_class.to_s ? object : nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
included do
|
47
|
+
def self.inherited(subclass)
|
48
|
+
begin
|
49
|
+
#check to make sure if it exists, throws error and rescues with constant creation otherwise
|
50
|
+
subclass.to_s.split("::").last.constantize
|
51
|
+
rescue
|
52
|
+
# define subclass name as constant on global object
|
53
|
+
# probably smarter way to do this? Something zeitwerk?
|
54
|
+
Object.const_set(subclass.to_s.split("::").last, subclass)
|
55
|
+
|
56
|
+
subclass.class_eval do
|
57
|
+
# patch subclasses to validate based on their schema.
|
58
|
+
# Schemas are defined in subclasses with `define_schema`
|
59
|
+
validates :module_data,
|
60
|
+
presence: false,
|
61
|
+
json: {
|
62
|
+
message: ->(errors) { errors },
|
63
|
+
schema: lambda { cleaned_schema }
|
64
|
+
}
|
65
|
+
|
66
|
+
# a helper similar to ARs `where` only for json fields
|
67
|
+
scope :jwhere, lambda { |hash| where("module_data @> ?", hash.to_json) }
|
68
|
+
|
69
|
+
def initialize(params)
|
70
|
+
super
|
71
|
+
|
72
|
+
self.class::SCHEMA["properties"].keys.each do |attr|
|
73
|
+
unless self.module_data[attr]
|
74
|
+
if self.class::SCHEMA["required"].include? attr
|
75
|
+
self.module_data[attr] = "REQUIRED: #{self.class::SCHEMA["properties"][attr]["type"]}"
|
76
|
+
else
|
77
|
+
self.module_data[attr] = nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def cleaned_schema
|
86
|
+
schema = self.class::SCHEMA.to_json
|
87
|
+
|
88
|
+
hash_schema = JSON.parse(schema)
|
89
|
+
properties = hash_schema["properties"]
|
90
|
+
required = schema['required']
|
91
|
+
|
92
|
+
properties.each do |property, value|
|
93
|
+
unless self.module_data[property]
|
94
|
+
unless required.include?(property)
|
95
|
+
properties.delete property
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
hash_schema["properties"] = properties
|
101
|
+
hash_schema.to_json
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
super
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.descendants
|
110
|
+
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.define_schema(hash)
|
114
|
+
class_eval do
|
115
|
+
const_set(:SCHEMA, hash.with_indifferent_access)
|
116
|
+
|
117
|
+
json_attrs = self::SCHEMA["properties"]
|
118
|
+
|
119
|
+
class_variable_set(:@@json_attrs, self::SCHEMA["properties"])
|
120
|
+
class_variable_set(:@@json_required, self::SCHEMA["required"])
|
121
|
+
|
122
|
+
initialize_attr_getters(json_attrs.keys)
|
123
|
+
initialize_attr_setters(json_attrs.keys)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def self.initialize_attr_getters(attr_names)
|
130
|
+
# patches including classes to have getters for their json attr names
|
131
|
+
attr_names.each do |attr_name|
|
132
|
+
define_method attr_name do
|
133
|
+
self.module_data[attr_name]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.initialize_attr_setters(attr_names)
|
139
|
+
# patches including classes to have setters for their json attr names
|
140
|
+
attr_names.each do |attr_name|
|
141
|
+
define_method "#{attr_name}=" do |new_value|
|
142
|
+
self.module_data[attr_name] = new_value
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
loader.eager_load
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module JsonSti
|
2
|
+
class ClassMasterList
|
3
|
+
def self.sti_base_class_list
|
4
|
+
# a list of STI base classes which have their own tables
|
5
|
+
@@sti_base_class_list ||= build_sti_base_class_list
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.relations_lookup
|
9
|
+
# a lookup table including the subclasses of each baseclasses
|
10
|
+
# and what relationships each STI class has to other STI classes
|
11
|
+
@@relations_lookup ||= build_relations_lookup
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.base_class_list
|
15
|
+
# a list of STI base classes which have their own tables
|
16
|
+
@@base_class_list ||= build_base_class_list
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def self.build_sti_base_class_list
|
22
|
+
ObjectSpace.
|
23
|
+
each_object(Class).
|
24
|
+
select { |klass| klass.included_modules.include? JsonSti }.
|
25
|
+
map(&:to_s).
|
26
|
+
reject { |klass| klass.include?("::") }.
|
27
|
+
map(&:underscore).
|
28
|
+
map(&:to_sym)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.build_base_class_list
|
32
|
+
models = ActiveRecord::Base.
|
33
|
+
descendants.
|
34
|
+
map(&:name).
|
35
|
+
reject { |klass| klass.include?("::") }.
|
36
|
+
reject { |klass| klass.include?("HABTM") }.
|
37
|
+
reject { |klass| klass.include?("WP") }.
|
38
|
+
map(&:underscore).
|
39
|
+
map(&:to_sym).
|
40
|
+
tap { |models| models.delete :application_record}
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.build_relations_lookup
|
44
|
+
@@relations_lookup = {}
|
45
|
+
|
46
|
+
base_class_list.each do |class_name|
|
47
|
+
@@relations_lookup[class_name] = {}
|
48
|
+
build_relation_list_for_class(class_name)
|
49
|
+
build_members_list_for_class(class_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
@@relations_lookup
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.build_relation_list_for_class(class_name)
|
56
|
+
klass = class_name.to_s.camelize.constantize
|
57
|
+
associations = klass.reflect_on_all_associations
|
58
|
+
|
59
|
+
relation_list = associations.map(&:class_name).
|
60
|
+
map(&:to_s).
|
61
|
+
map(&:underscore).
|
62
|
+
map(&:to_sym)
|
63
|
+
|
64
|
+
@@relations_lookup[class_name][:relationships] = (relation_list & JsonSti::ClassMasterList.sti_base_class_list)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.build_members_list_for_class(class_name)
|
68
|
+
klass = class_name.to_s.camelize.constantize
|
69
|
+
members = klass.descendants.map(&:to_s).
|
70
|
+
map{ |descendant| descendant.gsub("#{class_name.to_s.camelize}::", "") }.
|
71
|
+
map(&:underscore).
|
72
|
+
map(&:to_sym)
|
73
|
+
|
74
|
+
@@relations_lookup[class_name][:members] = members
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module JsonSti
|
2
|
+
class InheritableSeeder
|
3
|
+
def self.seed!(num_to_create=3)
|
4
|
+
relations_lookup = JsonSti::ClassMasterList.relations_lookup
|
5
|
+
|
6
|
+
relations_lookup.each do |type, info|
|
7
|
+
info[:members].each do |member|
|
8
|
+
klass = "#{type.to_s.camelize}::#{member.to_s.camelize}".constantize
|
9
|
+
instance = klass.create
|
10
|
+
|
11
|
+
if !instance.valid?
|
12
|
+
skip_sub_object_creation = self.fix_errors_on_instance_and_determine_next_step(instance)
|
13
|
+
next if skip_sub_object_creation
|
14
|
+
end
|
15
|
+
|
16
|
+
p "Created a #{klass.to_s}"
|
17
|
+
|
18
|
+
info[:relationships].each do |relationship|
|
19
|
+
relations_lookup[relationship][:members].each do |relation_member|
|
20
|
+
self.create_relationship_for_instance(instance, relationship, relation_member, num_to_create)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.populate_attrs_for_instance!(instance, only_required=false)
|
28
|
+
klass = instance.class
|
29
|
+
json_attrs = klass.class_variable_get(:@@json_attrs)
|
30
|
+
return if json_attrs.blank?
|
31
|
+
|
32
|
+
attrs = only_required ? klass.class_variable_get(:@@json_required) : klass.class_variable_get(:@@json_attrs).keys
|
33
|
+
|
34
|
+
return if attrs.blank?
|
35
|
+
|
36
|
+
attrs.each do |attr|
|
37
|
+
type = json_attrs[attr].values
|
38
|
+
case type.first
|
39
|
+
when "string"
|
40
|
+
if type[1] && type[1] == "date"
|
41
|
+
new_val = Faker::Date.between(from: 10.days.ago, to: Date.today)
|
42
|
+
elsif type[1] && type[1] == "time"
|
43
|
+
new_val = Faker::Time.between(from: DateTime.now - 1, to: DateTime.now)
|
44
|
+
else
|
45
|
+
new_val = Faker::Marketing.buzzwords
|
46
|
+
end
|
47
|
+
when "boolean"
|
48
|
+
new_val = [true, false].sample
|
49
|
+
when "integer"
|
50
|
+
new_val = Integer(Faker::Number.within(range: 0..99))
|
51
|
+
when "number"
|
52
|
+
new_val = Faker::Number.decimal(l_digits:2, r_digits: 3)
|
53
|
+
end
|
54
|
+
|
55
|
+
instance.send((attr.to_s + "="), new_val)
|
56
|
+
end
|
57
|
+
|
58
|
+
instance.save!
|
59
|
+
|
60
|
+
instance
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.generate_valid_instance_of_class!(klass, only_required=false)
|
64
|
+
populate_attrs_for_instance!(klass.new, only_required)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def self.create_relationship_for_instance(instance, relationship_type, relation_member, num_to_create)
|
70
|
+
p "Creating a #{relation_member} for a #{instance.class}"
|
71
|
+
|
72
|
+
num_to_create.times do |n|
|
73
|
+
ar_association = instance.class.reflect_on_all_associations.detect do |association|
|
74
|
+
association.class_name == relationship_type.to_s.camelize
|
75
|
+
end
|
76
|
+
|
77
|
+
if ar_association.to_s.downcase =~ /many/
|
78
|
+
relation_name = relation_member.to_s.pluralize
|
79
|
+
sub_instance = instance.send(relation_name).create
|
80
|
+
else
|
81
|
+
klass_to_create = "#{relationship_type.to_s.camelize}::#{relation_member.to_s.camelize}".constantize
|
82
|
+
sub_instance = generate_valid_instance_of_class!(klass_to_create)
|
83
|
+
|
84
|
+
sub_instance_rel_id = sub_instance.class.to_s.split("::").first.underscore + "_id="
|
85
|
+
instance.send(sub_instance_rel_id, sub_instance.id)
|
86
|
+
end
|
87
|
+
|
88
|
+
JsonSti::InheritableSeeder.populate_attrs_for_instance!(sub_instance)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.fix_errors_on_instance_and_determine_next_step(instance)
|
93
|
+
klass = instance.class
|
94
|
+
skip_sub_object_creation = false
|
95
|
+
|
96
|
+
instance.errors.messages.each do |error_key, error_value|
|
97
|
+
if error_key == :module_data
|
98
|
+
JsonSti::InheritableSeeder.populate_attrs_for_instance!(instance)
|
99
|
+
|
100
|
+
elsif error_value.include? "must exist"
|
101
|
+
fix_belongs_to_based_errors_for_instance(instance, error_key)
|
102
|
+
skip_sub_object_creation = true
|
103
|
+
|
104
|
+
else
|
105
|
+
p "============================="
|
106
|
+
p "There was an unhandled error on instance creation: #{error_key} : #{error_value.first}"
|
107
|
+
p "============================="
|
108
|
+
skip_sub_object_creation = true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
skip_sub_object_creation
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.fix_belongs_to_based_errors_for_instance(instance, error_key)
|
116
|
+
valid_sub_type = ClassMasterList.relations_lookup[error_key][:members].sample.to_s
|
117
|
+
sub_type_klass = "#{error_key.to_s.camelize}::#{valid_sub_type.camelize}".constantize
|
118
|
+
|
119
|
+
p "creating #{sub_type_klass.to_s} belongs to for #{instance.class.to_s}"
|
120
|
+
new_sub_instance = instance.send("#{error_key}=", sub_type_klass.create)
|
121
|
+
|
122
|
+
JsonSti::InheritableSeeder.populate_attrs_for_instance!(new_sub_instance)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
metadata
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: json_sti
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Max
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-12-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.8.7
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.8.7
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.77'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.77'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.7'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.7'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: faker
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.7'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.7'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: activerecord
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 4.2.0
|
104
|
+
- - "<"
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '7'
|
107
|
+
type: :runtime
|
108
|
+
prerelease: false
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: 4.2.0
|
114
|
+
- - "<"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '7'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: activesupport
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 4.2.0
|
124
|
+
- - "<"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '7'
|
127
|
+
type: :runtime
|
128
|
+
prerelease: false
|
129
|
+
version_requirements: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 4.2.0
|
134
|
+
- - "<"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '7'
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
name: pg
|
139
|
+
requirement: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '1.1'
|
144
|
+
type: :runtime
|
145
|
+
prerelease: false
|
146
|
+
version_requirements: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - "~>"
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '1.1'
|
151
|
+
- !ruby/object:Gem::Dependency
|
152
|
+
name: zeitwerk
|
153
|
+
requirement: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - "~>"
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '2.2'
|
158
|
+
type: :runtime
|
159
|
+
prerelease: false
|
160
|
+
version_requirements: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - "~>"
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '2.2'
|
165
|
+
- !ruby/object:Gem::Dependency
|
166
|
+
name: activerecord_json_validator
|
167
|
+
requirement: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - "~>"
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: 1.3.0
|
172
|
+
type: :runtime
|
173
|
+
prerelease: false
|
174
|
+
version_requirements: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - "~>"
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: 1.3.0
|
179
|
+
description: A common argument against STI in rails is that the tables eventually
|
180
|
+
get cluttered with class specific columns. By keeping all subtype specific attrs
|
181
|
+
in json, you completely avoid table bloat while keeping all the advantages of AR
|
182
|
+
and a relational database
|
183
|
+
email: andrew.max89@gmail.com
|
184
|
+
executables: []
|
185
|
+
extensions: []
|
186
|
+
extra_rdoc_files: []
|
187
|
+
files:
|
188
|
+
- lib/json_sti.rb
|
189
|
+
- lib/json_sti/class_master_list.rb
|
190
|
+
- lib/json_sti/inheritable_seeder.rb
|
191
|
+
homepage:
|
192
|
+
licenses:
|
193
|
+
- MIT
|
194
|
+
metadata: {}
|
195
|
+
post_install_message:
|
196
|
+
rdoc_options: []
|
197
|
+
require_paths:
|
198
|
+
- lib
|
199
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - ">="
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
204
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
requirements: []
|
210
|
+
rubygems_version: 3.0.3
|
211
|
+
signing_key:
|
212
|
+
specification_version: 4
|
213
|
+
summary: A scheme for single table inheritance with ActiveRecord which puts all class
|
214
|
+
specific attributes in a json blob, and allows validations
|
215
|
+
test_files: []
|