Skip to content

Instantly share code, notes, and snippets.

@mrnugget
Created June 12, 2012 14:46
Show Gist options
  • Select an option

  • Save mrnugget/2917962 to your computer and use it in GitHub Desktop.

Select an option

Save mrnugget/2917962 to your computer and use it in GitHub Desktop.
Changed attributes
#
# FIRST VERSION
#
# Using string interpolation
#
class Endpoint
attr_reader :changed_attributes
def self.has_attribute(attr_name)
attr_reader attr_name
class_eval %Q"
def #{attr_name}=(value)
unless defined? @changed_attributes
@changed_attributes = {}
end
@#{attr_name} = value
@changed_attributes[:#{attr_name}] = value
end
"
end
end
class Player < Endpoint
has_attribute :nickname
has_attribute :name
def initialize(attributes = {})
attributes.each do |k,v|
send("#{k}=", v)
end
end
end
player = Player.new
player.nickname = 'mrnugget'
puts player.changed_attributes.inspect # => {:nickname => "mrnugget"}
player2 = Player.new(name: 'Foobar')
puts player2.changed_attributes.inspect # => {:name => "Foobar"}
player2.nickname = 'barfoobar'
puts player2.changed_attributes.inspect # => {:name => "Foobar", :nickname => "barfoobar"}
#
# SECOND VERSION
#
# Using `define_method`
#
# Produces the same results
#
class Endpoint
attr_reader :changed_attributes
def self.has_attribute(attr_name)
attr_reader attr_name
class_eval do
define_method("#{attr_name}=") do |value|
unless defined? @changed_attributes
@changed_attributes = {}
end
instance_variable_set("@#{attr_name}", value)
@changed_attributes[attr_name] = value
end
end
end
end
class Player < Endpoint
has_attribute :nickname
has_attribute :name
def initialize(attributes = {})
attributes.each do |k,v|
send("#{k}=", v)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment