Class: AttrJson::AttributeDefinition
- Inherits:
-
Object
- Object
- AttrJson::AttributeDefinition
- Defined in:
- lib/attr_json/attribute_definition.rb,
lib/attr_json/attribute_definition/registry.rb
Overview
Represents a attr_json
definition, on either a AttrJson::Record
or AttrJson::Model. Normally this class is only used by
AttrJson::AttributeDefinition::Registry.
Defined Under Namespace
Classes: Registry
Constant Summary collapse
- NO_DEFAULT_PROVIDED =
Object.new.freeze
- VALID_OPTIONS =
%i{container_attribute store_key default array}.freeze
Instance Attribute Summary collapse
-
#container_attribute ⇒ Object
readonly
Returns the value of attribute container_attribute.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#original_args ⇒ Object
readonly
Returns the value of attribute original_args.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
Class Method Summary collapse
-
.lookup_type(type) ⇒ Object
Can look up a symbol to a type, or leave a type alone, or raise if it's neither.
- .single_model_type?(arg_type) ⇒ Boolean
Instance Method Summary collapse
-
#array_of_primitive_type? ⇒ Boolean
Used for figuring out appropriate behavior in nested attribute implementation among other places.
- #array_type? ⇒ Boolean
- #cast(value) ⇒ Object
-
#default_argument ⇒ Object
Can be value or proc!.
- #deserialize(value) ⇒ Object
- #has_custom_store_key? ⇒ Boolean
- #has_default? ⇒ Boolean
-
#initialize(name, type, options = {}) ⇒ AttributeDefinition
constructor
A new instance of AttributeDefinition.
- #provide_default! ⇒ Object
- #serialize(value) ⇒ Object
-
#single_model_type? ⇒ Boolean
Used for figuring out appropriate behavior for nested attribute implementation among other places.
- #store_key ⇒ Object
Constructor Details
#initialize(name, type, options = {}) ⇒ AttributeDefinition
Returns a new instance of AttributeDefinition.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/attr_json/attribute_definition.rb', line 26 def initialize(name, type, = {}) .assert_valid_keys *VALID_OPTIONS # saving original args for reflection useful for debugging, maybe other things. @original_args = [name, type, ] @name = name.to_sym @container_attribute = [:container_attribute] && [:container_attribute].to_s @store_key = [:store_key] && [:store_key].to_s @default = if .has_key?(:default) [:default] elsif [:array] == true -> { [] } else NO_DEFAULT_PROVIDED end type = self.class.lookup_type(type) @type = ([:array] == true ? AttrJson::Type::Array.new(type) : type) end |
Instance Attribute Details
#container_attribute ⇒ Object (readonly)
Returns the value of attribute container_attribute.
14 15 16 |
# File 'lib/attr_json/attribute_definition.rb', line 14 def container_attribute @container_attribute end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
14 15 16 |
# File 'lib/attr_json/attribute_definition.rb', line 14 def name @name end |
#original_args ⇒ Object (readonly)
Returns the value of attribute original_args.
14 15 16 |
# File 'lib/attr_json/attribute_definition.rb', line 14 def original_args @original_args end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
14 15 16 |
# File 'lib/attr_json/attribute_definition.rb', line 14 def type @type end |
Class Method Details
.lookup_type(type) ⇒ Object
Can look up a symbol to a type, or leave a type alone, or raise if it's neither. Extracted into a method, so it can be called from AttrJson::Model#attr_json, for some timezone aware shenanigans.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/attr_json/attribute_definition.rb', line 118 def self.lookup_type(type) if type.is_a? Symbol # ActiveModel::Type.lookup may make more sense, but ActiveModel::Type::Date # seems to have a bug with multi-param assignment. Mostly they return # the same types, but ActiveRecord::Type::Date works with multi-param assignment. # # We pass `adapter: nil` to avoid triggering a db connection. # See: https://github.com/jrochkind/attr_json/issues/41 # This is at the "cost" of not using any adapter-specific types... which # maybe preferable anyway? # # AND we add precision for datetime/time types... since we're using Rails json # serializing, we're kind of stuck with this precision in current implementation. lookup_kwargs = { adapter: nil } if type == :datetime || type == :time lookup_kwargs = { precision: ActiveSupport::JSON::Encoding.time_precision } end type = ActiveRecord::Type.lookup(type, **lookup_kwargs) elsif !(type.is_a?(ActiveModel::Type::Value) || type.is_a?(ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter)) raise ArgumentError, "Second argument (#{type}) must be a symbol or instance of an ActiveModel::Type::Value subclass" end type end |
Instance Method Details
#array_of_primitive_type? ⇒ Boolean
Used for figuring out appropriate behavior in nested attribute implementation among other places. true if type is an array of things that are not nested models.
111 112 113 |
# File 'lib/attr_json/attribute_definition.rb', line 111 def array_of_primitive_type? array_type? && !self.class.single_model_type?(type.base_type) end |
#array_type? ⇒ Boolean
95 96 97 |
# File 'lib/attr_json/attribute_definition.rb', line 95 def array_type? type.is_a? AttrJson::Type::Array end |
#cast(value) ⇒ Object
50 51 52 |
# File 'lib/attr_json/attribute_definition.rb', line 50 def cast(value) type.cast(value) end |
#default_argument ⇒ Object
Can be value or proc!
75 76 77 78 |
# File 'lib/attr_json/attribute_definition.rb', line 75 def default_argument return nil unless has_default? @default end |
#deserialize(value) ⇒ Object
58 59 60 |
# File 'lib/attr_json/attribute_definition.rb', line 58 def deserialize(value) type.deserialize(value) end |
#has_custom_store_key? ⇒ Boolean
62 63 64 |
# File 'lib/attr_json/attribute_definition.rb', line 62 def has_custom_store_key? !!@store_key end |
#has_default? ⇒ Boolean
70 71 72 |
# File 'lib/attr_json/attribute_definition.rb', line 70 def has_default? @default != NO_DEFAULT_PROVIDED end |
#provide_default! ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/attr_json/attribute_definition.rb', line 80 def provide_default! unless has_default? raise ArgumentError.new("This #{self.class.name} does not have a default defined!") end # Seems weird to assume a Proc can't be the default itself, but I guess # Proc's aren't serializable, so fine assumption. Modeled after: # https://github.com/rails/rails/blob/f2dfd5c6fdffdf65e6f07aae8e855ac802f9302f/activerecord/lib/active_record/attribute/user_provided_default.rb#L12-L16 if @default.is_a?(Proc) cast(@default.call) else cast(@default) end end |
#serialize(value) ⇒ Object
54 55 56 |
# File 'lib/attr_json/attribute_definition.rb', line 54 def serialize(value) type.serialize(value) end |
#single_model_type? ⇒ Boolean
Used for figuring out appropriate behavior for nested attribute implementation among other places. true if type is a nested model, either straight or polymorphic
101 102 103 |
# File 'lib/attr_json/attribute_definition.rb', line 101 def single_model_type? self.class.single_model_type?(type) end |
#store_key ⇒ Object
66 67 68 |
# File 'lib/attr_json/attribute_definition.rb', line 66 def store_key AttrJson.efficient_to_s(@store_key || name) end |