Skip to content

Instantly share code, notes, and snippets.

@erichurst
Last active August 29, 2015 13:56
Show Gist options
  • Save erichurst/8944603 to your computer and use it in GitHub Desktop.
Save erichurst/8944603 to your computer and use it in GitHub Desktop.
Simple module for dynamic values
module ModMachine
extend ActiveSupport::Concern
included do
end
module ClassMethods
#
# Builds a module with constants assigned to the index passed in the `options` array. Be sure
# to pass all arguments as you would write them manually. In other words `attribute` and any
# constants passed in `options` should be classified case (e.g. ThisModule).
#
# `attribute` = Name of the class attribute that should be the module's name. MUST be a attribute
# of the class.
# `options` = Array of constants identified with `attribute`
#
# example
# mod_machine_for("Category", ["PeerReviewed", "NonPeerReviewed", "CaseStudy"])
#
def mod_machine_for(attribute, options=[])
constants = ""
options.each_with_index do |constant, index|
constants << "#{constant} = #{index}; "
end
mod = %Q{module #{attribute}; #{constants} end}
self.module_eval(mod)
build_boolean_instance_methods(attribute, options)
build_mutable_instance_methods(attribute, options)
end
#
# Builds out the boolean methods for constants defined in `mod_machine_for`.
# Arguments must follow the same format as the aforementioned method.
#
def build_boolean_instance_methods(attribute, options=[])
options.each do |const|
class_eval <<-RUBY
def #{const.to_s.demodulize.tableize.singularize}?
self.#{attribute.downcase} == #{attribute}::#{const.to_s.demodulize}
end
RUBY
end
end
#
# Builds out mutable update methods for constants defined in `mod_machine_for`.
# Arguments must follow the same format as the aforementioned method.
#
# example
# object.case_study!
# #=> UPDATE 'objects' SET 'category' = 2 WHERE 'objects'.'id' = 1;
# object.case_study?
# #=> true
#
def build_mutable_instance_methods(attribute, options=[])
column = ":" + attribute.to_s.downcase
options.each do |const|
class_eval <<-RUBY
def #{const.to_s.demodulize.tableize.singularize}!
update_attribute #{column}, #{attribute}::#{const.to_s.demodulize}
end
RUBY
end
end
end #End ClassMethods
end #End StateMachine
@erichurst
Copy link
Author

Example:

mod_machine_for("Status", ["Active", "Inactive", "Archived"])

builds out methods for active?, inactive?, archived?, etc.
builds out methods for active!, inactive!, archived!, etc.

Would greatly appreciate feedback on ways to make this more concise, and generally better.

@erichurst
Copy link
Author

In Rails 4.1 you should just use ActiveRecord::Enum as it is the same functionality. http://api.rubyonrails.org/v4.1.0/classes/ActiveRecord/Enum.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment