Class: Recurly::Resource
- Inherits:
-
Object
- Object
- Recurly::Resource
- Defined in:
- lib/recurly/resource.rb,
lib/recurly/resource/pager.rb
Overview
The base class for all Recurly resources (e.g. Account, Subscription, Transaction).
Resources behave much like ActiveModel classes, especially like ActiveRecord.
Life Cycle
To take you through the typical life cycle of a resource, we’ll use Account as an example.
Creating a Record
You can instantiate a record before attempting to save it.
account = Recurly::Account.new :first_name => 'Walter'
Once instantiated, you can assign and reassign any attribute.
account.first_name = 'Walt'
account.last_name = 'White'
When you’re ready to save, do so.
account.save # => false
If save returns false
, validation likely failed. You can check the record for errors.
account.errors # => {"account_code"=>["can't be blank"]}
Once the errors are fixed, you can try again.
account.account_code = 'heisenberg'
account.save # => true
The object will be updated with any information provided by the server (including any UUIDs set).
account.created_at # => 2011-04-30 07:13:35 -0700
You can also create accounts in one fell swoop.
Recurly::Account.create(
:first_name => 'Jesse'
:last_name => 'Pinkman'
:account_code => 'capn_cook'
)
# => #<Recurly::Account account_code: "capn_cook" ...>
You can use alternative “bang” methods for exception control. If the record fails to save, a Recurly::Resource::Invalid exception will be raised.
begin
account = Recurly::Account.new :first_name => 'Junior'
account.save!
rescue Recurly::Resource::Invalid
p account.errors
end
You can access the invalid record from the exception itself (if, for example, you use the create!
method).
begin
Recurly::Account.create! :first_name => 'Skylar', :last_name => 'White'
rescue Recurly::Resource::Invalid => e
p e.record.errors
end
Fetching a Record
Records are fetched by their unique identifiers.
account = Recurly::Account.find 'better_call_saul'
# => #<Recurly::Account account_code: "better_call_saul" ...>
If the record doesn’t exist, a Recurly::Resource::NotFound exception will be raised.
Updating a Record
Once fetched, a record can be updated with a hash of attributes.
account.update_attributes :first_name => 'Saul', :last_name => 'Goodman'
# => true
(A bang method, update_attributes!, will raise Recurly::Resource::Invalid.)
You can also update a record by setting attributes and calling save.
account.last_name = 'McGill'
account.save # Alternatively, call save!
Deleting a Record
To delete (deactivate, close, etc.) a fetched record, merely call destroy on it.
account.destroy # => true
Fetching a List of Records
If you want to iterate over a list of accounts, you can use a Pager.
pager = Account.paginate :per_page => 50
If you want to iterate over every record, a convenience method will automatically paginate:
Account.find_each { |account| p account }
Direct Known Subclasses
Account, AddOn, Adjustment, BillingInfo, Coupon, Invoice, Plan, Redemption, Subscription, Transaction
Defined Under Namespace
Classes: Invalid, NotFound, Pager
Class Attribute Summary collapse
-
.attribute_names ⇒ Array?
readonly
The list of attribute names defined for the resource class.
Instance Attribute Summary collapse
-
#attributes ⇒ Hash
The raw hash of record attributes.
-
#etag ⇒ String?
readonly
An ETag for the current record.
- #response ⇒ Net::HTTPResponse? readonly
-
#uri ⇒ String?
The unique resource identifier (URI) of the record (if persisted).
Class Method Summary collapse
- .all(options = {}) ⇒ Object
-
.associations ⇒ Hash
A list of association names for the current class.
-
.belongs_to(parent_name, options = {}) ⇒ Proc
Establishes a belongs_to association.
-
.collection_name ⇒ String
(also: collection_path)
The underscored, pluralized name of the resource class.
-
.count ⇒ Integer
The total record count of the resource in question.
-
.create(attributes = {}) ⇒ Resource
Instantiates and attempts to save a record.
-
.create!(attributes = {}) ⇒ Resource
Instantiates and attempts to save a record.
-
.define_attribute_methods(attribute_names) ⇒ Array
Per attribute, defines readers, writers, boolean and change-tracking methods.
- .embedded!(root_index = false) ⇒ Object
-
.find(uuid, options = {}) ⇒ Resource
A record matching the designated unique identifier.
-
.find_each(per_page = 50) {|record| ... } ⇒ nil
Iterates through every record by automatically paging.
- .first ⇒ Resource?
-
.from_response(response) ⇒ Resource
Instantiates a record from an HTTP response, setting the record’s response attribute in the process.
-
.from_xml(xml) ⇒ Resource
Instantiates a record from an XML blob: either a String or XML element.
-
.has_many(collection_name, options = {}) ⇒ Proc?
Establishes a has_many association.
-
.has_one(member_name, options = {}) ⇒ Proc?
Establishes a has_one association.
-
.member_name ⇒ String
The underscored name of the resource class.
-
.member_path(uuid) ⇒ String
The relative path to a resource’s identifier from the API’s base URI.
-
.paginate(options = {}) ⇒ Pager
(also: scoped, where)
A pager with an iterable collection of records.
-
.reflect_on_association(name) ⇒ :has_many, ...
An association type.
-
.resource_name ⇒ String
The demodulized name of the resource class.
-
.scope(name, params = {}) ⇒ Proc
Defines a new resource scope.
-
.scopes ⇒ Hash
Defined scopes per resource.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#changed ⇒ Array
A list of changed attribute keys.
-
#changed? ⇒ true, false
Do any attributes have unsaved changes?.
-
#changed_attributes ⇒ Hash
Hash of changed attributes.
-
#changes ⇒ Hash
Map of changed attributes to original value and new value.
-
#destroy ⇒ true, false
Attempts to destroy the record.
-
#destroyed? ⇒ true, false
Has the record been destroyed? (Set
true
after a successful destroy.). -
#errors ⇒ Hash
A hash with indifferent read access containing any validation errors where the key is the attribute name and the value is an array of error messages.
-
#initialize(attributes = {}) {|_self| ... } ⇒ Resource
constructor
A new resource instance.
- #inspect(attributes = self.class.attribute_names.to_a) ⇒ String (also: #to_s)
- #marshal_dump ⇒ Object
- #marshal_load(serialization) ⇒ Object
-
#new_record? ⇒ true, false
Is the record new (i.e., not saved on Recurly’s servers)?.
-
#persist!(saved = false) ⇒ true
Marks a record as persisted, i.e.
-
#persisted? ⇒ true, false
Has the record persisted (i.e., saved on Recurly’s servers)?.
-
#previous_changes ⇒ Hash
Previously-changed attributes.
-
#read_attribute(key) ⇒ Object
(also: #[])
The value of a specified attribute, lazily fetching any defined association.
-
#reload(response = nil) ⇒ self
Reloads the record from the server.
-
#save ⇒ true, false
Attempts to save the record, returning the success of the request.
-
#save! ⇒ true
Attempts to save the record, returning
true
if the record was saved and raising Invalid otherwise. - #signable_attributes ⇒ Object
- #to_param ⇒ Object
-
#to_xml(options = {}) ⇒ String
Serializes the record to XML.
-
#update_attributes(attributes = {}) ⇒ true, false
Update a record with a given hash of attributes.
-
#update_attributes!(attributes = {}) ⇒ true
Update a record with a given hash of attributes.
-
#valid? ⇒ true, ...
The validity of the record:
true
if the record was successfully saved (or persisted and unchanged),false
if the record was not successfully saved, ornil
for a record with an unknown state (i.e. (i.e. new records that haven’t been saved and persisted records with changed attributes).. -
#write_attribute(key, value) ⇒ Object
(also: #[]=)
Sets the value of a specified attribute.
Constructor Details
#initialize(attributes = {}) {|_self| ... } ⇒ Resource
Returns A new resource instance.
533 534 535 536 537 538 539 540 541 542 |
# File 'lib/recurly/resource.rb', line 533 def initialize attributes = {} if instance_of? Resource raise Error, "#{self.class} is an abstract class and cannot be instantiated" end @attributes, @new_record, @destroyed, @uri, @href = {}, true, false self.attributes = attributes yield self if block_given? end |
Class Attribute Details
.attribute_names ⇒ Array? (readonly)
Returns The list of attribute names defined for the resource class.
229 230 231 |
# File 'lib/recurly/resource.rb', line 229 def attribute_names @attribute_names end |
Instance Attribute Details
#attributes ⇒ Hash
Returns The raw hash of record attributes.
519 520 521 |
# File 'lib/recurly/resource.rb', line 519 def attributes @attributes end |
#etag ⇒ String? (readonly)
Returns An ETag for the current record.
526 527 528 |
# File 'lib/recurly/resource.rb', line 526 def etag @etag end |
#response ⇒ Net::HTTPResponse? (readonly)
523 524 525 |
# File 'lib/recurly/resource.rb', line 523 def response @response end |
Class Method Details
.all(options = {}) ⇒ Object
250 251 252 |
# File 'lib/recurly/resource.rb', line 250 def all = {} paginate().to_a end |
.associations ⇒ Hash
Returns A list of association names for the current class.
423 424 425 426 427 428 429 430 431 |
# File 'lib/recurly/resource.rb', line 423 def associations @associations ||= begin unless constants.include? :Associations include const_set :Associations, Module.new end { :has_many => [], :has_one => [], :belongs_to => [] } end end |
.belongs_to(parent_name, options = {}) ⇒ Proc
Establishes a belongs_to association.
492 493 494 495 496 497 498 499 500 501 502 |
# File 'lib/recurly/resource.rb', line 492 def belongs_to parent_name, = {} associations[:belongs_to] << parent_name.to_s self::Associations.module_eval { define_method(parent_name) { self[parent_name] } if .key?(:readonly) && [:readonly] == false define_method("#{parent_name}=") { |parent| self[parent_name] = parent } end } end |
.collection_name ⇒ String Also known as: collection_path
Returns The underscored, pluralized name of the resource class.
167 168 169 |
# File 'lib/recurly/resource.rb', line 167 def collection_name Helper.pluralize Helper.underscore(resource_name) end |
.count ⇒ Integer
Returns The total record count of the resource in question.
286 287 288 |
# File 'lib/recurly/resource.rb', line 286 def count paginate.count end |
.create(attributes = {}) ⇒ Resource
Instantiates and attempts to save a record.
335 336 337 |
# File 'lib/recurly/resource.rb', line 335 def create attributes = {} new(attributes) { |record| record.save } end |
.create!(attributes = {}) ⇒ Resource
Instantiates and attempts to save a record.
345 346 347 |
# File 'lib/recurly/resource.rb', line 345 def create! attributes = {} new(attributes) { |record| record.save! } end |
.define_attribute_methods(attribute_names) ⇒ Array
Returns Per attribute, defines readers, writers, boolean and change-tracking methods.
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/recurly/resource.rb', line 206 def define_attribute_methods attribute_names @attribute_names = attribute_names.map! { |m| m.to_s }.sort!.freeze remove_const :AttributeMethods if constants.include? :AttributeMethods include const_set :AttributeMethods, Module.new { attribute_names.each do |name| define_method(name) { self[name] } # Get. define_method("#{name}=") { |value| self[name] = value } # Set. define_method("#{name}?") { !!self[name] } # Present. define_method("#{name}_change") { changes[name] } # Dirt... define_method("#{name}_changed?") { changed_attributes.key? name } define_method("#{name}_was") { changed_attributes[name] } define_method("#{name}_previously_changed?") { previous_changes.key? name } define_method("#{name}_previously_was") { previous_changes[name].first if previous_changes.key? name } end } end |
.embedded!(root_index = false) ⇒ Object
509 510 511 512 513 514 515 |
# File 'lib/recurly/resource.rb', line 509 def root_index = false private :initialize private_class_method(*%w(new create create!)) unless root_index private_class_method(*%w(all find_each first paginate scoped where)) end end |
.find(uuid, options = {}) ⇒ Resource
Returns A record matching the designated unique identifier.
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/recurly/resource.rb', line 311 def find uuid, = {} if uuid.nil? # Should we raise an ArgumentError, instead? raise NotFound, "can't find a record with nil identifier" end = {} if etag = [:etag] [:head] = { 'If-None-Match' => etag } end uri = uuid =~ /^http/ ? uuid : member_path(uuid) begin from_response API.get(uri, {}, ) rescue API::NotFound => e raise NotFound, e.description end end |
.find_each(per_page = 50) {|record| ... } ⇒ nil
Iterates through every record by automatically paging.
278 279 280 |
# File 'lib/recurly/resource.rb', line 278 def find_each per_page = 50 paginate(:per_page => per_page).find_each(&Proc.new) end |
.first ⇒ Resource?
292 293 294 |
# File 'lib/recurly/resource.rb', line 292 def first paginate(:per_page => 1).first end |
.from_response(response) ⇒ Resource
Instantiates a record from an HTTP response, setting the record’s response attribute in the process.
354 355 356 357 358 |
# File 'lib/recurly/resource.rb', line 354 def from_response response record = from_xml response.body record.instance_eval { @etag, @response = response['ETag'], response } record end |
.from_xml(xml) ⇒ Resource
Instantiates a record from an XML blob: either a String or XML element.
Assuming the record is from an API response, the record is flagged as persisted.
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/recurly/resource.rb', line 368 def from_xml xml xml = XML.new xml if xml.name == member_name record = new elsif Recurly.const_defined?(class_name = Helper.classify(xml.name)) record = Recurly.const_get(class_name).send :new elsif root = xml.root and root.elements.empty? return XML.cast root else record = {} end xml.root.attributes.each do |name, value| record.instance_variable_set "@#{name}", value.to_s end xml.each_element do |el| if el.name == 'a' name, uri = el.attribute('name').value, el.attribute('href').value record[name] = case el.attribute('method').to_s when 'get', '' then proc { |*opts| API.get uri, {}, *opts } when 'post' then proc { |*opts| API.post uri, nil, *opts } when 'put' then proc { |*opts| API.put uri, nil, *opts } when 'delete' then proc { |*opts| API.delete uri, *opts } end next end if el.children.empty? && href = el.attribute('href') resource_class = Recurly.const_get( Helper.classify(el.attribute('type') || el.name) ) record[el.name] = case el.name when *associations[:has_many] Pager.new resource_class, :uri => href.value, :parent => record when *(associations[:has_one] + associations[:belongs_to]) lambda { begin relation = resource_class.from_response API.get(href.value) relation.attributes[member_name] = record relation rescue Recurly::API::NotFound end } end else record[el.name] = XML.cast el end end record.persist! if record.respond_to? :persist! record end |
.has_many(collection_name, options = {}) ⇒ Proc?
Establishes a has_many association.
439 440 441 442 443 444 445 446 447 448 449 450 451 |
# File 'lib/recurly/resource.rb', line 439 def has_many collection_name, = {} associations[:has_many] << collection_name.to_s self::Associations.module_eval { define_method(collection_name) { self[collection_name] ||= [] } if .key?(:readonly) && [:readonly] == false define_method("#{collection_name}=") { |collection| self[collection_name] = collection } end } end |
.has_one(member_name, options = {}) ⇒ Proc?
Establishes a has_one association.
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 |
# File 'lib/recurly/resource.rb', line 459 def has_one member_name, = {} associations[:has_one] << member_name.to_s self::Associations.module_eval { define_method(member_name) { self[member_name] } if .key?(:readonly) && [:readonly] == false associated = Recurly.const_get Helper.classify(member_name) define_method("#{member_name}=") { |member| associated_uri = "#{path}/#{member_name}" self[member_name] = case member when Hash associated.send :new, member.merge(:uri => associated_uri) when associated member.uri = associated_uri and member else raise ArgumentError, "expected #{associated}" end } define_method("build_#{member_name}") { |*args| attributes = args.shift || {} self[member_name] = associated.send( :new, attributes.merge(:uri => "#{path}/#{member_name}") ).tap { |child| child.attributes[self.class.member_name] = self } } define_method("create_#{member_name}") { |*args| send("build_#{member_name}", *args).tap { |child| child.save } } end } end |
.member_name ⇒ String
Returns The underscored name of the resource class.
175 176 177 |
# File 'lib/recurly/resource.rb', line 175 def member_name Helper.underscore resource_name end |
.member_path(uuid) ⇒ String
Returns The relative path to a resource’s identifier from the API’s base URI.
185 186 187 |
# File 'lib/recurly/resource.rb', line 185 def member_path uuid [collection_path, uuid].compact.join '/' end |
.paginate(options = {}) ⇒ Pager Also known as: scoped, where
Returns A pager with an iterable collection of records.
244 245 246 |
# File 'lib/recurly/resource.rb', line 244 def paginate = {} Pager.new self, end |
.reflect_on_association(name) ⇒ :has_many, ...
Returns An association type.
505 506 507 |
# File 'lib/recurly/resource.rb', line 505 def reflect_on_association name a = associations.find { |k, v| v.include? name.to_s } and a.first end |
.resource_name ⇒ String
Returns The demodulized name of the resource class.
159 160 161 |
# File 'lib/recurly/resource.rb', line 159 def resource_name Helper.demodulize name end |
.scope(name, params = {}) ⇒ Proc
Defines a new resource scope.
264 265 266 267 268 |
# File 'lib/recurly/resource.rb', line 264 def scope name, params = {} scopes[name = name.to_s] = params extend const_set :Scopes, Module.new unless const_defined? :Scopes self::Scopes.send(:define_method, name) { paginate scopes[name] } end |
.scopes ⇒ Hash
Returns Defined scopes per resource.
255 256 257 |
# File 'lib/recurly/resource.rb', line 255 def scopes @scopes ||= Recurly::Helper.hash_with_indifferent_read_access end |
Instance Method Details
#==(other) ⇒ Object
848 849 850 |
# File 'lib/recurly/resource.rb', line 848 def == other other.is_a?(self.class) && other.to_s == to_s end |
#changed ⇒ Array
Returns A list of changed attribute keys.
572 573 574 |
# File 'lib/recurly/resource.rb', line 572 def changed changed_attributes.keys end |
#changed? ⇒ true, false
Do any attributes have unsaved changes?
578 579 580 |
# File 'lib/recurly/resource.rb', line 578 def changed? !changed_attributes.empty? end |
#changed_attributes ⇒ Hash
Returns Hash of changed attributes.
567 568 569 |
# File 'lib/recurly/resource.rb', line 567 def changed_attributes @changed_attributes ||= {} end |
#changes ⇒ Hash
Returns Map of changed attributes to original value and new value.
583 584 585 586 587 |
# File 'lib/recurly/resource.rb', line 583 def changes changed_attributes.inject({}) { |changes, (key, original_value)| changes[key] = [original_value, self[key]] and changes } end |
#destroy ⇒ true, false
Attempts to destroy the record.
(if the record does not persist on Recurly).
836 837 838 839 840 841 842 |
# File 'lib/recurly/resource.rb', line 836 def destroy return false unless persisted? @response = API.delete uri @destroyed = true rescue API::NotFound => e raise NotFound, e.description end |
#destroyed? ⇒ true, false
Has the record been destroyed? (Set true
after a successful destroy.)
608 609 610 |
# File 'lib/recurly/resource.rb', line 608 def destroyed? @destroyed end |
#errors ⇒ Hash
Returns A hash with indifferent read access containing any validation errors where the key is the attribute name and the value is an array of error messages.
796 797 798 |
# File 'lib/recurly/resource.rb', line 796 def errors @errors ||= Recurly::Helper.hash_with_indifferent_read_access end |
#inspect(attributes = self.class.attribute_names.to_a) ⇒ String Also known as: to_s
879 880 881 882 883 884 885 886 887 |
# File 'lib/recurly/resource.rb', line 879 def inspect attributes = self.class.attribute_names.to_a string = "#<#{self.class}" string << "##@type" if instance_variable_defined? :@type attributes += %w(errors) if errors.any? string << " %s" % attributes.map { |k| "#{k}: #{self.send(k).inspect}" }.join(', ') string << '>' end |
#marshal_dump ⇒ Object
852 853 854 855 856 857 858 859 860 861 862 863 864 |
# File 'lib/recurly/resource.rb', line 852 def marshal_dump [ @attributes.reject { |k, v| v.is_a? Proc }, @new_record, @destroyed, @uri, @href, changed_attributes, previous_changes, etag, response ] end |
#marshal_load(serialization) ⇒ Object
866 867 868 869 870 871 872 873 874 875 876 |
# File 'lib/recurly/resource.rb', line 866 def marshal_load serialization @attributes, @new_record, @destroyed, @uri, @href, @changed_attributes, @previous_changes, @response, @etag = serialization end |
#new_record? ⇒ true, false
Is the record new (i.e., not saved on Recurly’s servers)?
600 601 602 |
# File 'lib/recurly/resource.rb', line 600 def new_record? @new_record end |
#persist!(saved = false) ⇒ true
Marks a record as persisted, i.e. not a new or deleted record, resetting any tracked attribute changes in the process. (This is an internal method and should probably not be called unless you know what you’re doing.)
806 807 808 809 810 811 812 813 |
# File 'lib/recurly/resource.rb', line 806 def persist! saved = false @new_record, @uri = false if changed? @previous_changes = changes if saved changed_attributes.clear end true end |
#persisted? ⇒ true, false
Has the record persisted (i.e., saved on Recurly’s servers)?
617 618 619 |
# File 'lib/recurly/resource.rb', line 617 def persisted? !(new_record? || destroyed?) end |
#previous_changes ⇒ Hash
Returns Previously-changed attributes.
591 592 593 |
# File 'lib/recurly/resource.rb', line 591 def previous_changes @previous_changes ||= {} end |
#read_attribute(key) ⇒ Object Also known as: []
The value of a specified attribute, lazily fetching any defined association.
629 630 631 632 633 634 635 |
# File 'lib/recurly/resource.rb', line 629 def read_attribute key value = attributes[key = key.to_s] if value.respond_to?(:call) && self.class.reflect_on_association(key) value = attributes[key] = value.call end value end |
#reload(response = nil) ⇒ self
Returns Reloads the record from the server.
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 |
# File 'lib/recurly/resource.rb', line 549 def reload response = nil if response return if response.body.length.zero? fresh = self.class.from_response response else fresh = self.class.find( @href || to_param, :etag => (etag unless changed?) ) end fresh and copy_from fresh persist! true self rescue API::NotModified self end |
#save ⇒ true, false
Attempts to save the record, returning the success of the request.
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 |
# File 'lib/recurly/resource.rb', line 712 def save if new_record? || changed? clear_errors @response = API.send( persisted? ? :put : :post, path, to_xml(:delta => true) ) reload response persist! true end true rescue API::UnprocessableEntity => e apply_errors e Transaction::Error.validate! e, (self if is_a? Transaction) false end |
#save! ⇒ true
Attempts to save the record, returning true
if the record was saved and raising Invalid otherwise.
740 741 742 |
# File 'lib/recurly/resource.rb', line 740 def save! save || raise(Invalid.new(self)) end |
#signable_attributes ⇒ Object
844 845 846 |
# File 'lib/recurly/resource.rb', line 844 def signable_attributes Hash[xml_keys.map { |key| [key, self[key]] }] end |
#to_param ⇒ Object
544 545 546 |
# File 'lib/recurly/resource.rb', line 544 def to_param self[self.class.param_name] end |
#to_xml(options = {}) ⇒ String
Serializes the record to XML.
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 |
# File 'lib/recurly/resource.rb', line 681 def to_xml = {} builder = [:builder] || XML.new("<#{self.class.member_name}/>") xml_keys.each { |key| value = respond_to?(key) ? send(key) : self[key] node = builder.add_element key # Duck-typing here is problematic because of ActiveSupport's #to_xml. case value when Resource, Subscription::AddOns value.to_xml .merge(:builder => node) when Array value.each { |e| node.add_element Helper.singularize(key), e } when Hash, Recurly::Money value.each_pair { |k, v| node.add_element k.to_s, v } else node.text = value end } builder.to_s end |
#update_attributes(attributes = {}) ⇒ true, false
Update a record with a given hash of attributes.
772 773 774 |
# File 'lib/recurly/resource.rb', line 772 def update_attributes attributes = {} self.attributes = attributes and save end |
#update_attributes!(attributes = {}) ⇒ true
Update a record with a given hash of attributes.
786 787 788 |
# File 'lib/recurly/resource.rb', line 786 def update_attributes! attributes = {} self.attributes = attributes and save! end |
#valid? ⇒ true, ...
Returns The validity of the record: true
if the record was successfully saved (or persisted and unchanged), false
if the record was not successfully saved, or nil
for a record with an unknown state (i.e. (i.e. new records that haven’t been saved and persisted records with changed attributes).
757 758 759 760 761 |
# File 'lib/recurly/resource.rb', line 757 def valid? return true if persisted? && changed_attributes.empty? return if response.nil? || (errors.empty? && changed_attributes?) errors.empty? end |
#write_attribute(key, value) ⇒ Object Also known as: []=
Sets the value of a specified attribute.
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 |
# File 'lib/recurly/resource.rb', line 646 def write_attribute key, value if changed_attributes.key?(key = key.to_s) changed_attributes.delete key if changed_attributes[key] == value elsif self[key] != value changed_attributes[key] = self[key] end if self.class.associations.values.flatten.include? key value = fetch_association key, value # FIXME: More explicit; less magic. elsif key.end_with?('_in_cents') && !respond_to?(:currency) value = Money.new value unless value.is_a? Money end attributes[key] = value end |