Class: NestedRecord::Base
- Inherits:
-
Object
- Object
- NestedRecord::Base
- Extended by:
- ActiveModel::Callbacks
- Includes:
- ActiveModel::Attributes, ActiveModel::Dirty, ActiveModel::Model, ActiveModel::Validations::Callbacks, Macro
- Defined in:
- lib/nested_record/base.rb
Class Method Summary collapse
- .attribute(name, *args, primary: false, **options) ⇒ Object
-
.attributes_builder ⇒ Object
:nodoc:.
- .collection_class ⇒ Object
- .collection_methods(&block) ⇒ Object
- .deep_inherited? ⇒ Boolean
- .def_primary_uuid(name) ⇒ Object
- .find_subtype(type_name) ⇒ Object
- .has_attribute?(attr_name) ⇒ Boolean
- .inherited(klass) ⇒ Object
- .instance_type ⇒ Object
- .instantiate(attributes) ⇒ Object
- .new(attributes = nil) ⇒ Object
- .primary_key(*attributes) ⇒ Object
- .primary_key=(attributes) ⇒ Object
- .subtype(name, &block) ⇒ Object
- .subtypes(options) ⇒ Object
- .type_for_attribute(attr_name) ⇒ Object
Instance Method Summary collapse
- #==(other) ⇒ Object
- #as_json ⇒ Object
- #init_with_attributes(attributes) ⇒ Object
-
#initialize(attributes = nil) ⇒ Base
constructor
A new instance of Base.
- #inspect ⇒ Object
- #match?(attrs) ⇒ Boolean
- #query_attribute(attr) ⇒ Object
- #read_attribute(attr) ⇒ Object
Constructor Details
#initialize(attributes = nil) ⇒ Base
Returns a new instance of Base.
225 226 227 228 229 |
# File 'lib/nested_record/base.rb', line 225 def initialize(attributes = nil) super self.type = self.class.instance_type if self.class.deep_inherited? && !(attributes&.key?('type') || attributes&.key?(:type)) _run_initialize_callbacks end |
Class Method Details
.attribute(name, *args, primary: false, **options) ⇒ Object
106 107 108 109 110 |
# File 'lib/nested_record/base.rb', line 106 def attribute(name, *args, primary: false, **) super(name, *args, **).tap do primary_key(name) if primary end end |
.attributes_builder ⇒ Object
:nodoc:
13 14 15 16 17 18 |
# File 'lib/nested_record/base.rb', line 13 def attributes_builder # :nodoc: unless defined?(@attributes_builder) && @attributes_builder @attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, _default_attributes) end @attributes_builder end |
.collection_class ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/nested_record/base.rb', line 61 def collection_class return const_get(collection_class_name, false) if const_defined?(collection_class_name, false) record_class = self collection_superclass = deep_inherited? ? superclass.collection_class : NestedRecord::Collection const_set( collection_class_name, Class.new(collection_superclass) do @record_class = record_class end ) end |
.collection_methods(&block) ⇒ Object
73 74 75 76 |
# File 'lib/nested_record/base.rb', line 73 def collection_methods(&block) raise ArgumentError, 'block is required for .collection_methods' unless block collection_class.class_eval(&block) end |
.deep_inherited? ⇒ Boolean
31 32 33 |
# File 'lib/nested_record/base.rb', line 31 def deep_inherited? @deep_inherted == true end |
.def_primary_uuid(name) ⇒ Object
119 120 121 |
# File 'lib/nested_record/base.rb', line 119 def def_primary_uuid(name) attribute name, :string, default: -> { SecureRandom.uuid }, primary: true end |
.find_subtype(type_name) ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/nested_record/base.rb', line 137 def find_subtype(type_name) return self unless type_name.present? type_name = type_name.to_s.camelize subclass = local_subtype(type_name) subclass ||= begin if type_name.start_with?('::') NestedRecord.constantize(type_name) elsif subtypes_store_full? NestedRecord.constantize(type_name) elsif subtypes_namespace NestedRecord.safe_constantize("#{subtypes_namespace}::#{type_name}") || NestedRecord.constantize(type_name) else NestedRecord.lookup_const(self, type_name) end rescue NameError raise NestedRecord::InvalidTypeError, "Failed to locate type '#{type_name}'" end unless subclass.is_a? Class raise NestedRecord::InvalidTypeError, "Invalid type '#{type_name}': should be a class" end unless subclass <= self raise NestedRecord::InvalidTypeError, "Invalid type '#{type_name}': should be a subclass of #{self}" end subclass end |
.has_attribute?(attr_name) ⇒ Boolean
133 134 135 |
# File 'lib/nested_record/base.rb', line 133 def has_attribute?(attr_name) attribute_types.key?(attr_name.to_s) end |
.inherited(klass) ⇒ Object
20 21 22 23 24 25 26 27 28 29 |
# File 'lib/nested_record/base.rb', line 20 def inherited(klass) parent = self if parent < NestedRecord::Base klass.class_eval do attribute :type, :string unless parent.has_attribute? :type @deep_inherted = true end end super end |
.instance_type ⇒ Object
86 87 88 89 90 91 92 93 |
# File 'lib/nested_record/base.rb', line 86 def instance_type @instance_type ||= if subtypes_underscored? type_const.underscore else type_const.dup end end |
.instantiate(attributes) ⇒ Object
53 54 55 56 57 58 59 |
# File 'lib/nested_record/base.rb', line 53 def instantiate(attributes) klass = find_subtype(attributes['type']) attributes = klass.attributes_builder.build_from_database(attributes) klass.allocate.tap do |instance| instance.init_with_attributes(attributes) end end |
.new(attributes = nil) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/nested_record/base.rb', line 35 def new(attributes = nil) if local_subtype? return super else if attributes attributes = attributes.stringify_keys klass = find_subtype(attributes['type']) else klass = self end end if self == klass super else klass.new(attributes) end end |
.primary_key(*attributes) ⇒ Object
112 113 114 115 116 117 |
# File 'lib/nested_record/base.rb', line 112 def primary_key(*attributes) unless attributes.empty? self.primary_key = attributes end @primary_key end |
.primary_key=(attributes) ⇒ Object
123 124 125 126 127 |
# File 'lib/nested_record/base.rb', line 123 def primary_key=(attributes) attributes = Array(attributes) raise ArgumentError, 'primary_key cannot be an empty array' if attributes.empty? @primary_key = attributes.map(&:to_s) end |
.subtype(name, &block) ⇒ Object
95 96 97 98 99 100 101 102 103 104 |
# File 'lib/nested_record/base.rb', line 95 def subtype(name, &block) raise NotImplementedError, 'TODO: Subtyping from local subtype is not supported at the moment' if local_subtype? class_name = name.to_s.camelize subtype = Class.new(self) do @local_subtype = true @type_const = class_name class_eval(&block) if block end local_subtypes!.const_set(class_name, subtype) end |
.subtypes(options) ⇒ Object
78 79 80 81 82 83 84 |
# File 'lib/nested_record/base.rb', line 78 def subtypes() raise NestedRecord::ConfigurationError, '.subtypes is supported only for base classes' if deep_inherited? if [:full] && [:namespace] raise NestedRecord::ConfigurationError, ':full and :namespace options cannot be used together' end @subtypes_options = end |
.type_for_attribute(attr_name) ⇒ Object
129 130 131 |
# File 'lib/nested_record/base.rb', line 129 def type_for_attribute(attr_name) attribute_types[attr_name.to_s] end |
Instance Method Details
#==(other) ⇒ Object
236 237 238 |
# File 'lib/nested_record/base.rb', line 236 def ==(other) attributes == other.attributes end |
#as_json ⇒ Object
240 241 242 |
# File 'lib/nested_record/base.rb', line 240 def as_json attributes.transform_values(&:as_json) end |
#init_with_attributes(attributes) ⇒ Object
231 232 233 234 |
# File 'lib/nested_record/base.rb', line 231 def init_with_attributes(attributes) @attributes = attributes _run_initialize_callbacks end |
#inspect ⇒ Object
244 245 246 247 |
# File 'lib/nested_record/base.rb', line 244 def inspect as = attributes.except('type').map { |k,v| "#{k}: #{v.inspect}" } "#<#{self.class.name} #{as.join(', ')}>" end |
#match?(attrs) ⇒ Boolean
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/nested_record/base.rb', line 265 def match?(attrs) attrs.all? do |attr, others| case attr when :_is_a?, '_is_a?' is_a? others when :_instance_of?, '_instance_of?' instance_of? others when :_not_equal?, '_not_equal?' !equal?(others) else ours = read_attribute(attr) if others.is_a? Array others.include? ours else others == ours end end end end |
#query_attribute(attr) ⇒ Object
255 256 257 258 259 260 261 262 263 |
# File 'lib/nested_record/base.rb', line 255 def query_attribute(attr) value = read_attribute(attr) case value when true then true when false, nil then false else !value.blank? end end |
#read_attribute(attr) ⇒ Object
249 250 251 252 253 |
# File 'lib/nested_record/base.rb', line 249 def read_attribute(attr) name = attr.to_s name = self.class.attribute_aliases[name] || name @attributes.fetch_value(name) end |