Module: Gorillib::Model
- Extended by:
- Concern
- Defined in:
- lib/gorillib/model/base.rb,
lib/gorillib/model/lint.rb,
lib/gorillib/model/field.rb,
lib/gorillib/model/errors.rb,
lib/gorillib/model/defaults.rb,
lib/gorillib/model/validate.rb,
lib/gorillib/model/doc_string.rb,
lib/gorillib/model/named_schema.rb,
lib/gorillib/model/schema_magic.rb,
lib/gorillib/model/serialization.rb,
lib/gorillib/model/active_model_shim.rb,
lib/gorillib/model/positional_fields.rb,
lib/gorillib/model/serialization/csv.rb,
lib/gorillib/model/serialization/tsv.rb,
lib/gorillib/model/serialization/json.rb,
lib/gorillib/model/active_model_naming.rb,
lib/gorillib/model/serialization/lines.rb,
lib/gorillib/model/active_model_conversion.rb
Overview
Provides a set of class methods for defining a field schema and instance methods for reading and writing attributes.
Defined Under Namespace
Modules: ActiveModelShim, ClassMethods, Conversion, DocString, Error, Lint, LoadFromCsv, LoadFromJson, LoadFromTsv, LoadLines, NamedSchema, Naming, PositionalFields, Validate Classes: ConflictingPositionError, Field, Name, RawDataMismatchError, SimpleCollectionField, UnknownFieldError
Instance Method Summary collapse
-
#==(other) ⇒ true, false
Two models are equal if they have the same class and their attributes are equal.
- #as_json(*args) ⇒ Object
-
#attribute_set?(field_name) ⇒ true, false
True if the attribute is set.
-
#attribute_values ⇒ Array[Object]
All the attributes, in field order, with
nil
where unset. -
#attributes ⇒ {Symbol => Object}
Returns a Hash of all attributes.
-
#compact_attributes ⇒ {Symbol => Object}
Returns a Hash of all attributes that have been set.
- #handle_extra_attributes(attrs) ⇒ Object
- #initialize(*args, &block) ⇒ Object
-
#inspect ⇒ String
override to_inspectable (not this) in your descendant class.
- #inspect_compact ⇒ Object
-
#read_attribute(field_name) ⇒ Object
Read a value from the model's attributes.
-
#read_unset_attribute(field_name) ⇒ Object
This is called by
read_attribute
if an attribute is unset; you should not call this directly. -
#receive!(hsh = {}) ⇒ nil
Accept the given attributes, converting each value to the appropriate type, constructing included models and collections, and other triggers as defined.
-
#to_inspectable ⇒ String
assembles just the given attributes into the inspect string.
- #to_json(options = {}) ⇒ Object
- #to_s ⇒ Object
- #to_tsv(options = {}) ⇒ Object
- #to_wire(options = {}) ⇒ Object
-
#unset_attribute(field_name) ⇒ Object
Unset an attribute.
-
#update_attributes(hsh) ⇒ Gorillib::Model
Accept the given attributes, adopting each value directly.
-
#write_attribute(field_name, val) ⇒ Object
Write the value of a single attribute.
Methods included from Concern
append_features, extended, included
Instance Method Details
#==(other) ⇒ true, false
Two models are equal if they have the same class and their attributes are equal.
187 188 189 190 |
# File 'lib/gorillib/model/base.rb', line 187 def ==(other) return false unless other.instance_of?(self.class) attributes == other.attributes end |
#as_json(*args) ⇒ Object
18 |
# File 'lib/gorillib/model/serialization.rb', line 18 def as_json(*args) to_wire(*args) ; end |
#attribute_set?(field_name) ⇒ true, false
True if the attribute is set.
Note that an attribute can have the value nil but be set.
174 175 176 |
# File 'lib/gorillib/model/base.rb', line 174 def attribute_set?(field_name) instance_variable_defined?("@#{field_name}") end |
#attribute_values ⇒ Array[Object]
Returns all the attributes, in field order, with nil
where unset.
41 42 43 |
# File 'lib/gorillib/model/base.rb', line 41 def attribute_values self.class.field_names.map{|fn| read_attribute(fn) } end |
#attributes ⇒ {Symbol => Object}
Returns a Hash of all attributes
32 33 34 35 36 37 38 |
# File 'lib/gorillib/model/base.rb', line 32 def attributes self.class.field_names.inject(Hash.new) do |hsh, fn| # hsh[fn] = attribute_set?(fn) ? read_attribute(fn) : nil hsh[fn] = read_attribute(fn) hsh end end |
#compact_attributes ⇒ {Symbol => Object}
Returns a Hash of all attributes that have been set
52 53 54 55 56 57 |
# File 'lib/gorillib/model/base.rb', line 52 def compact_attributes self.class.field_names.inject(Hash.new) do |hsh, fn| hsh[fn] = read_attribute(fn) if attribute_set?(fn) hsh end end |
#handle_extra_attributes(attrs) ⇒ Object
86 87 88 89 |
# File 'lib/gorillib/model/base.rb', line 86 def handle_extra_attributes(attrs) @_extra_attributes ||= Hash.new @_extra_attributes.merge!(attrs) end |
#initialize(*args, &block) ⇒ Object
21 22 23 24 |
# File 'lib/gorillib/model/base.rb', line 21 def initialize(*args, &block) attrs = self.class.attrs_hash_from_args(args) receive!(attrs, &block) end |
#inspect ⇒ String
override to_inspectable (not this) in your descendant class
194 195 196 197 198 199 200 201 |
# File 'lib/gorillib/model/base.rb', line 194 def inspect str = '#<' << self.class.name.to_s attrs = to_inspectable if attrs.present? str << '(' << attrs.map{|attr, val| "#{attr}=#{val.respond_to?(:inspect_compact) ? val.inspect_compact : val.inspect}" }.join(", ") << ')' end str << '>' end |
#inspect_compact ⇒ Object
207 208 209 |
# File 'lib/gorillib/model/base.rb', line 207 def inspect_compact str = "#<#{self.class.name.to_s}>" end |
#read_attribute(field_name) ⇒ Object
Read a value from the model's attributes.
120 121 122 123 124 125 126 127 |
# File 'lib/gorillib/model/base.rb', line 120 def read_attribute(field_name) attr_name = "@#{field_name}" if instance_variable_defined?(attr_name) instance_variable_get(attr_name) else read_unset_attribute(field_name) end end |
#read_unset_attribute(field_name) ⇒ Object
This is called by read_attribute
if an attribute is unset; you should
not call this directly. You might use this to provide defaults, or lazy
access, or layered resolution.
Once a non-nil default value has been read, it is fixed on the field; this method
will not be called again, and attribute_set?(...)
will return true
.
If the default is generated from a block (or anything but a literal nil), no default is set:
Defaultable.field :might_be_nil, String, default: ->{ puts 'ran!'; some_other_value ? some_other_value.reverse : nil }
Defaultable.field :some_other_value, String
dd = Defaultable.new
dd.attribute_set?(:might_be_nil) # => false
dd.might_be_nil # => nil
'ran!' # block was run
dd.might_be_nil # => nil
'ran!' # block was run again
dd.some_other_val = 'hello'
dd.might_be_nil # => 'olleh'
'ran!' # block was run again, and set a value this time
dd.some_other_val = 'goodbye'
dd.might_be_nil # => 'olleh'
# block was not run again
86 87 88 89 90 91 92 |
# File 'lib/gorillib/model/defaults.rb', line 86 def read_unset_attribute(field_name) field = self.class.fields[field_name] or return nil return unless field.has_default? val = attribute_default(field) return nil if val.nil? && (not field.default.nil?) # don't write nil unless intent is clearly to have default nil write_attribute(field.name, val) end |
#receive!(hsh = {}) ⇒ nil
Accept the given attributes, converting each value to the appropriate type, constructing included models and collections, and other triggers as defined.
Use #receive!
to accept 'dirty' data -- from JSON, from a nested hash,
or some such. Use #update_attributes
if your data is already type safe.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/gorillib/model/base.rb', line 69 def receive!(hsh={}) if hsh.respond_to?(:attributes) hsh = hsh.compact_attributes else Gorillib::Model::Validate.hashlike!(hsh){ "attributes for #{self.inspect}" } hsh = hsh.dup end self.class.field_names.each do |field_name| if hsh.has_key?(field_name) then val = hsh.delete(field_name) elsif hsh.has_key?(field_name.to_s) then val = hsh.delete(field_name.to_s) else next ; end self.send("receive_#{field_name}", val) end handle_extra_attributes(hsh) nil end |
#to_inspectable ⇒ String
assembles just the given attributes into the inspect string.
213 214 215 |
# File 'lib/gorillib/model/base.rb', line 213 def to_inspectable compact_attributes end |
#to_json(options = {}) ⇒ Object
20 21 22 |
# File 'lib/gorillib/model/serialization.rb', line 20 def to_json(={}) MultiJson.dump(to_wire(), ) end |
#to_s ⇒ Object
203 204 205 |
# File 'lib/gorillib/model/base.rb', line 203 def to_s inspect end |
#to_tsv(options = {}) ⇒ Object
24 25 26 27 28 |
# File 'lib/gorillib/model/serialization.rb', line 24 def to_tsv(={}) attributes.map do |key, attr| attr.respond_to?(:to_wire) ? attr.to_wire() : attr end.join("\t") end |
#to_wire(options = {}) ⇒ Object
12 13 14 15 16 17 |
# File 'lib/gorillib/model/serialization.rb', line 12 def to_wire(={}) compact_attributes.merge(:_type => self.class.typename).inject({}) do |acc, (key,attr)| acc[key] = attr.respond_to?(:to_wire) ? attr.to_wire() : attr acc end end |
#unset_attribute(field_name) ⇒ Object
Unset an attribute. Subsequent reads of the attribute will return nil
,
and attribute_set?
for that field will return false.
156 157 158 159 160 161 162 163 164 |
# File 'lib/gorillib/model/base.rb', line 156 def unset_attribute(field_name) if instance_variable_defined?("@#{field_name}") val = instance_variable_get("@#{field_name}") remove_instance_variable("@#{field_name}") return val else return nil end end |
#update_attributes(hsh) ⇒ Gorillib::Model
Accept the given attributes, adopting each value directly.
Use #receive!
to accept 'dirty' data -- from JSON, from a nested hash,
or some such. Use #update_attributes
if your data is already type safe.
99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/gorillib/model/base.rb', line 99 def update_attributes(hsh) if hsh.respond_to?(:attributes) then hsh = hsh.attributes ; end Gorillib::Model::Validate.hashlike!(hsh){ "attributes for #{self.inspect}" } self.class.field_names.each do |field_name| if hsh.has_key?(field_name) then val = hsh[field_name] elsif hsh.has_key?(field_name.to_s) then val = hsh[field_name.to_s] else next ; end write_attribute(field_name, val) end self end |
#write_attribute(field_name, val) ⇒ Object
Write the value of a single attribute.
139 140 141 |
# File 'lib/gorillib/model/base.rb', line 139 def write_attribute(field_name, val) instance_variable_set("@#{field_name}", val) end |