class ResourceModel::Base
Attributes
associated_model_attributes[R]
associated_model_collection_attributes[R]
associated_resource_model_attributes[R]
associated_resource_model_collection_attributes[R]
boolean_attributes[R]
date_attributes[R]
decimal_attributes[R]
enum_attributes[R]
integer_attributes[R]
string_attributes[R]
usd_attributes[R]
Public Class Methods
boolean_accessor(attribute_name)
click to toggle source
# File lib/resource_model/base.rb, line 199 def self.boolean_accessor(attribute_name) raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) if self.boolean_attributes.include?(attribute_name) raise ArgumentError, "Already contains a boolean accessor named `#{attribute_name}`" else @boolean_attributes << attribute_name self.class_eval <<-eos attr_reader :#{attribute_name} def #{attribute_name}=(value) case value when nil @#{attribute_name} = nil when TrueClass, FalseClass @#{attribute_name} = value else @#{attribute_name} = value.present? ? ['1', 1, 'true', 't'].include?(value) : nil end end eos end end
date_accessor(attribute_name, options={})
click to toggle source
# File lib/resource_model/base.rb, line 301 def self.date_accessor(attribute_name, options={}) raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) raise ArgumentError, "Expected options[:timezone]=`#{options[:timezone]}` to be an instance of Symbol, String, or Nil" unless options[:timezone].nil? || options[:timezone].is_a?(String) || options[:timezone].is_a?(Symbol) if self.date_attributes.include?(attribute_name) raise ArgumentError, "Already contains a date accessor named `#{attribute_name}`" else @date_attributes << attribute_name self.class_eval <<-eos attr_reader :#{attribute_name} attr_reader :#{attribute_name}_unconverted_value def #{attribute_name}=(value) case value when nil @#{attribute_name}_unconverted_value = nil @#{attribute_name} = nil when Time, DateTime @#{attribute_name}_unconverted_value = value timezone = #{case options[:timezone]; when Symbol; "self.send(#{options[:timezone].inspect})"; when String; "ActiveSupport::TimeZone[#{options[:timezone].inspect}]"; else; "ActiveSupport::TimeZone['UTC']"; end} @#{attribute_name} = ActiveSupport::TimeWithZone.new(nil, timezone, (value.is_a?(ActiveSupport::TimeWithZone) ? value.time : value)) when String @#{attribute_name}_unconverted_value = value parsed_date = DateTime.parse(value) rescue nil timezone = #{case options[:timezone]; when Symbol; "self.send(#{options[:timezone].inspect})"; when String; "ActiveSupport::TimeZone[#{options[:timezone].inspect}]"; else; "ActiveSupport::TimeZone['UTC']"; end} @#{attribute_name} = parsed_date ? ActiveSupport::TimeWithZone.new(nil, timezone, parsed_date) : nil else raise ArgumentError, 'Unexpected value passed to date_accessor #{attribute_name}; expected Time, String, or nil.' end end validate do if self.#{attribute_name}_unconverted_value.present? != self.#{attribute_name}.present? self.errors.add(:#{attribute_name}, :invalid) end end eos end end
decimal_accessor(attribute_name, options={})
click to toggle source
# File lib/resource_model/base.rb, line 249 def self.decimal_accessor(attribute_name, options={}) raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) if self.decimal_attributes.include?(attribute_name) raise ArgumentError, "Already contains a decimal accessor named `#{attribute_name}`" else decimal_regex = /\A\s*[+-]?\s*\d*(\d,\d)*\d*\.?\d*\s*\Z/ @decimal_attributes << attribute_name self.class_eval <<-eos attr_reader :#{attribute_name} attr_reader :#{attribute_name}_unconverted_value def #{attribute_name}=(value) @#{attribute_name}_unconverted_value = value @#{attribute_name} = value.present? && value.to_s =~ #{decimal_regex.inspect} ? BigDecimal.new(value.to_s.gsub(/\\s|[,]/, '')) : nil end validate do if self.#{attribute_name}_unconverted_value.present? != self.#{attribute_name}.present? self.errors.add(:#{attribute_name}, :not_a_number) end end eos end end
enum_accessor(attribute_name, enums:, raise_error_on_set: false, allow_nil: true)
click to toggle source
# File lib/resource_model/base.rb, line 363 def self.enum_accessor(attribute_name, enums:, raise_error_on_set: false, allow_nil: true) raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) raise ArgumentError, "Expected `enums`: `#{enums}` to be an instance of Array containing only instances of String" unless enums.is_a?(Array) && enums.all? { |e| e.is_a?(String) } raise ArgumentError, "Expected `raise_error_on_set`: `#{raise_error_on_set}` to be an instance of TrueClass or FalseClass" unless raise_error_on_set.is_a?(TrueClass) || raise_error_on_set.is_a?(FalseClass) raise ArgumentError, "Expected `allow_nil`: `#{allow_nil}` to be an instance of TrueClass or FalseClass" unless allow_nil.is_a?(TrueClass) || allow_nil.is_a?(FalseClass) if self.enum_attributes.include?(attribute_name) raise ArgumentError, "Already contains a enum accessor named `#{attribute_name}`" else @enum_attributes << attribute_name self.class_eval <<-eos attr_reader :#{attribute_name} validates :#{attribute_name}, inclusion: {in: #{(enums + (allow_nil ? [nil] : [])).inspect}} def #{attribute_name}=(value) value = nil unless value.present? if #{raise_error_on_set} && !((#{allow_nil} && value.nil?) || #{enums.inspect}.include?(value)) raise ArgumentError, 'Expected to receive valid enum string or nil.' end @#{attribute_name} = value end def #{attribute_name}_enums #{enums.inspect} end eos end end
has_associated_model(attribute_name, options={})
click to toggle source
# File lib/resource_model/base.rb, line 112 def self.has_associated_model(attribute_name, options={}) # accepts_nested_attributes: nil raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) if self.associated_model_attributes.include?(attribute_name) raise ArgumentError, "Already contains associated model named `#{attribute_name}`" else @associated_model_attributes << attribute_name class_name = options[:class_name] || "::#{attribute_name.to_s.camelcase}" self.class_eval <<-eos attr_reader :#{attribute_name}, :#{attribute_name}_id def #{attribute_name}=(model) raise ArgumentError, 'Expected instance of `#{class_name}`' unless model.nil? || model.is_a?(#{class_name}) @#{attribute_name}_id = model.present? ? model.id : nil @#{attribute_name} = model end def #{attribute_name}_id=(id) if id.present? scope = #{class_name}.where(id: id) eager_loads = #{options[:eager_load].inspect} if eager_loads scope = scope.eager_load(eager_loads) end self.#{attribute_name} = scope.first! else self.#{attribute_name} = nil end end eos end end
has_associated_model_collection(attribute_name, class_name: nil, unique: true)
click to toggle source
# File lib/resource_model/base.rb, line 146 def self.has_associated_model_collection(attribute_name, class_name: nil, unique: true) raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) if self.associated_model_collection_attributes.include?(attribute_name) raise ArgumentError, "Already contains associated model collection named `#{attribute_name}`" else @associated_model_collection_attributes << attribute_name class_name ||= "::#{attribute_name.to_s.singularize.camelcase}" self.class_eval <<-eos attr_reader :#{attribute_name} def #{attribute_name}_ids self.#{attribute_name}.collect { |model| model.id } end def #{attribute_name}=(models) case models when nil @#{attribute_name} = [] when Array models.each do |model| unless model.is_a?(#{class_name}) raise ArgumentError, "Assignment of collection to #{attribute_name} contained invalid type \#{model.class.name}; expected only instances of #{class_name}" end end @#{attribute_name} = models else if models.respond_to?(:to_a) self.#{attribute_name} = models.to_a else raise ArgumentError, 'Expected instance of array' end end end def #{attribute_name}_ids=(ids) if ids.present? ids = ids.collect do |i| unless i.is_a?(Integer) || (i.is_a?(String) && i =~ /\\A\\s*\\d+\\s*\\Z/) raise ArgumentError, "Assignment of collection to #{attribute_name}_ids contained value (\#{i}) not an integer or stringified integer" end i.to_i end#{unique ? '.uniq' : ''} self.#{attribute_name} = #{class_name}.where(id: ids).to_a else self.#{attribute_name} = [] end end eos end end
has_associated_resource_model(attribute_name, options={})
click to toggle source
# File lib/resource_model/base.rb, line 24 def self.has_associated_resource_model(attribute_name, options={}) raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) if self.associated_resource_model_attributes.include?(attribute_name) raise ArgumentError, "Already contains associated resource model named `#{attribute_name}`" else @associated_resource_model_attributes << attribute_name class_name = options[:class_name] || "::#{attribute_name.to_s.camelcase}" self.class_eval <<-eos attr_reader :#{attribute_name} def #{attribute_name}=(model) raise ArgumentError, 'Expected instance of `#{class_name}`' unless model.nil? || model.is_a?(#{class_name}) @#{attribute_name}_attributes = nil @#{attribute_name} = model end def #{attribute_name}_attributes=(attributes) if attributes model = #{class_name}.new(attributes) self.#{attribute_name} = model else self.#{attribute_name} = nil end @#{attribute_name}_attributes = attributes end validate do if self.#{attribute_name} && !self.#{attribute_name}.valid? self.errors.add(:#{attribute_name}, :invalid) end end eos end end
has_associated_resource_model_collection(attribute_name, options={})
click to toggle source
# File lib/resource_model/base.rb, line 61 def self.has_associated_resource_model_collection(attribute_name, options={}) raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) if self.associated_resource_model_collection_attributes.include?(attribute_name) raise ArgumentError, "Already contains associated resource model collection named `#{attribute_name}`" else @associated_resource_model_collection_attributes << attribute_name class_name = options[:class_name] || "::#{attribute_name.to_s.singularize.camelcase}" self.class_eval <<-eos attr_reader :#{attribute_name} def #{attribute_name}=(models) case models when nil @#{attribute_name} = [] when Array models.each do |model| unless model.is_a?(#{class_name}) raise ArgumentError, "Assignment of collection to #{attribute_name} contained invalid type \#{model.class.name}; expected only instances of #{class_name}" end end @#{attribute_name} = models else if models.respond_to?(:to_a) self.#{attribute_name} = models.to_a else raise ArgumentError, 'Expected instance of array' end end end def #{attribute_name}_attributes=(attributes={}) if attributes self.#{attribute_name} = attributes.collect do |(k, model_attributes)| #{class_name}.new(model_attributes) end else self.#{attribute_name} = [] end end validate do if !self.#{attribute_name}.inject(true) { |valid, model| model.valid? && valid } self.errors.add(:#{attribute_name}, :invalid) end end eos end end
inherited(klass)
click to toggle source
# File lib/resource_model/base.rb, line 390 def self.inherited(klass) klass.class_eval <<-eos @associated_model_attributes = [] @associated_model_collection_attributes = [] @associated_resource_model_attributes = [] @associated_resource_model_collection_attributes = [] @boolean_attributes = [] @integer_attributes = [] @decimal_attributes = [] @usd_attributes = [] @date_attributes = [] @string_attributes = [] @enum_attributes = [] eos class << klass def associated_model_attributes self.superclass.associated_model_attributes + @associated_model_attributes end def associated_model_collection_attributes self.superclass.associated_model_collection_attributes + @associated_model_collection_attributes end def associated_resource_model_attributes self.superclass.associated_resource_model_attributes + @associated_resource_model_attributes end def associated_resource_model_collection_attributes self.superclass.associated_resource_model_collection_attributes + @associated_resource_model_collection_attributes end def boolean_attributes self.superclass.boolean_attributes + @boolean_attributes end def integer_attributes self.superclass.integer_attributes + @integer_attributes end def decimal_attributes self.superclass.decimal_attributes + @decimal_attributes end def usd_attributes self.superclass.usd_attributes + @usd_attributes end def date_attributes self.superclass.date_attributes + @date_attributes end def string_attributes self.superclass.date_attributes + @string_attributes end def enum_attributes self.superclass.date_attributes + @enum_attributes end end end
integer_accessor(attribute_name)
click to toggle source
# File lib/resource_model/base.rb, line 224 def self.integer_accessor(attribute_name) raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) if self.integer_attributes.include?(attribute_name) raise ArgumentError, "Already contains a integer accessor named `#{attribute_name}`" else @integer_attributes << attribute_name self.class_eval <<-eos attr_reader :#{attribute_name} attr_reader :#{attribute_name}_unconverted_value def #{attribute_name}=(value) @#{attribute_name}_unconverted_value = value @#{attribute_name} = value.present? && value.to_s =~ /\\A\\s*\\-?\\d+\\s*\\Z/ ? value.to_i : nil end validate do if self.#{attribute_name}_unconverted_value.present? != self.#{attribute_name}.present? self.errors.add(:#{attribute_name}, :not_an_integer) end end eos end end
model_name()
click to toggle source
# File lib/resource_model/base.rb, line 9 def self.model_name ActiveModel::Name.new(self, nil, self.name) end
new(attributes={})
click to toggle source
# File lib/resource_model/base.rb, line 441 def initialize(attributes={}) self.attributes = attributes end
string_accessor(attribute_name, options={})
click to toggle source
# File lib/resource_model/base.rb, line 341 def self.string_accessor(attribute_name, options={}) raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) if self.string_attributes.include?(attribute_name) raise ArgumentError, "Already contains a string accessor named `#{attribute_name}`" else @string_attributes << attribute_name self.class_eval <<-eos attr_reader :#{attribute_name} def #{attribute_name}=(value) if #{options[:strip] == true} && value value = value.strip end value = nil unless value.present? @#{attribute_name} = value end eos end end
usd_accessor(attribute_name, options={})
click to toggle source
# File lib/resource_model/base.rb, line 275 def self.usd_accessor(attribute_name, options={}) raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol) if self.usd_attributes.include?(attribute_name) raise ArgumentError, "Already contains a usd accessor named `#{attribute_name}`" else usd_regex = /\A\s*[+-]?\s*\$?\s*\d*(\d,\d)*\d*\.?\d*\s*\Z/ @usd_attributes << attribute_name self.class_eval <<-eos attr_reader :#{attribute_name} attr_reader :#{attribute_name}_unconverted_value def #{attribute_name}=(value) @#{attribute_name}_unconverted_value = value @#{attribute_name} = value.present? && value.to_s =~ #{usd_regex.inspect} ? BigDecimal.new(value.to_s.gsub(/[\$,]|\\s/, '')) : nil end validate do if self.#{attribute_name}_unconverted_value.present? != self.#{attribute_name}.present? self.errors.add(:#{attribute_name}, :invalid) end end eos end end
view_template()
click to toggle source
# File lib/resource_model/base.rb, line 13 def self.view_template raise NotImplementedError end
Public Instance Methods
attributes=(attributes)
click to toggle source
# File lib/resource_model/base.rb, line 445 def attributes=(attributes) ( self.class.associated_resource_model_collection_attributes + self.class.associated_model_collection_attributes ).each do |attribute| unless (value = self.send(attribute)).is_a?(Array) && value.present? self.send("#{attribute}=", []) end end if attributes.present? attributes = attributes.dup ( self.class.associated_resource_model_attributes + self.class.associated_resource_model_collection_attributes ).each do |attribute| attribute_attributes_key = "#{attribute}_attributes".to_sym if attributes.key?(attribute) self.send("#{attribute}=", attributes.delete(attribute)) end if attributes.key?(attribute_attributes_key) self.send("#{attribute_attributes_key}=", attributes.delete(attribute_attributes_key)) end end self.class.associated_model_attributes.each do |attribute| id_attribute = "#{attribute}_id".to_sym if attributes.key?(attribute) self.send("#{attribute}=", attributes.delete(attribute)) attributes.delete(id_attribute) elsif attributes.key?(id_attribute) self.send("#{id_attribute}=", attributes.delete(id_attribute)) end end self.class.associated_model_collection_attributes.each do |attribute| ids_attribute = "#{attribute}_ids" if attributes.key?(attribute) self.send("#{attribute}=", attributes.delete(attribute)) attributes.delete(ids_attribute) elsif attributes.key?(ids_attribute) self.send("#{ids_attribute}=", attributes.delete(ids_attribute)) end end attributes.each do |name, value| send("#{name}=", value) end end end
persisted?()
click to toggle source
# File lib/resource_model/base.rb, line 17 def persisted? self.respond_to?(:id) && self.id.present? end
to_json_attributes()
click to toggle source
# File lib/resource_model/base.rb, line 497 def to_json_attributes hash = {} self.class.boolean_attributes.each do |attribute_name| hash[attribute_name] = self.send(attribute_name) end self.class.integer_attributes.each do |attribute_name| hash[attribute_name] = self.send(attribute_name) end self.class.decimal_attributes.each do |attribute_name| hash[attribute_name] = self.send(attribute_name).andand.to_s end self.class.usd_attributes.each do |attribute_name| hash[attribute_name] = self.send(attribute_name).andand.to_s end self.class.date_attributes.each do |attribute_name| hash[attribute_name] = self.send(attribute_name).andand.iso8601 end self.class.string_attributes.each do |attribute_name| hash[attribute_name] = self.send(attribute_name) end self.class.enum_attributes.each do |attribute_name| hash[attribute_name] = self.send(attribute_name) end self.class.associated_model_attributes.each do |attribute_name| id_attribute_name = "#{attribute_name}_id" value = self.send(id_attribute_name) if value hash[id_attribute_name.to_sym] = value end end self.class.associated_model_collection_attributes.each do |attribute_name| ids_attribute_name = "#{attribute_name}_ids" value = self.send(ids_attribute_name) if value hash[ids_attribute_name] = value end end self.class.associated_resource_model_attributes.each do |attribute_name| value = self.send(attribute_name) if value hash["#{attribute_name}_attributes".to_sym] = value.to_json_attributes end end self.class.associated_resource_model_collection_attributes.each do |attribute_name| hash["#{attribute_name}_attributes".to_sym] = self.send(attribute_name).inject({}) do |sub_hash, item| sub_hash[sub_hash.size] = item.to_json_attributes sub_hash end end hash end