module JsonSti
Public Class Methods
clean_val_aa(val)
click to toggle source
handles bug in ransackable where 1 is converted to true
# File lib/json_sti.rb, line 67 def self.clean_val_aa(val) val.is_a?(TrueClass) ? 1 : val end
define_schema(hash)
click to toggle source
# File lib/json_sti.rb, line 102 def self.define_schema(hash) class_eval do const_set(:SCHEMA, hash.with_indifferent_access) json_attrs = self::SCHEMA["properties"] class_variable_set(:@@json_attrs, self::SCHEMA["properties"]) class_variable_set(:@@json_required, self::SCHEMA["required"]) initialize_attr_getters(json_attrs.keys) initialize_attr_setters(json_attrs.keys) #creates methods required for ransackables searches in active admin class << self self.class_variable_get(:@@json_attrs).each do |prop, type| if type["type"].include?("string") define_method "#{prop}_equals" do |value| self.j_where(Hash[prop, value]) end define_method "#{prop}_contains" do |value| self.j_like_key(prop, value) end elsif type["type"].include?("integer") define_method "#{prop}_equals" do |value| self.j_where(Hash[prop, value.to_i]) end define_method "#{prop}_greater_than" do |value| self.j_gt(prop, value) end define_method "#{prop}_less_than" do |value| self.j_lt(prop, value) end elsif type["type"].include?("number") define_method "#{prop}_equals" do |value| self.j_where(Hash[prop, clean_val_aa(value).to_f]) end define_method "#{prop}_greater_than" do |value| self.j_gt(prop, value) end define_method "#{prop}_less_than" do |value| self.j_lt(prop, value) end elsif type["type"].include?("boolean") # todo figure this out in for select, eq for checkboxes or viceversa # define_method "#{prop}_in" do |*value| # self.j_where(Hash[prop, value]) # end end end define_method "ransackable_scopes" do |_auth_object = nil| scopes = [] ransackable_string_query_types = %i(equals contains) self.class_variable_get(:@@json_attrs).each do |prop, type| if type["type"].include?("string") ransackable_string_query_types.each do |ransackable_query_type| scopes.push "#{prop}_#{ransackable_query_type}" end elsif type["type"].include?("integer") scopes.push "#{prop}_equals" scopes.push "#{prop}_greater_than" scopes.push "#{prop}_less_than" elsif type["type"].include?("number") scopes.push "#{prop}_equals" scopes.push "#{prop}_greater_than" scopes.push "#{prop}_less_than" elsif type["type"].include?("boolean") # todo figure this out in for select, eq for checkboxes or viceversa # scopes.push "#{prop}_in" end end scopes end end end end
descendants()
click to toggle source
# File lib/json_sti.rb, line 98 def self.descendants ObjectSpace.each_object(Class).select { |klass| klass < self } end
inherited(subclass)
click to toggle source
Calls superclass method
# File lib/json_sti.rb, line 47 def self.inherited(subclass) begin #check to make sure if it exists, throws error and rescues with constant creation otherwise subclass.to_s.split("::").last.constantize rescue # define subclass name as constant on global object # probably smarter way to do this? Something zeitwerk? Object.const_set(subclass.to_s.split("::").last, subclass) subclass.class_eval do # patch subclasses to validate based on their schema. # Schemas are defined in subclasses with `define_schema` validates :module_data, presence: false, json: { message: ->(errors) { errors }, schema: lambda { self.class::SCHEMA } } # handles bug in ransackable where 1 is converted to true def self.clean_val_aa(val) val.is_a?(TrueClass) ? 1 : val end # a helper similar to ARs `where` only for json fields scope :j_where, lambda { |hash| where("module_data @> ?", hash.to_json) } scope :j_like_key, lambda { |key, value| where("module_data ->> :key LIKE :value",key: key, value: "%#{value}%") } scope :j_gt, lambda { |prop, val| where("module_data ->> '#{prop}' > ?", "#{clean_val_aa(val).to_f}") } scope :j_lt, lambda { |prop, val| where("module_data ->> '#{prop}' < ?", "#{clean_val_aa(val).to_f}" ) } scope :j_gte, lambda { |prop, val| where("module_data ->> '#{prop}' >= ?", "#{clean_val_aa(val).to_f}") } scope :j_lte, lambda { |prop, val| where("module_data ->> '#{prop}' <= ?", "#{clean_val_aa(val).to_f}" ) } def initialize(params) super self.class::SCHEMA["properties"].keys.each do |attr| unless self.module_data[attr] if self.class::SCHEMA["required"].include? attr self.module_data[attr] = "REQUIRED: #{self.class::SCHEMA["properties"][attr]["type"]}" else self.module_data[attr] = nil end end end end end end super end
initialize_attr_getters(attr_names)
click to toggle source
# File lib/json_sti.rb, line 188 def self.initialize_attr_getters(attr_names) # patches including classes to have getters for their json attr names attr_names.each do |attr_name| define_method attr_name do self.module_data[attr_name] end end end
initialize_attr_setters(attr_names)
click to toggle source
# File lib/json_sti.rb, line 197 def self.initialize_attr_setters(attr_names) # patches including classes to have setters for their json attr names attr_names.each do |attr_name| define_method "#{attr_name}=" do |new_value| self.module_data[attr_name] = new_value end end end
initialize_single_table_arel_helpers()
click to toggle source
# File lib/json_sti.rb, line 12 def self.initialize_single_table_arel_helpers JsonSti::ClassMasterList.base_class_list.each do |receiving_class_name| receiving_class = receiving_class_name.to_s.camelize.constantize next unless ClassMasterList.relations_lookup[receiving_class_name] ClassMasterList.relations_lookup[receiving_class_name][:relationships].each do |relationship_to_create| ClassMasterList.relations_lookup[relationship_to_create][:members].each do |relationship_to_create_member| creation_class = "#{relationship_to_create.to_s.camelize}::#{relationship_to_create_member.to_s.singularize.camelize}".constantize ar_association = receiving_class.reflect_on_all_associations.detect do |association| association.class_name == relationship_to_create.to_s.camelize end receiving_class.class_eval do if ar_association.to_s.downcase =~ /many/ # create has_many helper methods for sti subtypes define_method "#{relationship_to_create_member.to_s.pluralize}" do self.send(relationship_to_create.to_s.pluralize).where(type: creation_class.to_s) end else # create belongs_to helper methods for sti subtypes define_method "#{relationship_to_create_member.to_s.singularize}" do object = self.send(relationship_to_create.to_s.singularize) return object.class.to_s == creation_class.to_s ? object : nil end end end end end end end
new(params)
click to toggle source
Calls superclass method
# File lib/json_sti.rb, line 79 def initialize(params) super self.class::SCHEMA["properties"].keys.each do |attr| unless self.module_data[attr] if self.class::SCHEMA["required"].include? attr self.module_data[attr] = "REQUIRED: #{self.class::SCHEMA["properties"][attr]["type"]}" else self.module_data[attr] = nil end end end end