Skip to content

Instantly share code, notes, and snippets.

@MarioCarrion
Created January 15, 2015 03:09
Show Gist options
  • Save MarioCarrion/fd1ec472a859528615d3 to your computer and use it in GitHub Desktop.
Save MarioCarrion/fd1ec472a859528615d3 to your computer and use it in GitHub Desktop.
module Versioning
class Base
PREFIX = '__versioned'
LENGTH = PREFIX.length
def version
raise ArgumentError.new('not defined')
end
def columns
@columns ||= column_accessors.collect { |x| x[(LENGTH + 1)..-1] }.join(',')
end
def values
column_accessors.collect { |column| self.send(column) }.join(',')
end
class << self
def versioned_accessor(name, type, options = { })
options.merge!({ length: 0, nil: true }) { |key, oldval, newval| oldval }
name = name.to_sym
column_name = "#{PREFIX}_#{name}".to_sym
raise ArgumentError.new("Name #{name} is duplicated") if public_method_defined?(column_name)
raise ArgumentError.new("Invalid type #{type}") unless [ :string, :integer ].include? type
raise ArgumentError.new("Invalid length #{options[:length]}") if type == :string && options[:length].to_i <= 0
define_method(column_name) do
case type
when :string
instance_variable_get("@#{name}")
when :integer
value = instance_variable_get("@#{name}")
options[:nil] ? value : value.to_i
end
end
alias_method("#{name}", "#{column_name}")
define_method("#{column_name}=") do |value|
raise ArgumentError.new("Nil not supported for #{name}") if !options[:nil] && value.nil?
return if value.nil? && options[:nil]
case type
when :integer
instance_variable_set("@#{name}", value.to_i)
when :string
instance_variable_set("@#{name}", value[0..(options[:length] - 1)])
end
end
alias_method("#{name}=", "#{column_name}=")
end
end
private
def column_accessors
@column_accessors ||= methods.select { |x| x[0..(LENGTH - 1)] == PREFIX && x[-1..-1] != '=' }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment