Module: XeroKiwi::Accounting::Resource
- Included in:
- Address, Allocation, BrandingTheme, Contact, ContactGroup, ContactPerson, CreditNote, ExternalLink, Invoice, LineItem, Organisation, Overpayment, Payment, PaymentTerm, PaymentTerms, Phone, Prepayment, TrackingCategory, User
- Defined in:
- lib/xero_kiwi/accounting/resource.rb
Overview
Mixin that gives an accounting resource class a declarative ‘attribute` DSL. One declaration per field drives reader generation, hydration (via Hydrator), `to_h`, `from_response`, `==` / `eql?` / `hash`, and ActiveRecord-style `inspect`.
Usage:
class Invoice
include Accounting::Resource
payload_key "Invoices"
identity :invoice_id # two Invoices are equal iff invoice_id matches
attribute :invoice_id, xero: "InvoiceID", type: :guid
attribute :date, xero: "Date", type: :date
attribute :contact, xero: "Contact", type: :object,
of: Contact, reference: true
attribute :line_items, xero: "LineItems", type: :collection, of: LineItem
end
Resources with a server-side primary key (Invoice, Contact, Payment, …) declare ‘identity :xxx_id`. Value types without a stable ID (Address, Phone, LineItem, …) omit `identity` and fall back to structural equality (every attribute must match).
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
- #hash ⇒ Object
-
#initialize(attrs, opts = {}) ⇒ Object
‘opts` is positional, not a kwarg, so that bare string-keyed hashes (`Klass.new(“Foo” => “bar”)`) don’t get silently absorbed as kwargs in Ruby 3.
-
#inspect ⇒ Object
ActiveRecord-style inspect: shows every declared attribute inline.
- #reference? ⇒ Boolean
- #to_h ⇒ Object
Class Method Details
.included(base) ⇒ Object
30 31 32 |
# File 'lib/xero_kiwi/accounting/resource.rb', line 30 def self.included(base) base.extend(ClassMethods) end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/xero_kiwi/accounting/resource.rb', line 97 def ==(other) return false unless other.is_a?(self.class) ids = self.class.identity_attributes if ids && !ids.empty? ids.all? { |attr| public_send(attr) == other.public_send(attr) } else to_h == other.to_h end end |
#hash ⇒ Object
109 110 111 112 113 114 115 116 |
# File 'lib/xero_kiwi/accounting/resource.rb', line 109 def hash ids = self.class.identity_attributes if ids && !ids.empty? ([self.class] + ids.map { |attr| public_send(attr) }).hash else [self.class, to_h].hash end end |
#initialize(attrs, opts = {}) ⇒ Object
‘opts` is positional, not a kwarg, so that bare string-keyed hashes (`Klass.new(“Foo” => “bar”)`) don’t get silently absorbed as kwargs in Ruby 3. Callers passing ‘reference: true` land here as a positional symbol-keyed hash, which is what we want.
79 80 81 82 83 84 85 86 87 |
# File 'lib/xero_kiwi/accounting/resource.rb', line 79 def initialize(attrs, opts = {}) attrs = attrs.transform_keys(&:to_s) @is_reference = opts[:reference] == true self.class.attributes.each do |name, spec| value = Hydrator.call(attrs[spec[:xero]], spec) instance_variable_set("@#{name}", value) end end |
#inspect ⇒ Object
ActiveRecord-style inspect: shows every declared attribute inline. Nested objects collapse to a one-line reference (identity-only when available, otherwise just the class name) so cascades don’t explode. Collections collapse to ‘[N items]`.
122 123 124 125 |
# File 'lib/xero_kiwi/accounting/resource.rb', line 122 def inspect pairs = self.class.attributes.map { |name, spec| "#{name}=#{format_for_inspect(public_send(name), spec)}" } "#<#{self.class} #{pairs.join(' ')}>" end |
#reference? ⇒ Boolean
89 90 91 |
# File 'lib/xero_kiwi/accounting/resource.rb', line 89 def reference? @is_reference end |
#to_h ⇒ Object
93 94 95 |
# File 'lib/xero_kiwi/accounting/resource.rb', line 93 def to_h self.class.attributes.keys.to_h { |key| [key, public_send(key)] } end |