Created
February 8, 2012 23:44
-
-
Save dnagir/1775540 to your computer and use it in GitHub Desktop.
Symbols and enums
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module HasSymbolicField | |
extend ActiveSupport::Concern | |
module ClassMethods | |
# Defining (all below are equivalent): | |
# - has_symbolic_field :status, [:active, :pending] | |
# - has_symbolic_field :status, :active => 'Active', :pending => 'Pending' | |
# - has_symbolic_field :status, :active => 'Active', :pending => nil | |
# Accessing: | |
# - it.status # :available | |
# - it.status = :pending | |
# - it.status = 'available' | |
# - it.status_name # "Available" | |
# - it.status_hash.keys # [:active, :pending] | |
# - it.status_hash.values # ["Active", "Pending"] | |
# - it.status_allowed? :random # false | |
# - it.status = :random # error | |
def has_symbolic_field(field, options={}) | |
clazz = self | |
options ||= {} | |
raise "Please provide the available options hash for #{clazz.name}##{field}." if options.empty? | |
# For array, convert it to Hash magically | |
options = Hash[ options.map {|v| [v.to_s.underscore.to_sym, v.to_s.humanize] } ] unless options.respond_to? :keys | |
options.each_pair do |k,v| | |
options[k] = k.to_s.humanize if v.blank? | |
end | |
# Create a closure | |
defining = lambda { | |
clazz.send(:define_method, "#{field}_allowed?") do |value| | |
return true if value.blank? | |
options.keys.include? value.to_sym | |
end | |
clazz.send(:define_method, "#{field}_name") do | |
key = read_attribute(field).try(:to_sym) | |
options[key] | |
end | |
clazz.send(:define_method, "#{field}_hash") do | |
options | |
end | |
clazz.class.send(:define_method, "#{field}_hash") do | |
options | |
end | |
clazz.send(:define_method, field) do | |
read_attribute(field).try(:to_sym) | |
end | |
clazz.send(:define_method, "#{field}=") do |value| | |
raise "The value '#{value}' for #{clazz.name}##{field} is not allowed." unless send("#{field}_allowed?", value) | |
write_attribute field, value.try(:to_s) | |
end | |
} | |
defining.call | |
end | |
end | |
end | |
::ActiveRecord::Base.send(:include, HasSymbolicField) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ActiveRecord::Base | |
has_symbolic_field :category, { | |
admin: 'Administrators', | |
managers: 'Sales Managers', | |
sales: 'Sales Staff', | |
external: 'External Networks' | |
} | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment