Created
May 15, 2015 09:10
-
-
Save caesarsol/c9bcf6267a210eae0c71 to your computer and use it in GitHub Desktop.
ChoicesFields: model macro to define helper functions on AR model attributes that have pre-determined values
This file contains 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 ChoicesFields | |
extend ActiveSupport::Concern | |
module ClassMethods | |
# Class macro that defines useful function for choice fields (<option> tag fields). | |
# | |
# Will define: | |
# ::fieldname_choices_hash | |
# Returns the hash given to the `choices_field` macro function. | |
# | |
# ::fieldname_choices | |
# Returns the "machine" values, used primarily for AR validation with: | |
# validates :a_field, inclusion: { within: self.a_field_choices } | |
# WARNING: Use `choice_field` before `validates` in your AR model definition. | |
# TODO: Add a convenient custom validator that reads the *_choices automatically. | |
# | |
# ::fieldname_options | |
# Returns an array of arrays, ordered to use with `select_tag` or `f.select`. | |
# | |
# #fieldname_humanized | |
# Will read `#fieldname` and return the associated human-redable value. | |
# | |
# See engines/business/spec/models/concern_choices_fields_spec.rb for details. | |
# | |
def choices_field(fieldname, choices_hash) | |
fieldname = fieldname.to_sym | |
fieldname_choices_hash = "#{fieldname}_choices_hash".to_sym | |
fieldname_choices = "#{fieldname}_choices".to_sym | |
fieldname_options = "#{fieldname}_options".to_sym | |
fieldname_humanized = "#{fieldname}_humanized".to_sym | |
choices_hash = choices_hash.with_indifferent_access | |
choices_keys = choices_hash.keys | |
choices_select = choices_hash.to_a.map(&:reverse) | |
## Class Methods ## | |
# Hash defining choices: machine => human_readable | |
define_singleton_method fieldname_choices_hash do | |
choices_hash | |
end | |
# Choices for validation | |
define_singleton_method fieldname_choices do | |
choices_keys | |
end | |
# Options for select | |
define_singleton_method fieldname_options do | |
choices_select | |
end | |
## Instance Methods ## | |
# Humanized name of current field | |
define_method fieldname_humanized do | |
choices_hash[self.send(fieldname)] | |
end | |
end | |
end | |
end |
This file contains 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
RSpec.describe ChoicesFields do | |
before :example do | |
class C | |
attr_accessor :a_field | |
include Business::Concerns::ChoicesFields | |
choices_field :a_field, { | |
'hello' => "Hello", | |
'world' => "World", | |
} | |
end | |
@it = C.new | |
end | |
it "defines correctly Class method ::fieldname_choices_hash" do | |
expect(@it.class.a_field_choices_hash).to eq({ | |
'hello' => "Hello", | |
'world' => "World", | |
}) | |
end | |
it "defines correctly Class method ::fieldname_choices" do | |
expect(@it.class.a_field_choices).to eq(['hello', 'world']) | |
end | |
it "defines correctly Class method ::fieldname_options" do | |
expect(@it.class.a_field_options).to eq([ | |
["Hello", 'hello'], | |
["World", 'world'], | |
]) | |
end | |
it "defines correctly Instance method #fieldname_humanized" do | |
@it.a_field = 'hello' | |
expect(@it.a_field_humanized).to eq("Hello") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment