gecko-ruby 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +9 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +41 -0
- data/CONTRIBUTING.md +0 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +144 -0
- data/Rakefile +19 -0
- data/gecko-ruby.gemspec +34 -0
- data/generate.thor +81 -0
- data/lib/gecko-ruby.rb +1 -0
- data/lib/gecko.rb +31 -0
- data/lib/gecko/client.rb +132 -0
- data/lib/gecko/helpers/association_helper.rb +69 -0
- data/lib/gecko/helpers/inspection_helper.rb +51 -0
- data/lib/gecko/helpers/record_helper.rb +29 -0
- data/lib/gecko/helpers/serialization_helper.rb +61 -0
- data/lib/gecko/helpers/validation_helper.rb +91 -0
- data/lib/gecko/record/account.rb +66 -0
- data/lib/gecko/record/address.rb +33 -0
- data/lib/gecko/record/base.rb +66 -0
- data/lib/gecko/record/base_adapter.rb +365 -0
- data/lib/gecko/record/company.rb +41 -0
- data/lib/gecko/record/contact.rb +25 -0
- data/lib/gecko/record/currency.rb +23 -0
- data/lib/gecko/record/exceptions.rb +15 -0
- data/lib/gecko/record/fulfillment.rb +42 -0
- data/lib/gecko/record/fulfillment_line_item.rb +26 -0
- data/lib/gecko/record/image.rb +38 -0
- data/lib/gecko/record/invoice.rb +29 -0
- data/lib/gecko/record/invoice_line_item.rb +18 -0
- data/lib/gecko/record/location.rb +23 -0
- data/lib/gecko/record/order.rb +50 -0
- data/lib/gecko/record/order_line_item.rb +35 -0
- data/lib/gecko/record/product.rb +27 -0
- data/lib/gecko/record/purchase_order.rb +43 -0
- data/lib/gecko/record/purchase_order_line_item.rb +29 -0
- data/lib/gecko/record/tax_type.rb +21 -0
- data/lib/gecko/record/user.rb +44 -0
- data/lib/gecko/record/variant.rb +96 -0
- data/lib/gecko/version.rb +3 -0
- data/test/client_test.rb +29 -0
- data/test/fixtures/vcr_cassettes/accounts.yml +57 -0
- data/test/fixtures/vcr_cassettes/accounts_current.yml +57 -0
- data/test/fixtures/vcr_cassettes/addresses.yml +68 -0
- data/test/fixtures/vcr_cassettes/addresses_count.yml +58 -0
- data/test/fixtures/vcr_cassettes/companies.yml +62 -0
- data/test/fixtures/vcr_cassettes/companies_count.yml +58 -0
- data/test/fixtures/vcr_cassettes/contacts.yml +60 -0
- data/test/fixtures/vcr_cassettes/contacts_count.yml +58 -0
- data/test/fixtures/vcr_cassettes/currencies.yml +62 -0
- data/test/fixtures/vcr_cassettes/currencies_count.yml +58 -0
- data/test/fixtures/vcr_cassettes/fulfillments.yml +59 -0
- data/test/fixtures/vcr_cassettes/fulfillments_count.yml +58 -0
- data/test/fixtures/vcr_cassettes/images.yml +59 -0
- data/test/fixtures/vcr_cassettes/images_count.yml +58 -0
- data/test/fixtures/vcr_cassettes/invoice_line_items.yml +63 -0
- data/test/fixtures/vcr_cassettes/invoice_line_items_count.yml +62 -0
- data/test/fixtures/vcr_cassettes/invoices.yml +63 -0
- data/test/fixtures/vcr_cassettes/invoices_count.yml +62 -0
- data/test/fixtures/vcr_cassettes/locations.yml +65 -0
- data/test/fixtures/vcr_cassettes/locations_count.yml +58 -0
- data/test/fixtures/vcr_cassettes/order_line_items.yml +63 -0
- data/test/fixtures/vcr_cassettes/order_line_items_count.yml +62 -0
- data/test/fixtures/vcr_cassettes/orders.yml +62 -0
- data/test/fixtures/vcr_cassettes/orders_count.yml +58 -0
- data/test/fixtures/vcr_cassettes/products.yml +79 -0
- data/test/fixtures/vcr_cassettes/products_count.yml +58 -0
- data/test/fixtures/vcr_cassettes/products_new_invalid.yml +54 -0
- data/test/fixtures/vcr_cassettes/products_new_valid.yml +58 -0
- data/test/fixtures/vcr_cassettes/purchase_order_line_items.yml +64 -0
- data/test/fixtures/vcr_cassettes/purchase_order_line_items_count.yml +62 -0
- data/test/fixtures/vcr_cassettes/purchase_orders.yml +63 -0
- data/test/fixtures/vcr_cassettes/purchase_orders_count.yml +62 -0
- data/test/fixtures/vcr_cassettes/tax_types.yml +74 -0
- data/test/fixtures/vcr_cassettes/tax_types_count.yml +62 -0
- data/test/fixtures/vcr_cassettes/users.yml +60 -0
- data/test/fixtures/vcr_cassettes/users_count.yml +58 -0
- data/test/fixtures/vcr_cassettes/users_current.yml +54 -0
- data/test/fixtures/vcr_cassettes/variants.yml +60 -0
- data/test/fixtures/vcr_cassettes/variants_count.yml +58 -0
- data/test/gecko_test.rb +7 -0
- data/test/helpers/association_helper_test.rb +56 -0
- data/test/helpers/inspection_helper_test.rb +27 -0
- data/test/helpers/serialization_helper_test.rb +30 -0
- data/test/helpers/validation_helper_test.rb +24 -0
- data/test/record/account_adapter_test.rb +43 -0
- data/test/record/address_adapter_test.rb +14 -0
- data/test/record/address_test.rb +18 -0
- data/test/record/company_adapter_test.rb +14 -0
- data/test/record/company_test.rb +18 -0
- data/test/record/contact_adapter_test.rb +14 -0
- data/test/record/contact_test.rb +18 -0
- data/test/record/currency_adapter_test.rb +14 -0
- data/test/record/currency_test.rb +18 -0
- data/test/record/fulfillment_adapter_test.rb +24 -0
- data/test/record/fulfillment_line_item_adapter_test.rb +21 -0
- data/test/record/fulfillment_line_item_test.rb +18 -0
- data/test/record/fulfillment_test.rb +27 -0
- data/test/record/image_adapter_test.rb +14 -0
- data/test/record/image_test.rb +25 -0
- data/test/record/invoice_adapter_test.rb +14 -0
- data/test/record/invoice_line_item_adapter_test.rb +20 -0
- data/test/record/invoice_line_item_test.rb +18 -0
- data/test/record/invoice_test.rb +18 -0
- data/test/record/location_adapter_test.rb +14 -0
- data/test/record/location_test.rb +18 -0
- data/test/record/order_adapter_test.rb +14 -0
- data/test/record/order_line_item_adapter_test.rb +14 -0
- data/test/record/order_line_item_test.rb +18 -0
- data/test/record/order_test.rb +18 -0
- data/test/record/product_adapter_test.rb +32 -0
- data/test/record/product_test.rb +18 -0
- data/test/record/purchase_order_adapter_test.rb +14 -0
- data/test/record/purchase_order_line_item_adapter_test.rb +14 -0
- data/test/record/purchase_order_line_item_test.rb +18 -0
- data/test/record/purchase_order_test.rb +18 -0
- data/test/record/tax_type_adapter_test.rb +14 -0
- data/test/record/tax_type_test.rb +18 -0
- data/test/record/user_adapter_test.rb +27 -0
- data/test/record/user_test.rb +18 -0
- data/test/record/variant_adapter_test.rb +14 -0
- data/test/record/variant_test.rb +44 -0
- data/test/support/let.rb +10 -0
- data/test/support/shared_adapter_examples.rb +159 -0
- data/test/support/shared_record_examples.rb +21 -0
- data/test/support/testing_adapter.rb +11 -0
- data/test/support/vcr_support.rb +7 -0
- data/test/test_helper.rb +21 -0
- metadata +430 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
module Gecko
|
2
|
+
module Helpers
|
3
|
+
# Helper for has_many/belongs_to relationships
|
4
|
+
module AssociationHelper
|
5
|
+
# Set up a belongs_to relationship between two classes based on a
|
6
|
+
# JSON key of {class_name}_id.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# class Gecko::Record::Variant
|
10
|
+
# belongs_to :product
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @param [Symbol] model_name
|
14
|
+
# @param [#to_hash] options options for setting up the relationship
|
15
|
+
# @option options [String] :class_name Override the default class name
|
16
|
+
# @option options [String] :readonly (false) Whether to serialize
|
17
|
+
# this attribute
|
18
|
+
#
|
19
|
+
# @return [undefined]
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
def belongs_to(model_name, options={})
|
23
|
+
class_name = options[:class_name] || model_name.to_s.classify
|
24
|
+
foreign_key = model_name.to_s.foreign_key.to_sym
|
25
|
+
|
26
|
+
define_method model_name do
|
27
|
+
if (id = attributes[foreign_key])
|
28
|
+
@client.adapter_for(class_name).find(id)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
attribute foreign_key, Integer, readonly: options[:readonly]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Set up a has_many relationship between two classes based on a
|
35
|
+
# JSON key of {class_name}_ids.
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# class Gecko::Record::Product
|
39
|
+
# has_many :variants
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# @param [Symbol] model_name
|
43
|
+
# @param [#to_hash] options options for setting up the relationship
|
44
|
+
# @option options [String] :class_name Override the default class name
|
45
|
+
# @option options [String] :readonly (true) Whether to serialize this
|
46
|
+
# attribute
|
47
|
+
#
|
48
|
+
# @return [undefined]
|
49
|
+
#
|
50
|
+
# @api public
|
51
|
+
def has_many(association_name, options={})
|
52
|
+
model_name = association_name.to_s.singularize
|
53
|
+
class_name = options[:class_name] || model_name.classify
|
54
|
+
foreign_key = model_name.foreign_key.pluralize.to_sym
|
55
|
+
readonly = options.key?(:readonly) ? options[:readonly] : true
|
56
|
+
|
57
|
+
define_method association_name do
|
58
|
+
ids = self.attributes[foreign_key]
|
59
|
+
if ids.any?
|
60
|
+
@client.adapter_for(class_name).find_many(ids)
|
61
|
+
else
|
62
|
+
[]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
attribute foreign_key, Array[Integer], readonly: readonly
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Gecko
|
2
|
+
module Helpers
|
3
|
+
# Helper for providing custom #inspect values to Records
|
4
|
+
module InspectionHelper
|
5
|
+
# Overrides the default inspect to just return the defined attributes
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# company.inspect #=> <Gecko::Record::Company id=123 name="Gecko Inc">
|
9
|
+
#
|
10
|
+
# @return [String]
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
def inspect
|
14
|
+
inspection = self.class.attribute_set.map do |attribute|
|
15
|
+
name = attribute.name
|
16
|
+
"#{name}: #{attribute_for_inspect(name)}"
|
17
|
+
end.join(', ')
|
18
|
+
"#<#{self.class} #{inspection}>"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# Returns an #inspect-like string for the value of the attribute
|
24
|
+
# attr_name.
|
25
|
+
# String attributes are truncated up to 50 characters,
|
26
|
+
# and Date and Time attributes are returned in the :db format.
|
27
|
+
# Other attributes return the value of #inspect without modification.
|
28
|
+
# Duplicated from Rails implementation
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# company.inspect #=> <Gecko::Record::Company id=123 name="Gecko Inc">
|
32
|
+
#
|
33
|
+
# @return [String]
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
def attribute_for_inspect(attr_name)
|
37
|
+
value = attributes[attr_name]
|
38
|
+
|
39
|
+
if value.is_a?(String) && value.length > 50
|
40
|
+
"#{value[0..50]}...".inspect
|
41
|
+
elsif value.is_a?(DateTime) || value.is_a?(Time)
|
42
|
+
%("#{value.strftime("%Y-%m-%d %H:%M:%S")}")
|
43
|
+
elsif value.is_a?(Date)
|
44
|
+
%("#{value.strftime("%Y-%m-%d")}")
|
45
|
+
else
|
46
|
+
value.inspect
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Gecko
|
2
|
+
module Helpers
|
3
|
+
# Helper for registering valid record types
|
4
|
+
module RecordHelper
|
5
|
+
# Registers a record type on the Gecko::Client
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# class Gecko::Client
|
9
|
+
# record :Invoice
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# @return [undefined]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
def record(record_type)
|
16
|
+
define_method record_type do
|
17
|
+
adapter_cache = "@#{record_type}_cache".to_sym
|
18
|
+
unless instance_variable_defined?(adapter_cache)
|
19
|
+
adapter_name = "#{record_type}Adapter".to_sym
|
20
|
+
adapter_klass = Gecko::Record.const_get(adapter_name)
|
21
|
+
adapter = adapter_klass.new(self, record_type)
|
22
|
+
instance_variable_set(adapter_cache, adapter)
|
23
|
+
end
|
24
|
+
instance_variable_get(adapter_cache)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Gecko
|
2
|
+
module Helpers
|
3
|
+
# Provides serialization to records
|
4
|
+
module SerializationHelper
|
5
|
+
# Returns a full JSON representation of a record
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# product.as_json #=> {product: {id: 12, name: "Big"}}
|
9
|
+
#
|
10
|
+
# @return [Hash]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
def as_json
|
14
|
+
{
|
15
|
+
root => serializable_hash
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return a serialized hash of the record's attributes
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# product.serializable_hash #=> {id: 12, name: "Big"}
|
23
|
+
#
|
24
|
+
# @return [Hash]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
def serializable_hash
|
28
|
+
attribute_hash = {}
|
29
|
+
attribute_set.each do |attribute|
|
30
|
+
next if attribute.options[:readonly]
|
31
|
+
serialize_attribute(attribute_hash, attribute)
|
32
|
+
end
|
33
|
+
attribute_hash
|
34
|
+
end
|
35
|
+
|
36
|
+
# Serialize a single attribute
|
37
|
+
#
|
38
|
+
# @param [Hash] attribute_hash Serialized record being iterated over
|
39
|
+
# @param [Virtus::Attribute] attribute The attribute being serialized
|
40
|
+
#
|
41
|
+
# @return [undefined]
|
42
|
+
#
|
43
|
+
# @api private
|
44
|
+
def serialize_attribute(attribute_hash, attribute)
|
45
|
+
attribute_hash[attribute.name] = attributes[attribute.name]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return JSON root key for a record
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
# product.root #=> "product"
|
52
|
+
#
|
53
|
+
# @return [String]
|
54
|
+
#
|
55
|
+
# @api private
|
56
|
+
def root
|
57
|
+
self.class.demodulized_name.underscore.to_sym
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Gecko
|
2
|
+
module Helpers
|
3
|
+
# Provides record validation
|
4
|
+
module ValidationHelper
|
5
|
+
# Returns whether a record is considered valid or not
|
6
|
+
#
|
7
|
+
# @return [Boolean]
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
def valid?
|
11
|
+
errors.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the validation errors object for the record
|
15
|
+
#
|
16
|
+
# @return [Gecko::Errors]
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
def errors
|
20
|
+
@errors ||= Gecko::Errors.new(self)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Errors
|
26
|
+
# The hash of errors for this record
|
27
|
+
#
|
28
|
+
# @return [Hash]
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
attr_reader :messages
|
32
|
+
|
33
|
+
# Set up the error object
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
def initialize(base)
|
37
|
+
@base = base
|
38
|
+
@messages = {}
|
39
|
+
end
|
40
|
+
|
41
|
+
# Fetch the errors for a specific attribute
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
# product.errors[:name]
|
45
|
+
# #=> ["can't be blank"]
|
46
|
+
#
|
47
|
+
# @params [Symbol] :attribute
|
48
|
+
#
|
49
|
+
# @return [Array]
|
50
|
+
#
|
51
|
+
# @api public
|
52
|
+
def [](attribute)
|
53
|
+
messages[attribute.to_sym]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Clear the validation errors
|
57
|
+
#
|
58
|
+
# @example
|
59
|
+
# product.errors.clear
|
60
|
+
#
|
61
|
+
# @return [undefined]
|
62
|
+
#
|
63
|
+
# @api public
|
64
|
+
def clear
|
65
|
+
@messages.clear
|
66
|
+
end
|
67
|
+
|
68
|
+
# Whether there are any errors
|
69
|
+
#
|
70
|
+
# @return [Boolean]
|
71
|
+
#
|
72
|
+
# @api public
|
73
|
+
def empty?
|
74
|
+
messages.all? { |k, v| v && v.empty? && !v.is_a?(String) }
|
75
|
+
end
|
76
|
+
|
77
|
+
# Parse JSON errors response into the error object
|
78
|
+
#
|
79
|
+
# @params [#to_hash] :error_hash hash of errors where key is an attribute
|
80
|
+
# name and value is an array of error strings
|
81
|
+
#
|
82
|
+
# @return [undefined]
|
83
|
+
#
|
84
|
+
# @api private
|
85
|
+
def from_response(error_hash)
|
86
|
+
error_hash.each do |attr, errors|
|
87
|
+
@messages[attr.to_sym] = errors
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'gecko/record/base'
|
2
|
+
|
3
|
+
module Gecko
|
4
|
+
module Record
|
5
|
+
class Account < Base
|
6
|
+
has_many :users
|
7
|
+
has_many :locations
|
8
|
+
|
9
|
+
attribute :name, String
|
10
|
+
attribute :industry, String
|
11
|
+
attribute :logo_url, String, readonly: true
|
12
|
+
attribute :website, String
|
13
|
+
attribute :tax_number, String
|
14
|
+
attribute :country, String
|
15
|
+
attribute :time_zone, String
|
16
|
+
|
17
|
+
attribute :contact_email, String
|
18
|
+
attribute :contact_mobile, String
|
19
|
+
attribute :contact_phone, String
|
20
|
+
|
21
|
+
attribute :invoice_details, String
|
22
|
+
attribute :order_details, String
|
23
|
+
attribute :quote_details, String
|
24
|
+
|
25
|
+
attribute :default_tax_rate, String
|
26
|
+
|
27
|
+
attribute :default_tax_type_id, Integer
|
28
|
+
|
29
|
+
attribute :tax_number_label, String
|
30
|
+
attribute :tax_label, String
|
31
|
+
|
32
|
+
belongs_to :billing_contact, class_name: "User"
|
33
|
+
belongs_to :primary_location, class_name: "Location"
|
34
|
+
belongs_to :primary_billing_location, class_name: "Location"
|
35
|
+
|
36
|
+
# belongs_to :default_currency, class_name: "Currency"
|
37
|
+
# belongs_to :default_payment_term, class_name: "PaymentTerm"
|
38
|
+
# belongs_to :default_purchase_order_price_list, class_name: "PriceList"
|
39
|
+
# belongs_to :default_order_price_list, class_name: "PriceList"
|
40
|
+
|
41
|
+
# attribute :stock_level_warn, String
|
42
|
+
# attribute :subscription_name, String
|
43
|
+
# attribute :subscription_price, String
|
44
|
+
# attribute :annual_subscription_price, String
|
45
|
+
# attribute :expires_at, String
|
46
|
+
end
|
47
|
+
|
48
|
+
class AccountAdapter < BaseAdapter
|
49
|
+
undef :count
|
50
|
+
undef :build
|
51
|
+
|
52
|
+
# Return the account for the logged in user
|
53
|
+
#
|
54
|
+
# @return [Gecko::Record::Account]
|
55
|
+
#
|
56
|
+
# @api public
|
57
|
+
def current
|
58
|
+
if self.has_record_for_id?(:current)
|
59
|
+
record_for_id(:current)
|
60
|
+
else
|
61
|
+
@identity_map[:current] = find(:current)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'gecko/record/base'
|
2
|
+
|
3
|
+
module Gecko
|
4
|
+
module Record
|
5
|
+
class Address < Base
|
6
|
+
belongs_to :company
|
7
|
+
|
8
|
+
attribute :phone_number, String
|
9
|
+
attribute :email, String
|
10
|
+
|
11
|
+
attribute :label, String
|
12
|
+
attribute :company_name, String
|
13
|
+
attribute :address1, String
|
14
|
+
attribute :address2, String
|
15
|
+
attribute :suburb, String
|
16
|
+
attribute :city, String
|
17
|
+
attribute :state, String
|
18
|
+
attribute :country, String
|
19
|
+
attribute :zip_code, String
|
20
|
+
|
21
|
+
attribute :status, String, readonly: true
|
22
|
+
|
23
|
+
alias_method :country_code, :country
|
24
|
+
end
|
25
|
+
|
26
|
+
class AddressAdapter < BaseAdapter
|
27
|
+
# Override plural_path to properly pluralize address
|
28
|
+
def plural_path
|
29
|
+
'addresses'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'gecko/helpers/association_helper'
|
2
|
+
require 'gecko/helpers/inspection_helper'
|
3
|
+
require 'gecko/helpers/serialization_helper'
|
4
|
+
require 'gecko/helpers/validation_helper'
|
5
|
+
|
6
|
+
module Gecko
|
7
|
+
module Record
|
8
|
+
class Base
|
9
|
+
include Virtus.model
|
10
|
+
extend Gecko::Helpers::AssociationHelper
|
11
|
+
include Gecko::Helpers::InspectionHelper
|
12
|
+
include Gecko::Helpers::SerializationHelper
|
13
|
+
include Gecko::Helpers::ValidationHelper
|
14
|
+
|
15
|
+
# Set up the default attributes associated with all records
|
16
|
+
attribute :id, Integer, readonly: true
|
17
|
+
attribute :updated_at, DateTime, readonly: true
|
18
|
+
attribute :created_at, DateTime, readonly: true
|
19
|
+
|
20
|
+
# Overrides the default Virtus functionality to store:
|
21
|
+
# - The Gecko::Client used to create the object
|
22
|
+
# - a raw copy of the attributes for the association helpers to read from
|
23
|
+
#
|
24
|
+
# @return [undefined]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
def initialize(client, attributes={})
|
28
|
+
super(attributes)
|
29
|
+
@client = client
|
30
|
+
end
|
31
|
+
|
32
|
+
# Whether the record has been persisted
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# variant.persisted? #=> true
|
36
|
+
#
|
37
|
+
# @return <Boolean>
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
def persisted?
|
41
|
+
!!id
|
42
|
+
end
|
43
|
+
|
44
|
+
# Save a record
|
45
|
+
#
|
46
|
+
# @return <Gecko::Record::Base>
|
47
|
+
#
|
48
|
+
# @api public
|
49
|
+
def save
|
50
|
+
@client.adapter_for(self.class.demodulized_name).save(self)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return the demodulized class name
|
54
|
+
#
|
55
|
+
# @example
|
56
|
+
# Gecko::Record::Product.demodulized_name #=> "Product"
|
57
|
+
#
|
58
|
+
# @return [String]
|
59
|
+
#
|
60
|
+
# @api private
|
61
|
+
def self.demodulized_name
|
62
|
+
self.name.split('::').last
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|