enumerize-1.1.1/0000755000004100000410000000000012677055751013564 5ustar www-datawww-dataenumerize-1.1.1/Rakefile0000644000004100000410000000041012677055751015224 0ustar www-datawww-data#!/usr/bin/env rake require "bundler/gem_tasks" require 'rake/testtask' require 'rspec/core/rake_task' Rake::TestTask.new do |t| t.libs << 'test' t.pattern = 'test/*_test.rb' t.verbose = true end RSpec::Core::RakeTask.new task :default => [:test, :spec] enumerize-1.1.1/Gemfile0000644000004100000410000000017512677055751015062 0ustar www-datawww-dataeval_gemfile('Gemfile.global') gem 'minitest', '~> 5.8' gem 'rails', '4.2.4', :require => false gem 'mongoid', '~> 5.0' enumerize-1.1.1/enumerize.gemspec0000644000004100000410000000156712677055751017145 0ustar www-datawww-data# -*- encoding: utf-8 -*- require File.expand_path('../lib/enumerize/version', __FILE__) Gem::Specification.new do |gem| gem.authors = ["Sergey Nartimov"] gem.email = "team@brainspec.com" gem.description = %q{Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper support} gem.summary = %q{Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper support} gem.homepage = "https://github.com/brainspec/enumerize" gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } gem.files = `git ls-files`.split("\n") gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") gem.name = "enumerize" gem.require_paths = ["lib"] gem.version = Enumerize::VERSION gem.required_ruby_version = '>= 1.9.3' gem.add_dependency('activesupport', '>= 3.2') end enumerize-1.1.1/.rspec0000644000004100000410000000003612677055751014700 0ustar www-datawww-data--color --require spec_helper enumerize-1.1.1/MIT-LICENSE0000644000004100000410000000205212677055751015217 0ustar www-datawww-dataCopyright (c) 2012 Brainspec MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. enumerize-1.1.1/Gemfile.global0000644000004100000410000000055412677055751016322 0ustar www-datawww-datasource 'https://rubygems.org' gemspec gem 'rake' gem 'rspec', :require => false gem 'sqlite3', :platform => [:ruby, :mswin, :mingw] gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby gem 'sequel' platforms :rbx do gem 'rubysl', '~> 2.0' gem 'psych' gem 'rubinius-developer_tools' gem 'rubysl-test-unit' end gem 'simple_form' gem 'formtastic' enumerize-1.1.1/spec/0000755000004100000410000000000012677055751014516 5ustar www-datawww-dataenumerize-1.1.1/spec/spec_helper.rb0000644000004100000410000000127112677055751017335 0ustar www-datawww-datarequire 'rails' require 'enumerize' require 'rspec/matchers/fail_matchers' RSpec.configure do |config| config.disable_monkey_patching! config.order = :random Kernel.srand config.seed config.filter_run focus: true config.run_all_when_everything_filtered = true config.expect_with :rspec do |expectations| expectations.syntax = :expect expectations.include_chain_clauses_in_custom_matcher_descriptions = true end config.mock_with :rspec do |mocks| mocks.syntax = :expect mocks.verify_partial_doubles = true end if config.files_to_run.one? config.default_formatter = 'doc' end config.warnings = true config.include RSpec::Matchers::FailMatchers end enumerize-1.1.1/spec/enumerize/0000755000004100000410000000000012677055751016521 5ustar www-datawww-dataenumerize-1.1.1/spec/enumerize/integrations/0000755000004100000410000000000012677055751021227 5ustar www-datawww-dataenumerize-1.1.1/spec/enumerize/integrations/rspec/0000755000004100000410000000000012677055751022343 5ustar www-datawww-dataenumerize-1.1.1/spec/enumerize/integrations/rspec/matcher_spec.rb0000644000004100000410000001740212677055751025331 0ustar www-datawww-datarequire 'active_record' silence_warnings do ActiveRecord::Migration.verbose = false ActiveRecord::Base.logger = Logger.new(nil) ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") end ActiveRecord::Base.connection.instance_eval do create_table :users do |t| t.string :sex t.string :role t.string :account_type end end class User < ActiveRecord::Base extend Enumerize enumerize :sex, :in => [:male, :female], scope: true enumerize :role, :in => [:user, :admin], scope: :having_role enumerize :account_type, :in => [:basic, :premium] end RSpec.describe Enumerize::Integrations::RSpec::Matcher do let(:model) do Class.new do extend Enumerize def self.name 'Model' end end end subject do model.new end describe 'without qualifier' do it 'accepts when has defined a enumerize' do model.enumerize(:sex, :in => [:male, :female]) expect(subject).to enumerize(:sex) end it 'rejects when has not defined a enumerize' do message = 'Expected Model to define enumerize :sex' expect do expect(subject).to enumerize(:sex) end.to fail_with(message) end end describe '#in' do context 'defined as array' do before do model.enumerize(:sex, :in => [:male, :female]) end it 'accepts the right params as an array' do expect(subject).to enumerize(:sex).in([:male, :female]) end it 'accepts the right params as regular params' do expect(subject).to enumerize(:sex).in(:male, :female) end it 'accepts the the right params in a different order' do expect(subject).to enumerize(:sex).in(:female, :male) end it 'rejects wrong params' do message = 'Expected Model to define enumerize :sex in: "boy", "girl"' expect do expect(subject).to enumerize(:sex).in(:boy, :girl) end.to fail_with(message) end it 'has the right message when negated' do message = 'Did not expect Model to define enumerize :sex in: "female", "male"' expect do expect(subject).to_not enumerize(:sex).in(:male, :female) end.to fail_with(message) end end context 'defined as hash' do before do model.enumerize(:sex, :in => { male: 0, female: 1 }) end it 'accepts the right params as an array' do expect(subject).to enumerize(:sex).in(:male, :female) end it 'accepts the right params as a hash' do expect(subject).to enumerize(:sex).in(male: 0, female: 1) end it 'accepts the right params as a hash in a different order' do expect(subject).to enumerize(:sex).in(female: 1, male: 0) end it 'rejects wrong keys' do message = 'Expected Model to define enumerize :sex in: "{:boy=>0, :girl=>1}"' expect do expect(subject).to enumerize(:sex).in(boy: 0, girl: 1) end.to fail_with(message) end it 'rejects wrong values' do message = 'Expected Model to define enumerize :sex in: "{:male=>2, :female=>3}"' expect do expect(subject).to enumerize(:sex).in(male: 2, female: 3) end.to fail_with(message) end end it 'has the right description' do matcher = enumerize(:sex).in(:male, :female) expect(matcher.description).to eq('define enumerize :sex in: "female", "male"') end end describe '#with_default' do before do model.enumerize(:sex, :in => [:male, :female], default: :female) end it 'accepts the right default value' do expect(subject).to enumerize(:sex).in(:male, :female).with_default(:female) end it 'rejects the wrong default value' do message = 'Expected Model to define enumerize :sex in: "female", "male" with "male" as default value' expect do expect(subject).to enumerize(:sex).in(:male, :female).with_default(:male) end.to fail_with(message) end it 'rejects if the `in` is wrong with a correct default value' do message = 'Expected Model to define enumerize :sex in: "boy", "girl" with "female" as default value' expect do expect(subject).to enumerize(:sex).in(:boy, :girl).with_default(:female) end.to fail_with(message) end it 'has the right description' do matcher = enumerize(:sex).in(:male, :female).with_default(:female) message = 'define enumerize :sex in: "female", "male" with "female" as default value' expect(matcher.description).to eq(message) end end describe '#with_i18n_scope' do context 'defined as string' do before do model.enumerize(:sex, :in => [:male, :female], i18n_scope: 'sex') end it 'accepts the right i18n_scope' do expect(subject).to enumerize(:sex).in(:male, :female).with_i18n_scope('sex') end it 'rejects the wrong i18n_scope' do message = 'Expected Model to define enumerize :sex in: "female", "male" i18n_scope: "gender"' expect do expect(subject).to enumerize(:sex).in(:male, :female).with_i18n_scope('gender') end.to fail_with(message) end end context 'defined as array' do before do model.enumerize(:sex, :in => [:male, :female], i18n_scope: ['sex', 'more.sex']) end it 'accepts the wrong i18n_scope' do expect(subject).to enumerize(:sex).in(:male, :female).with_i18n_scope(['sex', 'more.sex']) end it 'rejects the wrong i18n_scope' do message = 'Expected Model to define enumerize :sex in: "female", "male" i18n_scope: ["sex"]' expect do expect(subject).to enumerize(:sex).in(:male, :female).with_i18n_scope(['sex']) end.to fail_with(message) end end end describe '#with_predicates' do it 'accepts when predicates is defined as a boolean' do model.enumerize(:sex, :in => [:male, :female], predicates: true) expect(subject).to enumerize(:sex).in(:male, :female).with_predicates(true) end it 'accepts when predicates is defined as a hash' do model.enumerize(:sex, :in => [:male, :female], predicates: { prefix: true }) expect(subject).to enumerize(:sex).in(:male, :female).with_predicates(prefix: true) end it 'rejects when predicates is not defined' do model.enumerize(:sex, :in => [:male, :female]) message = 'Expected Model to define enumerize :sex in: "female", "male" predicates: true' expect do expect(subject).to enumerize(:sex).in(:male, :female).with_predicates(true) end.to fail_with(message) end end describe '#with_multiple' do it 'accepts when has defined the multiple' do model.enumerize(:sex, :in => [:male, :female], multiple: true) expect(subject).to enumerize(:sex).in(:male, :female).with_multiple(true) end it 'rejects when has not defined the multiple' do model.enumerize(:sex, :in => [:male, :female]) message = 'Expected Model to define enumerize :sex in: "female", "male" multiple: true' expect do expect(subject).to enumerize(:sex).in(:male, :female).with_multiple(true) end.to fail_with(message) end end describe '#with_scope' do subject do User.new end it 'accepts when scope is defined as a boolean' do expect(subject).to enumerize(:sex).in(:male, :female).with_scope(true) end it 'accepts when scope is defined as a hash' do expect(subject).to enumerize(:role).in(:user, :admin).with_scope(scope: :having_role) end it 'rejects when scope is not defined' do message = 'Expected User to define enumerize :account_type in: "basic", "premium" scope: true' expect do expect(subject).to enumerize(:account_type).in(:basic, :premium).with_scope(true) end.to fail_with(message) end end end enumerize-1.1.1/.travis.yml0000644000004100000410000000062012677055751015673 0ustar www-datawww-datalanguage: ruby services: - mongodb before_install: - gem install bundler gemfile: - Gemfile rvm: - 1.9.3 - 2.0.0 - 2.1 - 2.2 - jruby-19mode matrix: include: - rvm: 2.2 gemfile: Gemfile.rails40 - rvm: 2.2 gemfile: Gemfile.mongo_mapper notifications: email: recipients: - lest@brainspec.com - nashby@brainspec.com - dreamfall@brainspec.com enumerize-1.1.1/lib/0000755000004100000410000000000012677055751014332 5ustar www-datawww-dataenumerize-1.1.1/lib/enumerize.rb0000644000004100000410000000417612677055751016672 0ustar www-datawww-datarequire 'active_support/concern' require 'enumerize/version' module Enumerize autoload :Attribute, 'enumerize/attribute' autoload :AttributeMap, 'enumerize/attribute_map' autoload :Value, 'enumerize/value' autoload :Set, 'enumerize/set' autoload :Base, 'enumerize/base' autoload :Module, 'enumerize/module' autoload :Predicates, 'enumerize/predicates' autoload :Predicatable, 'enumerize/predicatable' autoload :ModuleAttributes, 'enumerize/module_attributes' autoload :ActiveRecordSupport, 'enumerize/activerecord' autoload :SequelSupport, 'enumerize/sequel' autoload :MongoidSupport, 'enumerize/mongoid' module Scope autoload :ActiveRecord, 'enumerize/scope/activerecord' autoload :Sequel, 'enumerize/scope/sequel' autoload :Mongoid, 'enumerize/scope/mongoid' end def self.included(base) ActiveSupport::Deprecation.warn '`include Enumerize` was deprecated. Please use `extend Enumerize`.', caller extended(base) end def self.extended(base) base.send :include, Enumerize::Base base.extend Enumerize::Predicates if defined?(::ActiveRecord::Base) base.extend Enumerize::ActiveRecordSupport base.extend Enumerize::Scope::ActiveRecord end if defined?(::Mongoid::Document) base.extend Enumerize::MongoidSupport base.extend Enumerize::Scope::Mongoid end if defined?(::Sequel::Model) base.extend Enumerize::SequelSupport base.extend Enumerize::Scope::Sequel end if defined?(::RailsAdmin) require 'enumerize/integrations/rails_admin' base.extend Enumerize::Integrations::RailsAdmin end if ::Module === base base.extend Enumerize::Base::ClassMethods base.extend Enumerize::ModuleAttributes end super end begin require 'simple_form' require 'enumerize/hooks/simple_form' require 'enumerize/form_helper' rescue LoadError end begin require 'formtastic' require 'enumerize/hooks/formtastic' rescue LoadError end begin require 'rspec/matchers' rescue LoadError else require 'enumerize/integrations/rspec' end end enumerize-1.1.1/lib/enumerize/0000755000004100000410000000000012677055751016335 5ustar www-datawww-dataenumerize-1.1.1/lib/enumerize/predicatable.rb0000644000004100000410000000070712677055751021305 0ustar www-datawww-datamodule Enumerize module Predicatable def respond_to_missing?(method, include_private=false) predicate_method?(method) || super end private def method_missing(method, *args, &block) if predicate_method?(method) predicate_call(method[0..-2], *args, &block) else super end end def predicate_method?(method) method[-1] == '?' && @attr.values.include?(method[0..-2]) end end end enumerize-1.1.1/lib/enumerize/integrations/0000755000004100000410000000000012677055751021043 5ustar www-datawww-dataenumerize-1.1.1/lib/enumerize/integrations/rails_admin.rb0000644000004100000410000000054412677055751023655 0ustar www-datawww-datamodule Enumerize module Integrations module RailsAdmin def enumerize(name, options={}) super _enumerize_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{name}_enum self.class.enumerized_attributes[:#{name}].values.map{|v| [v.text, v.value]} end RUBY end end end end enumerize-1.1.1/lib/enumerize/integrations/rspec/0000755000004100000410000000000012677055751022157 5ustar www-datawww-dataenumerize-1.1.1/lib/enumerize/integrations/rspec/matcher.rb0000644000004100000410000001102412677055751024125 0ustar www-datawww-datamodule Enumerize module Integrations module RSpec class Matcher def initialize(expected_attr) self.expected_attr = expected_attr end def in(*expected_values) self.expected_values = expected_values.flatten self end def with_default(expected_default) self.expected_default = expected_default.to_s self end def with_i18n_scope(expected_i18n_scope) self.expected_i18n_scope = expected_i18n_scope self end def with_predicates(expected_predicates) self.expected_predicates = expected_predicates self end def with_multiple(expected_multiple) self.expected_multiple = expected_multiple self end def with_scope(expected_scope) self.expected_scope = expected_scope self end def failure_message "Expected #{expectation}" end def failure_message_when_negated "Did not expect #{expectation}" end def description description = "define enumerize :#{expected_attr}" description += " in: #{quote_values(expected_values)}" if expected_values description += " with #{expected_default.inspect} as default value" if expected_default description += " i18n_scope: #{expected_i18n_scope.inspect}" if expected_i18n_scope description += " predicates: #{expected_predicates.inspect}" if expected_predicates description += " multiple: #{expected_multiple.inspect}" if expected_multiple description += " scope: #{expected_scope.inspect}" if expected_scope description end def matches?(subject) self.subject = subject matches = true matches &= matches_attribute? matches &= matches_values? if expected_values matches &= matches_default_value? if expected_default matches &= matches_i18n_scope? if expected_i18n_scope matches &= matches_predicates? if expected_predicates matches &= matches_multiple? if expected_multiple matches &= matches_scope? if expected_scope matches end private attr_accessor :expected_attr, :expected_values, :subject, :expected_default, :expected_i18n_scope, :expected_predicates, :expected_multiple, :expected_scope def expectation "#{subject.class.name} to #{description}" end def matches_attribute? attributes.present? end def matches_values? matches_array_values? || matches_hash_values? end def matches_array_values? sorted_values == enumerized_values end def matches_hash_values? return unless expected_values.first.is_a?(Hash) expected_values.first.all? { |k, v| enumerized_value_hash[k.to_s] == v; } end def matches_default_value? expected_default == enumerized_default end def matches_i18n_scope? attributes.i18n_scope == expected_i18n_scope end def matches_predicates? if expected_predicates.is_a?(TrueClass) subject.respond_to?("#{sorted_values.first}?") else subject.respond_to?("#{expected_attr}_#{attributes.values.first}?") end end def matches_multiple? subject.instance_variable_defined?("@_#{expected_attr}_enumerized_set") end def matches_scope? if expected_scope.is_a?(TrueClass) subject_class.respond_to?("with_#{expected_attr}") else subject_class.respond_to?(expected_scope[:scope]) end end def sorted_values @sorted_values ||=expected_values.map(&:to_s).sort end def enumerized_values @enumerized_values ||= attributes.values.sort end def enumerized_default @enumerized_default ||= attributes.default_value end def enumerized_value_hash @enumerized_value_hash ||= attributes.instance_variable_get('@value_hash') end def attributes subject_class.enumerized_attributes.attributes[expected_attr.to_s] end def subject_class @subject_class ||= subject.class end def quote_values(values) sorted_values.map(&:inspect).join(', ') end end end end end enumerize-1.1.1/lib/enumerize/integrations/rspec.rb0000644000004100000410000000045712677055751022512 0ustar www-datawww-datarequire 'enumerize/integrations/rspec/matcher' module Enumerize module Integrations module RSpec def enumerize(attr) ::Enumerize::Integrations::RSpec::Matcher.new(attr) end end end end module RSpec module Matchers include Enumerize::Integrations::RSpec end end enumerize-1.1.1/lib/enumerize/predicates.rb0000644000004100000410000000314512677055751021010 0ustar www-datawww-datarequire 'active_support/core_ext/module/delegation' module Enumerize # Predicate methods. # # Basic usage: # # class User # extend Enumerize # enumerize :sex, in: %w(male female), predicates: true # end # # user = User.new # # user.male? # => false # user.female? # => false # # user.sex = 'male' # # user.male? # => true # user.female? # => false # # Using prefix: # # class User # extend Enumerize # enumerize :sex, in: %w(male female), predicates: { prefix: true } # end # # user = User.new # user.sex = 'female' # user.sex_female? # => true # # Use only and except options to specify what values create # predicate methods for. module Predicates def enumerize(name, options={}) super if options[:predicates] Builder.new(enumerized_attributes[name], options[:predicates]).build(_enumerize_module) end end class Builder def initialize(attr, options) @attr = attr @options = options.is_a?(Hash) ? options : {} end def values values = @attr.values if @options[:only] values &= Array(@options[:only]).map(&:to_s) end if @options[:except] values -= Array(@options[:except]).map(&:to_s) end values end def names values.map { |v| "#{v.tr('-', '_')}?" } end def build(klass) klass.delegate(*names, to: @attr.name, prefix: @options[:prefix], allow_nil: true) end end end end enumerize-1.1.1/lib/enumerize/set.rb0000644000004100000410000000263712677055751017465 0ustar www-datawww-datarequire 'active_support/core_ext/module/delegation' module Enumerize class Set include Enumerable include Predicatable attr_reader :values def initialize(obj, attr, values) @obj = obj @attr = attr @values = [] if values.respond_to?(:each) values.each do |input| value = @attr.find_value(input) if value && !@values.include?(value) @values << value end end end end def <<(value) @values << value mutate! end alias_method :push, :<< delegate :each, :empty?, :size, to: :values def to_ary @values.to_a end def texts @values.map(&:text) end delegate :join, to: :to_ary def ==(other) return false unless other.respond_to?(:each) other.size == size && other.all? { |v| @values.include?(@attr.find_value(v)) } end alias_method :eql?, :== def include?(value) @values.include?(@attr.find_value(value)) end def delete(value) @values.delete(@attr.find_value(value)) mutate! end def inspect "#" end def encode_with(coder) coder.represent_object(Array, @values) end private def predicate_call(value) include?(value) end def mutate! @values = @obj.public_send("#{@attr.name}=", @values).values end end end enumerize-1.1.1/lib/enumerize/sequel.rb0000644000004100000410000000350012677055751020156 0ustar www-datawww-datamodule Enumerize module SequelSupport def enumerize(name, options={}) super _enumerize_module.dependent_eval do if defined?(::Sequel::Model) && self < ::Sequel::Model include InstanceMethods require 'enumerize/hooks/sequel_dataset' end end end private module InstanceMethods def validate super self.class.enumerized_attributes.each do |attr| value = read_attribute_for_validation(attr.name) next if value.blank? if attr.kind_of? Multiple errors.add attr.name, "is invalid" unless value.respond_to?(:all?) && value.all? { |v| v.blank? || attr.find_value(v) } else errors.add attr.name, "is not included in the list" unless attr.find_value(value) end end end def _set_default_value_for_enumerized_attributes _enumerized_values_for_validation.delete_if do |k, v| v.nil? end if defined?(Sequel::Plugins::Serialization::InstanceMethods) modules = self.class.ancestors plugin_idx = modules.index(Sequel::Plugins::Serialization::InstanceMethods) if plugin_idx && plugin_idx < modules.index(Enumerize::SequelSupport::InstanceMethods) abort "ERROR: You need to enable the Sequel serialization plugin before calling any enumerize methods on a model." end plugin_idx = modules.index(Sequel::Plugins::ValidationHelpers::InstanceMethods) if plugin_idx && plugin_idx < modules.index(Enumerize::SequelSupport::InstanceMethods) abort "ERROR: You need to enable the Sequel validation_helpers plugin before calling any enumerize methods on a model." end end super end end end end enumerize-1.1.1/lib/enumerize/value.rb0000644000004100000410000000174012677055751020000 0ustar www-datawww-datarequire 'i18n' module Enumerize class Value < String include Predicatable attr_reader :value def initialize(attr, name, value=nil) @attr = attr @value = value.nil? ? name.to_s : value super(name.to_s) end def text I18n.t(i18n_keys[0], :default => i18n_keys[1..-1]) end def ==(other) super(other.to_s) || value == other end def encode_with(coder) coder.represent_object(self.class.superclass, @value) end private def predicate_call(value) value == self end def i18n_keys @i18n_keys ||= begin i18n_keys = i18n_scopes i18n_keys << [:"enumerize.defaults.#{@attr.name}.#{self}"] i18n_keys << [:"enumerize.#{@attr.name}.#{self}"] i18n_keys << self.underscore.humanize # humanize value if there are no translations i18n_keys.flatten end end def i18n_scopes @attr.i18n_scopes.map { |s| :"#{s}.#{self}" } end end end enumerize-1.1.1/lib/enumerize/module.rb0000644000004100000410000000106112677055751020145 0ustar www-datawww-datamodule Enumerize class Module < ::Module attr_reader :_class_methods def initialize super @_class_methods = ::Module.new @_dependents = [] @_dependent_evals = [] end def included(klass) klass.extend _class_methods @_dependent_evals.each do |block| klass.instance_eval(&block) end @_dependents << klass end def dependent_eval(&block) @_dependents.each do |klass| klass.instance_eval(&block) end @_dependent_evals << block end end end enumerize-1.1.1/lib/enumerize/hooks/0000755000004100000410000000000012677055751017460 5ustar www-datawww-dataenumerize-1.1.1/lib/enumerize/hooks/sequel_dataset.rb0000644000004100000410000000070612677055751023013 0ustar www-datawww-datamodule Enumerize module Hooks module SequelDataset def self.included(klass) klass.alias_method_chain :literal_append, :enumerize end def literal_append_with_enumerize(sql, v) if v.is_a?(Enumerize::Value) literal_append(sql, v.value) else literal_append_without_enumerize(sql, v) end end end end end ::Sequel::Dataset.send :include, Enumerize::Hooks::SequelDataset enumerize-1.1.1/lib/enumerize/hooks/simple_form.rb0000644000004100000410000000241712677055751022325 0ustar www-datawww-datarequire 'active_support/concern' module Enumerize module Hooks module SimpleFormBuilderExtension extend ActiveSupport::Concern included do alias_method_chain :input, :enumerize alias_method_chain :input_field, :enumerize end def input_with_enumerize(attribute_name, options={}, &block) add_input_options_for_enumerized_attribute(attribute_name, options) input_without_enumerize(attribute_name, options, &block) end def input_field_with_enumerize(attribute_name, options={}) add_input_options_for_enumerized_attribute(attribute_name, options) input_field_without_enumerize(attribute_name, options) end private def add_input_options_for_enumerized_attribute(attribute_name, options) klass = object.class if klass.respond_to?(:enumerized_attributes) && (attr = klass.enumerized_attributes[attribute_name]) options[:collection] ||= attr.options if attr.kind_of?(Enumerize::Multiple) && options[:as] != :check_boxes options[:input_html] = options.fetch(:input_html, {}).merge(:multiple => true) end end end end end end ::SimpleForm::FormBuilder.send :include, Enumerize::Hooks::SimpleFormBuilderExtension enumerize-1.1.1/lib/enumerize/hooks/formtastic.rb0000644000004100000410000000146112677055751022162 0ustar www-datawww-datarequire 'active_support/concern' module Enumerize module Hooks module FormtasticFormBuilderExtension extend ActiveSupport::Concern included do alias_method_chain :input, :enumerize end def input_with_enumerize(method, options={}) klass = object.class if klass.respond_to?(:enumerized_attributes) && (attr = klass.enumerized_attributes[method]) options[:collection] ||= attr.options if attr.kind_of?(Enumerize::Multiple) && options[:as] != :check_boxes options[:input_html] = options.fetch(:input_html, {}).merge(:multiple => true) end end input_without_enumerize(method, options) end end end end ::Formtastic::FormBuilder.send :include, Enumerize::Hooks::FormtasticFormBuilderExtension enumerize-1.1.1/lib/enumerize/hooks/uniqueness.rb0000644000004100000410000000121012677055751022176 0ustar www-datawww-datarequire 'active_support/concern' module Enumerize module Hooks module UniquenessValidator extend ActiveSupport::Concern included do alias_method_chain :validate_each, :enumerize end def validate_each_with_enumerize(record, name, value) if record.class.respond_to?(:enumerized_attributes) && (attr = record.class.enumerized_attributes[name]) value = attr.find_value(value).try(:value) end validate_each_without_enumerize(record, name, value) end end end end ::ActiveRecord::Validations::UniquenessValidator.send :include, Enumerize::Hooks::UniquenessValidator enumerize-1.1.1/lib/enumerize/version.rb0000644000004100000410000000005112677055751020343 0ustar www-datawww-datamodule Enumerize VERSION = "1.1.1" end enumerize-1.1.1/lib/enumerize/scope/0000755000004100000410000000000012677055751017446 5ustar www-datawww-dataenumerize-1.1.1/lib/enumerize/scope/sequel.rb0000644000004100000410000000213512677055751021272 0ustar www-datawww-datamodule Enumerize module Scope module Sequel def enumerize(name, options={}) super _enumerize_module.dependent_eval do if defined?(::Sequel::Model) && self < ::Sequel::Model if options[:scope] _define_sequel_scope_methods!(name, options) end require 'enumerize/hooks/sequel_dataset' end end end private def _define_sequel_scope_methods!(name, options) klass = self scope_name = options[:scope] == true ? "with_#{name}" : options[:scope] def_dataset_method scope_name do |*values| values = values.map { |value| klass.enumerized_attributes[name].find_value(value).value } values = values.first if values.size == 1 where(name => values) end if options[:scope] == true def_dataset_method "without_#{name}" do |*values| values = values.map { |value| klass.enumerized_attributes[name].find_value(value).value } exclude(name => values) end end end end end end enumerize-1.1.1/lib/enumerize/scope/mongoid.rb0000644000004100000410000000165412677055751021435 0ustar www-datawww-datamodule Enumerize module Scope module Mongoid def enumerize(name, options={}) super _enumerize_module.dependent_eval do if self < ::Mongoid::Document if options[:scope] _define_mongoid_scope_methods!(name, options) end end end end private def _define_mongoid_scope_methods!(name, options) scope_name = options[:scope] == true ? "with_#{name}" : options[:scope] define_singleton_method scope_name do |*values| values = enumerized_attributes[name].find_values(*values).map(&:value) self.in(name => values) end if options[:scope] == true define_singleton_method "without_#{name}" do |*values| values = enumerized_attributes[name].find_values(*values).map(&:value) not_in(name => values) end end end end end end enumerize-1.1.1/lib/enumerize/scope/activerecord.rb0000644000004100000410000000177712677055751022461 0ustar www-datawww-datamodule Enumerize module Scope module ActiveRecord def enumerize(name, options={}) super _enumerize_module.dependent_eval do if self < ::ActiveRecord::Base if options[:scope] _define_activerecord_scope_methods!(name, options) end end end end private def _define_activerecord_scope_methods!(name, options) scope_name = options[:scope] == true ? "with_#{name}" : options[:scope] define_singleton_method scope_name do |*values| values = enumerized_attributes[name].find_values(*values).map(&:value) values = values.first if values.size == 1 where(name => values) end if options[:scope] == true define_singleton_method "without_#{name}" do |*values| values = enumerized_attributes[name].find_values(*values).map(&:value) where(arel_table[name].not_in(values)) end end end end end end enumerize-1.1.1/lib/enumerize/module_attributes.rb0000644000004100000410000000035512677055751022420 0ustar www-datawww-datamodule Enumerize module ModuleAttributes def included(base) base.extend Enumerize base.send :include, _enumerize_module enumerized_attributes.add_dependant base.enumerized_attributes super end end end enumerize-1.1.1/lib/enumerize/mongoid.rb0000644000004100000410000000043312677055751020316 0ustar www-datawww-datamodule Enumerize module MongoidSupport def enumerize(name, options={}) super _enumerize_module.dependent_eval do if self < ::Mongoid::Document after_initialize :_set_default_value_for_enumerized_attributes end end end end end enumerize-1.1.1/lib/enumerize/base.rb0000644000004100000410000000605412677055751017601 0ustar www-datawww-datamodule Enumerize module Base def self.included(base) base.extend ClassMethods if base.respond_to?(:validate) base.validate :_validate_enumerized_attributes end class << base if (method_defined?(:inherited) || private_method_defined?(:inherited)) && !private_method_defined?(:inherited_without_enumerized) alias_method :inherited_without_enumerized, :inherited private :inherited_without_enumerized end alias_method :inherited, :inherited_with_enumerized end end module ClassMethods def enumerize(name, options={}) attr = Attribute.new(self, name, options) enumerized_attributes << attr unless methods.include?(attr.name) _enumerize_module._class_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{attr.name} enumerized_attributes[:#{attr.name}] end RUBY end attr.define_methods!(_enumerize_module) end def enumerized_attributes @enumerized_attributes ||= AttributeMap.new end def inherited_with_enumerized(subclass) enumerized_attributes.add_dependant subclass.enumerized_attributes if respond_to?(:inherited_without_enumerized, true) inherited_without_enumerized subclass end end private def _enumerize_module @_enumerize_module ||= begin mod = Module.new include mod mod end end end def initialize(*) super _set_default_value_for_enumerized_attributes end def read_attribute_for_validation(key) key = key.to_s if _enumerized_values_for_validation.has_key?(key) _enumerized_values_for_validation[key] elsif defined?(super) super else send(key) end end private def _enumerized_values_for_validation @_enumerized_values_for_validation ||= {} end def _validate_enumerized_attributes self.class.enumerized_attributes.each do |attr| value = read_attribute_for_validation(attr.name) next if value.blank? if attr.kind_of? Multiple errors.add attr.name unless value.respond_to?(:all?) && value.all? { |v| v.blank? || attr.find_value(v) } else errors.add attr.name, :inclusion unless attr.find_value(value) end end end def _set_default_value_for_enumerized_attributes self.class.enumerized_attributes.each do |attr| if respond_to?(attr.name) attr_value = public_send(attr.name) else next end value_for_validation = _enumerized_values_for_validation[attr.name.to_s] if (!attr_value || attr_value.empty?) && (!value_for_validation || value_for_validation.empty?) value = attr.default_value if value.respond_to?(:call) value = value.arity == 0 ? value.call : value.call(self) end public_send("#{attr.name}=", value) end end end end end enumerize-1.1.1/lib/enumerize/activerecord.rb0000644000004100000410000000224712677055751021341 0ustar www-datawww-datamodule Enumerize module ActiveRecordSupport def enumerize(name, options={}) super _enumerize_module.dependent_eval do if self < ::ActiveRecord::Base include InstanceMethods # Since Rails use `allocate` method on models and initializes them with `init_with` method. # This way `initialize` method is not being called, but `after_initialize` callback always gets triggered. after_initialize :_set_default_value_for_enumerized_attributes # https://github.com/brainspec/enumerize/issues/111 require 'enumerize/hooks/uniqueness' end end end module InstanceMethods # https://github.com/brainspec/enumerize/issues/74 def write_attribute(attr_name, value) if self.class.enumerized_attributes[attr_name] _enumerized_values_for_validation[attr_name.to_s] = value end super end # Support multiple enumerized attributes def becomes(klass) became = super klass.enumerized_attributes.each do |attr| became.send("#{attr.name}=", send(attr.name)) end became end end end end enumerize-1.1.1/lib/enumerize/attribute_map.rb0000644000004100000410000000115512677055751021524 0ustar www-datawww-datamodule Enumerize class AttributeMap attr_reader :attributes def initialize @attributes = {} @dependants = [] end def [](name) @attributes[name.to_s] end def <<(attr) @attributes[attr.name.to_s] = attr @dependants.each do |dependant| dependant << attr end end def each @attributes.each_pair do |_name, attr| yield attr end end def empty? @attributes.empty? end def add_dependant(dependant) @dependants << dependant each do |attr| dependant << attr end end end end enumerize-1.1.1/lib/enumerize/attribute.rb0000644000004100000410000001207712677055751020674 0ustar www-datawww-datamodule Enumerize class Attribute attr_reader :name, :values, :default_value, :i18n_scope def initialize(klass, name, options={}) raise ArgumentError, ':in option is required' unless options[:in] raise ArgumentError, ':scope option does not work with option :multiple' if options[:multiple] && options[:scope] extend Multiple if options[:multiple] @klass = klass @name = name.to_sym value_class = options.fetch(:value_class, Value) @values = Array(options[:in]).map { |v| value_class.new(self, *v) } @value_hash = Hash[@values.map { |v| [v.value.to_s, v] }] @value_hash.merge! Hash[@values.map { |v| [v.to_s, v] }] if options[:i18n_scope] raise ArgumentError, ':i18n_scope option accepts only String or Array of strings' unless Array(options[:i18n_scope]).all? { |s| s.is_a?(String) } @i18n_scope = options[:i18n_scope] end if options[:default] @default_value = find_default_value(options[:default]) raise ArgumentError, 'invalid default value' unless @default_value end end def find_default_value(value) if value.respond_to?(:call) value else find_value(value) end end def find_value(value) @value_hash[value.to_s] unless value.nil? end def find_values(*values) values.map { |value| find_value(value) }.compact end def i18n_scopes @i18n_scopes ||= if i18n_scope scopes = Array(i18n_scope) elsif @klass.respond_to?(:model_name) scopes = ["enumerize.#{@klass.model_name.i18n_key}.#{name}"] else [] end end def options(options = {}) values = if options.empty? @values else raise ArgumentError, 'Options cannot have both :only and :except' if options[:only] && options[:except] only = Array(options[:only]).map(&:to_s) except = Array(options[:except]).map(&:to_s) @values.reject do |value| if options[:only] !only.include?(value) elsif options[:except] except.include?(value) end end end values.map { |v| [v.text, v.to_s] } end def respond_to_missing?(method, include_private=false) @value_hash.include?(method.to_s) || super end def define_methods!(mod) mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{name} if defined?(super) self.class.enumerized_attributes[:#{name}].find_value(super) elsif respond_to?(:read_attribute) self.class.enumerized_attributes[:#{name}].find_value(read_attribute(:#{name})) else if defined?(@#{name}) self.class.enumerized_attributes[:#{name}].find_value(@#{name}) else @#{name} = nil end end end def #{name}=(new_value) allowed_value_or_nil = self.class.enumerized_attributes[:#{name}].find_value(new_value) allowed_value_or_nil = allowed_value_or_nil.value unless allowed_value_or_nil.nil? if defined?(super) super allowed_value_or_nil elsif respond_to?(:write_attribute, true) write_attribute '#{name}', allowed_value_or_nil else @#{name} = allowed_value_or_nil end _enumerized_values_for_validation['#{name}'] = new_value.nil? ? nil : new_value.to_s allowed_value_or_nil end def #{name}_text self.#{name} && self.#{name}.text end def #{name}_value self.#{name} && self.#{name}.value end RUBY end private def method_missing(method) if @value_hash.include?(method.to_s) find_value(method) else super end end end module Multiple def find_default_value(value) if value.respond_to?(:call) value else find_values(*value) end end def define_methods!(mod) mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{name} unless defined?(@_#{name}_enumerized_set) if defined?(super) self.#{name} = super elsif respond_to?(:read_attribute) self.#{name} = read_attribute(:#{name}) else if defined?(@#{name}) self.#{name} = @#{name} else self.#{name} = [] end end end @_#{name}_enumerized_set end def #{name}=(values) @_#{name}_enumerized_set = Enumerize::Set.new(self, self.class.enumerized_attributes[:#{name}], values) raw_values = #{name}.values.map(&:value) if defined?(super) super raw_values elsif respond_to?(:write_attribute, true) write_attribute '#{name}', raw_values else @#{name} = raw_values end _enumerized_values_for_validation['#{name}'] = values.respond_to?(:map) ? values.map(&:to_s) : values #{name} end RUBY end end end enumerize-1.1.1/Gemfile.rails400000644000004100000410000000016312677055751016334 0ustar www-datawww-dataeval_gemfile('Gemfile.global') gem 'minitest', '~> 4.1' gem 'rails', '4.0.13', :require => false gem 'mongoid' enumerize-1.1.1/test/0000755000004100000410000000000012677055751014543 5ustar www-datawww-dataenumerize-1.1.1/test/mongo_mapper_test.rb0000644000004100000410000000267612677055751020625 0ustar www-datawww-datarequire 'test_helper' begin silence_warnings do require 'mongo_mapper' end MongoMapper.connection = Mongo::Connection.new('localhost', 27017) MongoMapper.database = 'enumerize-test-suite-of-mongomapper' describe Enumerize do class MongoMapperUser include MongoMapper::Document extend Enumerize key :sex key :role enumerize :sex, :in => %w[male female] enumerize :role, :in => %w[admin user], :default => 'user' end before { $VERBOSE = nil } after { $VERBOSE = true } let(:model) { MongoMapperUser } it 'sets nil if invalid value is passed' do user = model.new user.sex = :invalid user.sex.must_equal nil end it 'saves value' do model.delete_all user = model.new user.sex = :female user.save! user.sex.must_equal 'female' end it 'loads value' do model.delete_all model.create!(:sex => :male) store_translations(:en, :enumerize => {:sex => {:male => 'Male'}}) do user = model.first user.sex.must_equal 'male' user.sex_text.must_equal 'Male' end end it 'has default value' do model.new.role.must_equal 'user' end it 'validates inclusion' do user = model.new user.role = 'wrong' user.wont_be :valid? end it 'assigns value on loaded record' do model.delete_all model.create!(:sex => :male) user = model.first user.sex = :female user.sex.must_equal 'female' end end rescue LoadError # Skip end enumerize-1.1.1/test/attribute_map_test.rb0000644000004100000410000000262112677055751020770 0ustar www-datawww-datarequire 'test_helper' module Enumerize class AttributeMapTest < MiniTest::Spec subject { AttributeMap.new } def make_attr(name) Attribute.new(nil, name, :in => %[a b]) end it 'empty when no attrs' do subject.must_be_empty end it 'not empty when attr added' do subject << make_attr(:a) subject.wont_be_empty end it 'iterates over added attrs' do attr_1 = make_attr(:a) attr_2 = make_attr(:b) subject << attr_1 subject << attr_2 count = 0 actual = [] subject.each do |element| count += 1 actual << element end count.must_equal 2 actual.must_equal [attr_1, attr_2] end it 'reads attribute by name' do attr = make_attr(:a) subject << attr subject[:a].must_equal attr end it 'reads attribute by name using string' do attr = make_attr(:a) subject << attr subject['a'].must_equal attr end it 'updates dependants' do attr = make_attr(:a) dependant = MiniTest::Mock.new dependant.expect(:<<, nil, [attr]) subject.add_dependant dependant subject << attr dependant.verify end it 'adds attrs to dependant' do attr = make_attr(:a) subject << attr dependant = AttributeMap.new subject.add_dependant dependant dependant[:a].must_equal attr end end end enumerize-1.1.1/test/simple_form_test.rb0000644000004100000410000000620512677055751020446 0ustar www-datawww-datarequire 'test_helper' require 'simple_form/version' class SimpleFormSpec < MiniTest::Spec include ViewTestHelper include SimpleForm::ActionViewExtensions::FormHelper class Thing < Struct.new(:name) extend ActiveModel::Naming include ActiveModel::Conversion def persisted? false end end class User < Struct.new(:sex, :age) extend ActiveModel::Naming include ActiveModel::Conversion extend Enumerize enumerize :sex, :in => [:male, :female] def persisted? false end end class Post < Struct.new(:category, :title) extend ActiveModel::Naming include ActiveModel::Conversion extend Enumerize enumerize :categories, :in => [:music, :games], :multiple => true def persisted? false end end let(:user) { User.new } let(:post) { Post.new } it 'renders select with enumerized values using input_field' do concat(simple_form_for(user) do |f| f.input_field(:sex) end) assert_select 'select option[value=male]' assert_select 'select option[value=female]' end it 'renders select with enumerized values' do concat(simple_form_for(user) do |f| f.input(:sex) end) assert_select 'select option[value=male]' assert_select 'select option[value=female]' end it 'renders multiple select with enumerized values' do concat(simple_form_for(post) do |f| f.input(:categories) end) assert_select 'select[multiple=multiple]' assert_select 'select option[value=music]' assert_select 'select option[value=games]' end it 'renders multiple select with selected enumerized value' do post.categories << :music concat(simple_form_for(post) do |f| f.input(:categories) end) assert_select 'select[multiple=multiple]' assert_select 'select option[value=music][selected=selected]' assert_select 'select option[value=games][selected=selected]', count: 0 end it 'renders checkboxes with enumerized values' do concat(simple_form_for(post) do |f| f.input(:categories, as: :check_boxes) end) assert_select 'select[multiple=multiple]', count: 0 assert_select 'input[type=checkbox][value=music]' assert_select 'input[type=checkbox][value=games]' end it 'renders checkboxes with selected enumerized value' do post.categories << :music concat(simple_form_for(post) do |f| f.input(:categories, as: :check_boxes) end) assert_select 'input[type=checkbox][value=music][checked=checked]' assert_select 'input[type=checkbox][value=games][checked=checked]', count: 0 end it 'renders radio buttons with enumerated values' do concat(simple_form_for(user) do |f| f.input(:sex, :as => :radio_buttons) end) assert_select 'input[type=radio][value=male]' assert_select 'input[type=radio][value=female]' end it 'does not affect not enumerized attributes' do concat(simple_form_for(user) do |f| f.input(:age) end) assert_select 'input.string' end it 'does not affect not enumerized classes' do concat(simple_form_for(Thing.new) do |f| f.input(:name) end) assert_select 'input.string' end end enumerize-1.1.1/test/rails_admin_test.rb0000644000004100000410000000126512677055751020415 0ustar www-datawww-datarequire 'test_helper' class RailsAdminSpec < MiniTest::Spec let(:klass) do Class.new do extend Enumerize end end let(:object) { klass.new } it 'defines enum method' do store_translations(:en, :enumerize => {:foo => {:a => 'a text', :b => 'b text'}}) do klass.enumerize(:foo, in: [:a, :b]) object.foo_enum.must_equal [['a text', 'a'], ['b text', 'b']] end end it 'defines enum properly for custom values enumerations' do store_translations(:en, :enumerize => {:foo => {:a => 'a text', :b => 'b text'}}) do klass.enumerize(:foo, in: {:a => 1, :b => 2}) object.foo_enum.must_equal [['a text', 1], ['b text', 2]] end end end enumerize-1.1.1/test/module_attributes_test.rb0000644000004100000410000000244712677055751021671 0ustar www-datawww-datarequire 'test_helper' class ModuleAttributesSpec < MiniTest::Spec it 'inherits attribute from the module' do mod = Module.new do extend Enumerize enumerize :sex, :in => %w[male female], :default => 'male' end klass = Class.new klass.send :include, mod klass.enumerized_attributes[:sex].must_be_instance_of Enumerize::Attribute klass.new.sex.must_equal 'male' klass.sex.must_be_instance_of Enumerize::Attribute end it 'uses new attributes from the module' do mod = Module.new do extend Enumerize end klass = Class.new klass.send :include, mod mod.enumerize :sex, :in => %w[male female], :default => 'male' klass.enumerized_attributes[:sex].must_be_instance_of Enumerize::Attribute klass.new.sex.must_equal 'male' klass.sex.must_be_instance_of Enumerize::Attribute end it 'validates attributes' do mod = Module.new do extend Enumerize enumerize :sex, :in => %w[male female] end klass = Class.new do include ActiveModel::Validations include mod def self.model_name ActiveModel::Name.new(self, nil, 'name') end end object = klass.new object.sex = 'wrong' object.wont_be :valid? object.errors[:sex].must_include 'is not included in the list' end end enumerize-1.1.1/test/formtastic_test.rb0000644000004100000410000000610712677055751020306 0ustar www-datawww-datarequire 'test_helper' Formtastic::FormBuilder.action_class_finder = Formtastic::ActionClassFinder Formtastic::FormBuilder.input_class_finder = Formtastic::InputClassFinder class FormtasticSpec < MiniTest::Spec include ViewTestHelper include Formtastic::Helpers::FormHelper class Thing < Struct.new(:name) extend ActiveModel::Naming include ActiveModel::Conversion def persisted? false end end class User < Struct.new(:sex, :age) extend ActiveModel::Naming include ActiveModel::Conversion extend Enumerize enumerize :sex, :in => [:male, :female] def persisted? false end end class Post < Struct.new(:category, :title) extend ActiveModel::Naming include ActiveModel::Conversion extend Enumerize enumerize :categories, :in => [:music, :games], :multiple => true def persisted? false end end before { $VERBOSE = nil } after { $VERBOSE = true } let(:user) { User.new } let(:post) { Post.new } it 'renders select with enumerized values' do concat(semantic_form_for(user) do |f| f.input :sex end) assert_select 'select option[value=male]' assert_select 'select option[value=female]' end it 'renders multiple select with enumerized values' do concat(semantic_form_for(post) do |f| f.input(:categories) end) assert_select 'select[multiple=multiple]' assert_select 'select option[value=music]' assert_select 'select option[value=games]' end it 'renders multiple select with selected enumerized value' do post.categories << :music concat(semantic_form_for(post) do |f| f.input(:categories) end) assert_select 'select[multiple=multiple]' assert_select 'select option[value=music][selected=selected]' assert_select 'select option[value=games][selected=selected]', count: 0 end it 'renders checkboxes with enumerized values' do concat(semantic_form_for(post) do |f| f.input(:categories, as: :check_boxes) end) assert_select 'select[multiple=multiple]', count: 0 assert_select 'input[type=checkbox][value=music]' assert_select 'input[type=checkbox][value=games]' end it 'renders checkboxes with selected enumerized value' do post.categories << :music concat(semantic_form_for(post) do |f| f.input(:categories, as: :check_boxes) end) assert_select 'input[type=checkbox][value=music][checked=checked]' assert_select 'input[type=checkbox][value=games][checked=checked]', count: 0 end it 'renders radio buttons with enumerized values' do concat(semantic_form_for(user) do |f| f.input :sex, :as => :radio end) assert_select 'input[type=radio][value=male]' assert_select 'input[type=radio][value=female]' end it 'does not affect not enumerized attributes' do concat(semantic_form_for(user) do |f| f.input(:age) end) assert_select 'input[type=text]' end it 'does not affect not enumerized classes' do concat(semantic_form_for(Thing.new) do |f| f.input(:name) end) assert_select 'input[type=text]' end end enumerize-1.1.1/test/predicates_test.rb0000644000004100000410000000323712677055751020257 0ustar www-datawww-datarequire 'test_helper' describe Enumerize::Predicates do let(:klass) do Class.new do extend Enumerize end end let(:object) { klass.new } it 'creates predicate methods' do klass.enumerize(:foo, in: %w(a b), predicates: true) object.must_respond_to :a? object.must_respond_to :b? end it 'creates predicate methods when enumerized values have dash in it' do klass.enumerize(:foo, in: %w(foo-bar bar-foo), predicates: true) object.must_respond_to :foo_bar? object.must_respond_to :bar_foo? end it 'creates predicate methods on multiple attribute' do klass.enumerize(:foo, in: %w(a b), predicates: true, multiple: true) object.must_respond_to :a? object.must_respond_to :b? end it 'checks values' do klass.enumerize(:foo, in: %w(a b), predicates: true) object.foo = 'a' object.a?.must_equal true object.b?.must_equal false end it 'checks values on multiple attribute' do klass.enumerize(:foo, in: %w(a b), predicates: true, multiple: true) object.foo << :a object.a?.must_equal true object.b?.must_equal false end it 'prefixes methods' do klass.enumerize(:foo, in: %w(a b), predicates: { prefix: 'bar' }) object.wont_respond_to :a? object.wont_respond_to :b? object.must_respond_to :bar_a? object.must_respond_to :bar_b? end it 'accepts only option' do klass.enumerize(:foo, in: %w(a b), predicates: { only: :a }) object.must_respond_to :a? object.wont_respond_to :b? end it 'accepts except option' do klass.enumerize(:foo, in: %w(a b), predicates: { except: :a }) object.wont_respond_to :a? object.must_respond_to :b? end end enumerize-1.1.1/test/sequel_test.rb0000644000004100000410000001675212677055751017440 0ustar www-datawww-datarequire 'test_helper' require 'sequel' require 'logger' require 'jdbc/sqlite3' if RUBY_PLATFORM == 'java' module SequelTest silence_warnings do DB = if RUBY_PLATFORM == 'java' Sequel.connect('jdbc:sqlite::memory:') else Sequel.sqlite end DB.loggers << Logger.new(nil) end DB.create_table :users do primary_key :id String :sex String :role String :lambda_role String :name String :interests String :status String :account_type, default: "basic" end DB.create_table :documents do primary_key :id String :visibility Time :created_at Time :updated_at end class Document < Sequel::Model extend Enumerize enumerize :visibility, :in => [:public, :private, :protected], :scope => true, :default => :public end module RoleEnum extend Enumerize enumerize :role, :in => [:user, :admin], :default => :user, scope: :having_role enumerize :lambda_role, :in => [:user, :admin], :default => lambda { :admin } end class User < Sequel::Model plugin :serialization, :json, :interests plugin :dirty plugin :defaults_setter plugin :validation_helpers extend Enumerize include RoleEnum enumerize :sex, :in => [:male, :female] enumerize :interests, :in => [:music, :sports, :dancing, :programming], :multiple => true enumerize :status, :in => { active: 1, blocked: 2 }, scope: true enumerize :account_type, :in => [:basic, :premium] end class UniqStatusUser < User def validate super validates_unique :status validates_presence :sex end end describe Enumerize::SequelSupport do it 'sets nil if invalid value is passed' do user = User.new user.sex = :invalid user.sex.must_equal nil end it 'saves value' do User.filter.delete user = User.new user.sex = :female user.save user.sex.must_equal 'female' end it 'loads value' do User.filter.delete User.create(:sex => :male) store_translations(:en, :enumerize => {:sex => {:male => 'Male'}}) do user = User.first user.sex.must_equal 'male' user.sex_text.must_equal 'Male' end end it 'has default value' do User.new.role.must_equal 'user' User.new.values[:role].must_equal 'user' end it 'does not set default value for not selected attributes' do User.filter.delete User.create(:sex => :male) assert_equal [:id], User.select(:id).first.values.keys end it 'has default value with lambda' do User.new.lambda_role.must_equal 'admin' User.new.values[:lambda_role].must_equal 'admin' end it 'uses after_initialize callback to set default value' do User.filter.delete User.create(sex: 'male', lambda_role: nil) user = User.where(:sex => 'male').first user.lambda_role.must_equal 'admin' end it 'uses default value from db column' do User.new.account_type.must_equal 'basic' end it 'validates inclusion' do user = User.new user.role = 'wrong' user.wont_be :valid? user.errors[:role].must_include 'is not included in the list' end it 'validates inclusion on mass assignment' do assert_raises Sequel::ValidationFailed do User.create(role: 'wrong') end end it "uses persisted value for validation if it hasn't been set" do user = User.create :sex => :male User[user.id].read_attribute_for_validation(:sex).must_equal 'male' end it 'is valid with empty string assigned' do user = User.new user.role = '' user.must_be :valid? end it 'stores nil when empty string assigned' do user = User.new user.role = '' user.values[:role].must_equal nil end it 'supports multiple attributes' do user = User.new user.interests ||= [] user.interests.must_be_empty user.interests << "music" user.interests.must_equal %w(music) user.save user = User[user.id] user.interests.must_be_instance_of Enumerize::Set user.interests.must_equal %w(music) user.interests << "sports" user.interests.must_equal %w(music sports) user.interests = [] interests = user.interests interests << "music" interests.must_equal %w(music) interests << "dancing" interests.must_equal %w(music dancing) end it 'returns invalid multiple value for validation' do user = User.new user.interests << :music user.interests << :invalid values = user.read_attribute_for_validation(:interests) values.must_equal %w(music invalid) end it 'validates multiple attributes' do user = User.new user.interests << :invalid user.wont_be :valid? user.interests = Object.new user.wont_be :valid? user.interests = ['music', ''] user.must_be :valid? end it 'stores custom values for multiple attributes' do User.filter.delete klass = Class.new(User) klass.enumerize :interests, in: { music: 0, sports: 1, dancing: 2, programming: 3}, multiple: true user = klass.new user.interests << :music user.interests.must_equal %w(music) user.save user = klass[user.id] user.interests.must_equal %w(music) end it 'adds scope' do User.filter.delete user_1 = User.create(status: :active, role: :admin) user_2 = User.create(status: :blocked) User.with_status(:active).to_a.must_equal [user_1] User.with_status(:blocked).to_a.must_equal [user_2] User.with_status(:active, :blocked).to_set.must_equal [user_1, user_2].to_set User.without_status(:active).to_a.must_equal [user_2] User.without_status(:active, :blocked).to_a.must_equal [] User.having_role(:admin).to_a.must_equal [user_1] end it 'allows either key or value as valid' do user_1 = User.new(status: :active) user_2 = User.new(status: 1) user_3 = User.new(status: '1') user_1.status.must_equal 'active' user_2.status.must_equal 'active' user_3.status.must_equal 'active' user_1.must_be :valid? user_2.must_be :valid? user_3.must_be :valid? end it 'supports defining enumerized attributes on abstract class' do Document.filter.delete document = Document.new document.visibility = :protected document.visibility.must_equal 'protected' end it 'supports defining enumerized scopes on abstract class' do Document.filter.delete document_1 = Document.create(visibility: :public) document_2 = Document.create(visibility: :private) Document.with_visibility(:public).to_a.must_equal [document_1] end it 'validates uniqueness' do user = User.create(status: :active, sex: "male") user = UniqStatusUser.new user.sex = "male" user.status = :active user.valid?.must_equal false user.errors[:status].wont_be :empty? end it "doesn't update record" do Document.filter.delete expected = Time.new(2010, 10, 10) document = Document.new document.updated_at = expected document.save document = Document.last document.save assert_equal expected, document.updated_at end it 'changes from dirty should be serialized as scalar values' do user = User.create(:status => :active) user.status = :blocked expected = { status: [1, 2] }.to_yaml assert_equal expected, user.column_changes.to_yaml end end end enumerize-1.1.1/test/set_test.rb0000644000004100000410000000610312677055751016722 0ustar www-datawww-datarequire 'test_helper' require 'yaml' describe Enumerize::Set do let(:klass) do Class.new do extend Enumerize enumerize :foo, :in => %w(a b c), :multiple => true end end let(:object) { klass.new } def build_set(values) @set = Enumerize::Set.new(object, klass.foo, values) end def set @set end def assert_called(object, method) called = false object.singleton_class.class_eval do define_method method do |*args, &block| called = true super(*args, &block) end end yield assert called, "Expected ##{method} to be called" end before do build_set %w(a) end it 'equals to other set' do set.must_equal Enumerize::Set.new(nil, klass.foo, %w(a)) end it 'equals to array' do set.must_equal %w(a) end it 'equals to array of symbols' do set.must_equal [:a] end it 'has unique values' do set << :a set.must_equal %w(a) end it 'equals to array with different value order' do set << :b set.must_equal %w(b a) end it "isn't equal to a part of values" do set << :b set.wont_equal %w(a) end describe '#push' do it 'appends values' do set.push :b set.must_include :b end it 'reassigns attribute' do assert_called object, :foo= do set.push :b end end end describe '#delete' do it 'deletes value' do set.delete :a set.wont_include :a end it 'reassigns attribute' do assert_called object, :foo= do set.delete :a end end end describe '#inspect' do it 'returns custom string' do set << :b set.inspect.must_equal '#' end end describe '#to_ary' do it 'returns array' do set.to_ary.must_be_instance_of Array end end describe '#texts' do it 'returns array of text values' do set.texts.must_equal ['A'] end end describe '#join' do it 'joins values' do set << :b set.join(', ').must_equal 'a, b' end end describe 'boolean methods comparison' do it 'returns true if value equals method' do set << :a set.a?.must_equal true end it 'returns false if value does not equal method' do set << :a set.b?.must_equal false end it 'raises NoMethodError if there are no values like boolean method' do proc { set.some_method? }.must_raise NoMethodError end it 'raises ArgumentError if arguments are passed' do proc { set.a?('<3') }.must_raise ArgumentError end it 'responds to methods for existing values' do set.must_respond_to :a? set.must_respond_to :b? set.must_respond_to :c? end it 'returns a method object' do set.method(:a?).must_be_instance_of Method end it 'does not respond to a method for not existing value' do set.wont_respond_to :some_method? end end describe 'serialization' do it 'is serialized to yaml as array' do set << :a assert_equal YAML.dump(%w(a)), YAML.dump(set) end end end enumerize-1.1.1/test/test_helper.rb0000644000004100000410000000163112677055751017407 0ustar www-datawww-datarequire 'minitest/autorun' require 'minitest/spec' require 'active_support/core_ext/kernel/reporting' require 'active_model' require 'rails' begin require 'mongoid' rescue LoadError end module RailsAdmin end require 'simple_form' SimpleForm.setup {} require 'formtastic' module EnumerizeTest class Application < Rails::Application config.active_support.deprecation = :stderr config.active_support.test_order = :random config.eager_load = false config.secret_key_base = 'secret' end end EnumerizeTest::Application.initialize! $VERBOSE=true require 'enumerize' Dir["#{File.dirname(__FILE__)}/support/*.rb"].each do |file| require file end module MiscHelpers def store_translations(locale, translations, &block) begin I18n.backend.store_translations locale, translations yield ensure I18n.reload! end end end class MiniTest::Spec include MiscHelpers end enumerize-1.1.1/test/mongoid_test.rb0000644000004100000410000000616012677055751017566 0ustar www-datawww-datarequire 'test_helper' begin silence_warnings do require 'mongoid' end Mongoid.configure do |config| config.connect_to('enumerize-test-suite') config.options = { use_utc: true, include_root_in_json: true } end describe Enumerize do class MongoidUser include Mongoid::Document extend Enumerize field :sex field :role enumerize :sex, :in => %w[male female], scope: true enumerize :status, :in => %w[notice warning error], scope: true enumerize :role, :in => %w[admin user], :default => 'user', scope: :having_role enumerize :mult, :in => %w[one two three four], :multiple => true end before { $VERBOSE = nil } after { $VERBOSE = true } let(:model) { MongoidUser } it 'sets nil if invalid value is passed' do user = model.new user.sex = :invalid user.sex.must_equal nil end it 'saves value' do model.delete_all user = model.new user.sex = :female user.save! user.sex.must_equal 'female' end it 'loads value' do model.delete_all model.create!(:sex => :male) store_translations(:en, :enumerize => {:sex => {:male => 'Male'}}) do user = model.first user.sex.must_equal 'male' user.sex_text.must_equal 'Male' end end it 'has default value' do model.new.role.must_equal 'user' end it 'uses after_initialize callback to set default value' do model.delete_all model.create!(sex: 'male', role: nil) user = model.where(sex: 'male').first user.role.must_equal 'user' end it 'validates inclusion' do user = model.new user.role = 'wrong' user.wont_be :valid? end it 'assigns value on loaded record' do model.delete_all model.create!(:sex => :male) user = model.first user.sex = :female user.sex.must_equal 'female' end it 'loads multiple properly' do model.delete_all model.create!(:mult => ['one', 'two']) user = model.first user.mult.to_a.must_equal ['one', 'two'] end it 'adds scope' do model.delete_all user_1 = model.create!(sex: :male, role: :admin) user_2 = model.create!(sex: :female, role: :user) model.with_sex(:male).to_a.must_equal [user_1] model.with_sex(:female).to_a.must_equal [user_2] model.with_sex(:male, :female).to_set.must_equal [user_1, user_2].to_set model.without_sex(:male).to_a.must_equal [user_2] model.without_sex(:female).to_a.must_equal [user_1] model.without_sex(:male, :female).to_a.must_equal [] model.having_role(:admin).to_a.must_equal [user_1] model.having_role(:user).to_a.must_equal [user_2] end it 'chains scopes' do model.delete_all user_1 = model.create!(status: :notice) user_2 = model.create!(status: :warning) user_3 = model.create!(status: :error) model.with_status(:notice, :warning).with_status(:notice, :error).to_a.must_equal [user_1] model.with_status(:notice, :warning).union.with_status(:notice, :error).to_a.must_equal [user_1, user_2, user_3] end it 'ignores not enumerized values that passed to the scope method' do model.delete_all model.with_sex(:foo).must_equal [] end end rescue LoadError # Skip end enumerize-1.1.1/test/base_test.rb0000644000004100000410000001225612677055751017047 0ustar www-datawww-datarequire 'test_helper' describe Enumerize::Base do let(:klass) do Class.new do extend Enumerize end end let(:subklass) do Class.new(klass) end let(:object) { klass.new } it 'returns nil when not set' do klass.enumerize(:foo, :in => [:a, :b]) object.foo.must_equal nil end it 'returns value that was set' do klass.enumerize(:foo, :in => [:a, :b]) object.foo = :a object.foo.must_equal 'a' end it 'returns translation' do store_translations(:en, :enumerize => {:foo => {:a => 'a text'}}) do klass.enumerize(:foo, :in => [:a, :b]) object.foo = :a object.foo.text.must_equal 'a text' object.foo_text.must_equal 'a text' object.foo_text.must_equal 'a text' end end it 'returns nil as translation when value is nil' do store_translations(:en, :enumerize => {:foo => {:a => 'a text'}}) do klass.enumerize(:foo, :in => [:a, :b]) object.foo_text.must_equal nil end end it 'scopes translation by i18 key' do def klass.model_name name = "ExampleClass" def name.i18n_key 'example_class' end name end store_translations(:en, :enumerize => {:example_class => {:foo => {:a => 'a text scoped'}}}) do klass.enumerize(:foo, :in => [:a, :b]) object.foo = :a object.foo.text.must_equal 'a text scoped' object.foo_text.must_equal 'a text scoped' end end it 'returns humanized value if there are no translations' do store_translations(:en, :enumerize => {}) do klass.enumerize(:foo, :in => [:a, :b]) object.foo = :a object.foo_text.must_equal 'A' end end it 'stores value as string' do klass.enumerize(:foo, :in => [:a, :b]) object.foo = :a object.instance_variable_get(:@foo).must_be_instance_of String end it 'handles default value' do klass.enumerize(:foo, :in => [:a, :b], :default => :b) object.foo.must_equal 'b' end it 'handles default value with lambda' do klass.enumerize(:foo, :in => [:a, :b], :default => lambda { :b }) object.foo.must_equal 'b' end it 'injects object instance into lamda default value' do klass.enumerize(:foo, :in => [:a, :b], :default => lambda { |obj| :b if obj.is_a? klass }) object.foo.must_equal 'b' end it 'raises exception on invalid default value' do proc { klass.enumerize(:foo, :in => [:a, :b], :default => :c) }.must_raise ArgumentError end it 'has enumerized attributes' do klass.enumerized_attributes.must_be_empty klass.enumerize(:foo, :in => %w[a b]) klass.enumerized_attributes[:foo].must_be_instance_of Enumerize::Attribute end it "doesn't override existing method" do method = klass.method(:name) klass.enumerize(:name, :in => %w[a b], :default => 'a') klass.method(:name).must_equal method end it "inherits enumerized attributes from a parent class" do klass.enumerize(:foo, :in => %w[a b]) subklass.enumerized_attributes[:foo].must_be_instance_of Enumerize::Attribute end it "inherits enumerized attributes from a grandparent class" do klass.enumerize(:foo, :in => %w[a b]) Class.new(subklass).enumerized_attributes[:foo].must_be_instance_of Enumerize::Attribute end it "doesn't add enumerized attributes to parent class" do klass.enumerize(:foo, :in => %w[a b]) subklass.enumerize(:bar, :in => %w[c d]) klass.enumerized_attributes[:bar].must_equal nil end it 'adds new parent class attributes to subclass' do subklass = Class.new(klass) klass.enumerize :foo, :in => %w[a b] subklass.enumerized_attributes[:foo].must_be_instance_of Enumerize::Attribute end it 'stores nil value' do klass.enumerize(:foo, :in => [:a, :b]) object.foo = nil object.instance_variable_get(:@foo).must_equal nil end it 'casts value to string for validation' do klass.enumerize(:foo, :in => [:a, :b]) object.foo = :c object.read_attribute_for_validation(:foo).must_equal 'c' end it "doesn't cast nil to string for validation" do klass.enumerize(:foo, :in => [:a, :b]) object.foo = nil object.read_attribute_for_validation(:foo).must_equal nil end it 'calls super in the accessor method' do accessors = Module.new do def attributes @attributes ||= {} end def foo attributes[:foo] end def foo=(v) attributes[:foo] = v end end klass = Class.new do include accessors extend Enumerize enumerize :foo, :in => %w[test] end object = klass.new object.foo.must_be_nil object.attributes.must_equal({:foo => nil}) object.foo = 'test' object.foo.must_equal 'test' object.attributes.must_equal(:foo => 'test') end it 'stores hash values' do klass.enumerize(:foo, :in => {:a => 1, :b => 2}) object.foo = :a object.instance_variable_get(:@foo).must_equal 1 object.foo.must_equal 'a' object.foo = :b object.instance_variable_get(:@foo).must_equal 2 object.foo.must_equal 'b' end it 'returns custom value' do klass.enumerize(:foo, :in => {:a => 1, :b => 2}) object.foo = :a object.foo_value.must_equal 1 object.foo = :b object.foo_value.must_equal 2 end end enumerize-1.1.1/test/activerecord_test.rb0000644000004100000410000002145212677055751020605 0ustar www-datawww-datarequire 'test_helper' require 'active_record' require 'logger' silence_warnings do ActiveRecord::Migration.verbose = false ActiveRecord::Base.logger = Logger.new(nil) ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") end ActiveRecord::Base.connection.instance_eval do create_table :users do |t| t.string :sex t.string :role t.string :lambda_role t.string :name t.string :interests t.integer :status t.string :account_type, :default => :basic end create_table :documents do |t| t.string :visibility t.timestamps null: true end end class BaseEntity < ActiveRecord::Base self.abstract_class = true extend Enumerize enumerize :visibility, :in => [:public, :private, :protected], :scope => true, :default => :public end class Document < BaseEntity end module RoleEnum extend Enumerize enumerize :role, :in => [:user, :admin], :default => :user, scope: :having_role enumerize :lambda_role, :in => [:user, :admin], :default => lambda { :admin } end class User < ActiveRecord::Base extend Enumerize include RoleEnum enumerize :sex, :in => [:male, :female] serialize :interests, Array enumerize :interests, :in => [:music, :sports, :dancing, :programming], :multiple => true enumerize :status, :in => { active: 1, blocked: 2 }, scope: true enumerize :account_type, :in => [:basic, :premium] end class UniqStatusUser < User validates :status, uniqueness: true validates :sex, presence: true end describe Enumerize::ActiveRecordSupport do it 'sets nil if invalid value is passed' do user = User.new user.sex = :invalid user.sex.must_equal nil end it 'saves value' do User.delete_all user = User.new user.sex = :female user.save! user.sex.must_equal 'female' end it 'loads value' do User.delete_all User.create!(:sex => :male) store_translations(:en, :enumerize => {:sex => {:male => 'Male'}}) do user = User.first user.sex.must_equal 'male' user.sex_text.must_equal 'Male' end end it 'has default value' do User.new.role.must_equal 'user' User.new.attributes['role'].must_equal 'user' end it 'does not set default value for not selected attributes' do User.delete_all User.create!(:sex => :male) assert_equal ['id'], User.select(:id).first.attributes.keys end it 'has default value with lambda' do User.new.lambda_role.must_equal 'admin' User.new.attributes['lambda_role'].must_equal 'admin' end it 'uses after_initialize callback to set default value' do User.delete_all User.create!(sex: 'male', lambda_role: nil) user = User.where(:sex => 'male').first user.lambda_role.must_equal 'admin' end it 'uses default value from db column' do User.new.account_type.must_equal 'basic' end it 'has default value with default scope' do UserWithDefaultScope = Class.new(User) do default_scope -> { having_role(:user) } end UserWithDefaultScope.new.role.must_equal 'user' UserWithDefaultScope.new.attributes['role'].must_equal 'user' end it 'validates inclusion' do user = User.new user.role = 'wrong' user.wont_be :valid? user.errors[:role].must_include 'is not included in the list' end it 'validates inclusion when using write_attribute with string attribute' do user = User.new user.send(:write_attribute, 'role', 'wrong') user.read_attribute_for_validation(:role).must_equal 'wrong' user.wont_be :valid? user.errors[:role].must_include 'is not included in the list' end it 'validates inclusion when using write_attribute with symbol attribute' do user = User.new user.send(:write_attribute, :role, 'wrong') user.read_attribute_for_validation(:role).must_equal 'wrong' user.wont_be :valid? user.errors[:role].must_include 'is not included in the list' end it 'validates inclusion on mass assignment' do assert_raises ActiveRecord::RecordInvalid do User.create!(role: 'wrong') end end it "uses persisted value for validation if it hasn't been set" do user = User.create! :sex => :male User.find(user.id).read_attribute_for_validation(:sex).must_equal 'male' end it 'is valid with empty string assigned' do user = User.new user.role = '' user.must_be :valid? end it 'stores nil when empty string assigned' do user = User.new user.role = '' user.read_attribute(:role).must_equal nil end it 'supports multiple attributes' do user = User.new user.interests.must_be_empty user.interests << :music user.interests.must_equal %w(music) user.save! user = User.find(user.id) user.interests.must_be_instance_of Enumerize::Set user.interests.must_equal %w(music) user.interests << :sports user.interests.must_equal %w(music sports) user.interests = [] interests = user.interests interests << :music interests.must_equal %w(music) interests << :dancing interests.must_equal %w(music dancing) end it 'stores multiple value passed passed to new' do user = User.new(interests: [:music, :dancing]) user.save! user.interests.must_equal %w(music dancing) User.find(user.id).interests.must_equal %w(music dancing) end it 'returns invalid multiple value for validation' do user = User.new user.interests << :music user.interests << :invalid values = user.read_attribute_for_validation(:interests) values.must_equal %w(music invalid) end it 'validates multiple attributes' do user = User.new user.interests << :invalid user.wont_be :valid? user.interests = Object.new user.wont_be :valid? user.interests = ['music', ''] user.must_be :valid? end it 'stores custom values for multiple attributes' do User.delete_all klass = Class.new(User) klass.enumerize :interests, in: { music: 0, sports: 1, dancing: 2, programming: 3}, multiple: true user = klass.new user.interests << :music user.read_attribute(:interests).must_equal [0] user.interests.must_equal %w(music) user.save user = klass.find(user.id) user.interests.must_equal %w(music) end it 'adds scope' do User.delete_all user_1 = User.create!(status: :active, role: :admin) user_2 = User.create!(status: :blocked) User.with_status(:active).must_equal [user_1] User.with_status(:blocked).must_equal [user_2] User.with_status(:active, :blocked).to_set.must_equal [user_1, user_2].to_set User.without_status(:active).must_equal [user_2] User.without_status(:active, :blocked).must_equal [] User.having_role(:admin).must_equal [user_1] end it 'ignores not enumerized values that passed to the scope method' do User.delete_all User.with_status(:foo).must_equal [] end it 'allows either key or value as valid' do user_1 = User.new(status: :active) user_2 = User.new(status: 1) user_3 = User.new(status: '1') user_1.status.must_equal 'active' user_2.status.must_equal 'active' user_3.status.must_equal 'active' user_1.must_be :valid? user_2.must_be :valid? user_3.must_be :valid? end it 'supports defining enumerized attributes on abstract class' do Document.delete_all document = Document.new document.visibility = :protected document.visibility.must_equal 'protected' end it 'supports defining enumerized scopes on abstract class' do Document.delete_all document_1 = Document.create!(visibility: :public) document_2 = Document.create!(visibility: :private) Document.with_visibility(:public).must_equal [document_1] end it 'validates uniqueness' do user = User.new user.status = :active user.save! user = UniqStatusUser.new user.status = :active user.valid? user.errors[:status].wont_be :empty? end it 'is valid after #becomes' do User.delete_all user = User.new user.sex = :male user.save! uniq_user = User.find(user.id).becomes(UniqStatusUser) uniq_user.valid? uniq_user.errors.must_be_empty end it 'supports multiple attributes in #becomes' do User.delete_all uniq_user = UniqStatusUser.new uniq_user.interests = [:sports, :dancing] uniq_user.sex = :male uniq_user.save! user = uniq_user.becomes(User) user.sex.must_equal uniq_user.sex user.interests.must_equal uniq_user.interests end it "doesn't update record" do Document.delete_all expected = Time.utc(2010, 10, 10) document = Document.new document.updated_at = expected document.save! document = Document.last document.save! assert_equal expected, document.updated_at end it 'changes from dirty should be serialized as scalar values' do user = User.create(:status => :active) user.status = :blocked assert_equal [1, 2], YAML.load(user.changes.to_yaml)[:status] end end enumerize-1.1.1/test/value_test.rb0000644000004100000410000000775012677055751017254 0ustar www-datawww-datarequire 'test_helper' require 'yaml' describe Enumerize::Value do class Attr < Struct.new(:values) end let(:attr) { Attr.new([]) } let(:val) { Enumerize::Value.new(attr, 'test_value', 1) } it 'is a string' do val.must_be_kind_of String end describe 'equality' do it 'is compared to string' do val.must_be :==, 'test_value' val.wont_be :==, 'not_value' end it 'is compared to symbol' do val.must_be :==, :test_value val.wont_be :==, :not_value end it 'is compared to integer' do val.must_be :==, 1 val.wont_be :==, 2 end end describe 'translation' do let(:attr) { Struct.new(:values, :name, :i18n_scopes).new([], "attribute_name", []) } it 'uses common translation' do store_translations(:en, :enumerize => {:attribute_name => {:test_value => "Common translation"}}) do val.text.must_be :==, "Common translation" end end it 'uses default translation from the "default" section if its present' do store_translations(:en, :enumerize => {:defaults => {:attribute_name => {:test_value => "Common translation"}}}) do val.text.must_be :==, "Common translation" end end it 'uses model specific translation' do attr.i18n_scopes = ["enumerize.model_name.attribute_name"] store_translations(:en, :enumerize => {:model_name => {:attribute_name => {:test_value => "Model Specific translation"}}}) do val.text.must_be :==, "Model Specific translation" end end it 'uses model specific translation rather than common translation' do attr.i18n_scopes = ["enumerize.model_name.attribute_name"] store_translations(:en, :enumerize => {:attribute_name => {:test_value => "Common translation"}, :model_name => {:attribute_name => {:test_value => "Model Specific translation"}}}) do val.text.must_be :==, "Model Specific translation" end end it 'uses simply humanized value when translation is undefined' do store_translations(:en, :enumerize => {}) do val.text.must_be :==, "Test value" end end it 'uses specified in options translation scope' do attr.i18n_scopes = ["other.scope"] store_translations(:en, :other => {:scope => {:test_value => "Scope specific translation"}}) do val.text.must_be :==, "Scope specific translation" end end it 'uses first found translation scope from options' do attr.i18n_scopes = ["nonexistent.scope", "other.scope"] store_translations(:en, :other => {:scope => {:test_value => "Scope specific translation"}}) do val.text.must_be :==, "Scope specific translation" end end end describe 'boolean methods comparison' do before do attr.values = [val, Enumerize::Value.new(attr, 'other_value')] end it 'returns true if value equals method' do val.test_value?.must_equal true end it 'returns false if value does not equal method' do val.other_value?.must_equal false end it 'raises NoMethodError if there are no values like boolean method' do proc { val.some_method? }.must_raise NoMethodError end it 'raises ArgumentError if arguments are passed' do proc { val.other_value?('<3') }.must_raise ArgumentError end it 'responds to methods for existing values' do val.must_respond_to :test_value? val.must_respond_to :other_value? end it 'returns a method object' do val.method(:test_value?).must_be_instance_of Method end it "doesn't respond to a method for not existing value" do val.wont_respond_to :some_method? end end describe 'serialization' do let(:val) { Enumerize::Value.new(attr, 'test_value') } it 'should be serialized to yaml as string value' do assert_equal YAML.dump('test_value'), YAML.dump(val) end it 'serializes with Marshal' do dump_value = Marshal.dump(val) Marshal.load(dump_value).must_equal 'test_value' end end end enumerize-1.1.1/test/multiple_test.rb0000644000004100000410000000262712677055751017771 0ustar www-datawww-datarequire 'test_helper' describe Enumerize::Base do let(:klass) do Class.new do extend Enumerize end end let(:subklass) do Class.new(klass) end let(:object) { klass.new } it 'returns [] when not set' do klass.enumerize :foos, in: %w(a b), multiple: true object.foos.must_equal [] end it 'returns setted array' do klass.enumerize :foos, in: %w(a b c), multiple: true object.foos = %w(a c) object.foos.must_equal %w(a c) end it 'sets default value as single value' do klass.enumerize :foos, in: %w(a b c), default: 'b', multiple: true object.foos.must_equal %w(b) end it 'sets default value as array of one element' do klass.enumerize :foos, in: %w(a b c), default: %w(b), multiple: true object.foos.must_equal %w(b) end it 'sets default value as array of several elements' do klass.enumerize :foos, in: %w(a b c), default: %w(b c), multiple: true object.foos.must_equal %w(b c) end it "doesn't define _text method" do klass.enumerize :foos, in: %w(a b c), multiple: true object.wont_respond_to :foos_text end it "doesn't define _value method" do klass.enumerize :foos, in: %w(a b c), multiple: true object.wont_respond_to :foos_value end it "cannot define multiple with scope" do assert_raises ArgumentError do klass.enumerize :foos, in: %w(a b c), multiple: true, scope: true end end end enumerize-1.1.1/test/support/0000755000004100000410000000000012677055751016257 5ustar www-datawww-dataenumerize-1.1.1/test/support/view_test_helper.rb0000644000004100000410000000126612677055751022161 0ustar www-datawww-datarequire 'active_support/concern' require 'active_support/testing/setup_and_teardown' if defined?(ActionView::RoutingUrlFor) ActionView::RoutingUrlFor.send(:include, ActionDispatch::Routing::UrlFor) end module ViewTestHelper extend ActiveSupport::Concern include ActiveSupport::Testing::SetupAndTeardown include ActionView::TestCase::Behavior included do setup :set_controller end def set_controller @controller = MockController.new end def method_missing(method, *args) super unless method.to_s =~ /_path$/ end def respond_to?(method, include_private=false) method.to_s =~ /_path$/ || super end def protect_against_forgery? false end end enumerize-1.1.1/test/support/mock_controller.rb0000644000004100000410000000047012677055751022001 0ustar www-datawww-dataclass MockController attr_writer :action_name def _routes self end def action_name defined?(@action_name) ? @action_name : "edit" end def url_for(*args) "http://example.com" end def url_helpers self end def url_options {} end def hash_for_users_path(*); end end enumerize-1.1.1/test/attribute_test.rb0000644000004100000410000000743612677055751020144 0ustar www-datawww-datarequire 'test_helper' describe Enumerize::Attribute do def attr @attr ||= nil end def build_attr(*args, &block) @attr = Enumerize::Attribute.new(*args, &block) end it 'returns values' do build_attr nil, :foo, :in => [:a, :b] attr.values.must_equal %w[a b] end it 'converts name to symbol' do build_attr nil, 'foo', :in => %w[a b] attr.name.must_equal :foo end it 'uses custom value class' do value_class = Class.new(Enumerize::Value) build_attr nil, 'foo', :in => %w[a b], :value_class => value_class attr.values.first.must_be_instance_of value_class end describe 'i18n scopes' do it 'returns scopes from options' do build_attr nil, 'foo', :in => %w[a b], :i18n_scope => %w[bar buzz] attr.i18n_scopes.must_equal %w[bar buzz] end it 'accepts only string scopes' do proc { build_attr nil, 'foo', :in => %w[a b], :i18n_scope => [%w[bar buzz], "bar.buzz"] }.must_raise ArgumentError end end describe 'options for select' do it 'returns all options for select' do store_translations(:en, :enumerize => {:foo => {:a => 'a text', :b => 'b text'}}) do build_attr nil, :foo, :in => %w[a b] attr.options.must_equal [['a text', 'a'], ['b text', 'b']] end end it 'returns requested options for select via :only' do store_translations(:en, :enumerize => {:foo => {:a => 'a text', :b => 'b text'}}) do build_attr nil, :foo, :in => %w[a b] attr.options(:only => :a).must_equal [['a text', 'a']] attr.options(:only => [:b]).must_equal [['b text', 'b']] attr.options(:only => []).must_equal [] end end it 'returns requested options for select via :except' do store_translations(:en, :enumerize => {:foo => {:a => 'a text', :b => 'b text'}}) do build_attr nil, :foo, :in => %w[a b] attr.options(:except => :a).must_equal [['b text', 'b']] attr.options(:except => :b).must_equal [['a text', 'a']] attr.options(:except => []).must_equal [['a text', 'a'], ['b text', 'b']] end end it 'does not work with both :only and :except' do store_translations(:en, :enumerize => {:foo => {:a => 'a text', :b => 'b text'}}) do build_attr nil, :foo, :in => %w[a b] proc { attr.options(:except => [], :only => []) }.must_raise ArgumentError end end end describe 'values hash' do before do build_attr nil, :foo, :in => {:a => 1, :b => 2} end it 'returns hash keys as values' do attr.values.must_equal %w[a b] end it 'finds values by hash values' do attr.find_value(1).must_equal 'a' attr.find_value(2).must_equal 'b' end end it 'sets up shortcut methods for each value' do build_attr nil, :foo, :in => {:a => 1, :b => 2} attr.must_respond_to :a attr.must_respond_to :b attr.a.value.must_equal 1 attr.b.value.must_equal 2 attr.a.text.must_equal 'A' attr.b.text.must_equal 'B' end describe 'values hash with zero' do before do build_attr nil, :foo, :in => {:a => 1, :b => 2, :c => 0} end it 'returns hash keys as values' do attr.values.must_equal %w[a b c] end it 'finds values by hash values' do attr.find_value(1).must_equal 'a' attr.find_value(2).must_equal 'b' attr.find_value(0).must_equal 'c' end it 'finds all values by hash values' do attr.find_values(1, 2, 0).must_equal ['a', 'b', 'c'] end end describe 'boolean values hash' do before do build_attr nil, :foo, :in => {:a => true, :b => false} end it 'returns hash keys as values' do attr.values.must_equal %w[a b] end it 'finds values by hash values' do attr.find_value(true).must_equal 'a' attr.find_value(false).must_equal 'b' end end end enumerize-1.1.1/.gitignore0000644000004100000410000000035212677055751015554 0ustar www-datawww-data*.gem *.rbc .bundle .config .ruby-version .yardoc .idea/ enumerize.iml Gemfile*.lock gemfiles/Gemfile-*.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man log/* pkg rdoc spec/reports test/tmp test/version_tmp tmp vendor/bundle enumerize-1.1.1/Gemfile.mongo_mapper0000644000004100000410000000016712677055751017545 0ustar www-datawww-dataeval_gemfile('Gemfile.global') gem 'minitest', '~> 5.8' gem 'rails', '4.2.4', :require => false gem 'mongo_mapper' enumerize-1.1.1/CHANGELOG.md0000644000004100000410000002171212677055751015400 0ustar www-datawww-data## master ### enhancements ### bug fix ## 1.1.1 (January 25, 2016) ### bug fix * Fix exception when using predicate methods and enumerized values have dash in it. (by [@nashby](https://github.com/nashby)) ## 1.1.0 (November 15, 2015) ### enhancements * Add Sequel support. (by [@mrbrdo](https://github.com/mrbrdo)) * Add qualifiers to RSpec matcher. (by [@maurogeorge](https://github.com/maurogeorge)) * Support hash in the RSpec matcher. (by [@maurogeorge](https://github.com/maurogeorge)) ### bug fix ## 1.0.0 (August 2, 2015) ### enhancements * Add `texts` method for getting an array of text values of the enumerized field with multiple type. (by [@huynhquancam](https://github.com/huynhquancam)) * Drop Rails 3.2 support. (by [@nashby](https://github.com/nashby)) ### bug fix * Fix conflicts when Active Record and Mongoid are used at the same time. (by [@matsu911](https://github.com/matsu911)) ## 0.11.0 (March 29, 2015) ## ### enhancements * Add ability to set default value for enumerized field with multiple type. (by [@nashby](https://github.com/nashby)) * Support Rails 4.2. (by [@lest](https://github.com/lest)) ### bug fix * Use Mongoid's `:in` method for generated scopes, fix chained scopes. (by [@nashby](https://github.com/nashby)) * Use `after_initialize` callback to set default value in Mongoid documents. (by [@nashby](https://github.com/nashby)) ## 0.10.1 (March 4, 2015) ## ### bug fix * Use method_missing instead of defining singleton class methods to allow Marshal serialization (by [@lest](https://github.com/lest)) ## 0.10.0 (February 17, 2015) ## ### enhancements * Add scopes support to mongoid documents (by [@nashby](https://github.com/nashby)) * Use underscore.humanize in #text to make use of Inflector acronyms (by [@mintuhouse](https://github.com/mintuhouse)) * Raise an exception when :scope option is used together with :multiple option (by [@maurogeorge](https://github.com/maurogeorge)) * Use alias_method_chain instead of overriding Class#inherited (by [@yuroyoro](https://github.com/yuroyoro)) * Shortcut methods to retrieve enumerize values (by [@CyborgMaster](https://github.com/CyborgMaster)) * Extend equality operator to support comparing with symbols and custom values (e.g. integers) (by [@CyborgMaster](https://github.com/CyborgMaster)) ## 0.9.0 (December 11, 2014) ## ### enhancements * Add :value_class option (by [@lest](https://github.com/lest)) * Use 'defaults' scope in the localization file for the attributes that used across several models. This will help to avoid conflicting keys with model names and attribute names. Example: ```yml en: enumerize: defaults: sex: male: Male female: Female ``` You still can use the old solution without "default" scope: ```yml en: enumerize: sex: male: Male female: Female ``` (by [@nashby](https://github.com/nashby)) ### bug fix * Store values for validation using string keys (by [@nagyt234](https://github.com/nagyt234)) * Store custom values for multiple attributes (by [@lest](https://github.com/lest)) * Support validations after using AR#becomes (by [@lest](https://github.com/lest)) * Do not try to set attribute for not selected attributes (by [@dany1468](https://github.com/dany1468)) ## 0.8.0 (March 4, 2014) ## ### enhancements * Integration with SimpleForm's `input_field` (by [@nashby](https://github.com/nashby)) * Support multiple attributes in Active Record #becomes method (by [@lest](https://github.com/lest)) * Add ability to specify localization scope with `i18n_scope` option (by [@dreamfall](https://github.com/dreamfall)) ### bug fix * Fix Rails Admin integration when custom values are used (by [@brenes](https://github.com/brenes)) * Fix RSpec integration using enumerize with Spring (by [@winston](https://github.com/winston)) * Return proper RSpec failure message for enumerized attribute with default value (by [@nashby](https://github.com/nashby)) * Return proper RSpec description for enumerized attribute without default value (by [@andreygerasimchuk](https://github.com/andreygerasimchuk)) * Do not try to set default value for not selected attributes (by [@nashby](https://github.com/nashby)) * Fix uniqueness validation with Active Record (by [@lest](https://github.com/lest)) * Fix loading of attributes with multiple: true in mongoid (by [glebtv](https://github.com/glebtv)) * Serialize value as scalar type (by [@ka8725](https://github.com/ka8725)) ## 0.7.0 (August 21, 2013) ## ### enhancements * Give priority to model specific translation definition. See example [here](https://github.com/brainspec/enumerize/pull/96) (by [@labocho](https://github.com/labocho)) * Allow lambda in default value (by [@adie](https://github.com/adie)) * Add predicate methods to the multiple attributes (by [@nashby](https://github.com/nashby)) * Add RSpec matcher (by [@nashby](https://github.com/nashby)) * Add `*_value` method that returns actual value of the enumerized attribute (useful for attributes with custom values) (by [@tkyowa](https://github.com/tkyowa)) ### bug fix * Make validation work when `write_attribute` is using for setting enumerized values (by [@nashby](https://github.com/nashby)) * Validates enumerized values when enumeration is included via module (by [@nashby](https://github.com/nashby)) and (by [@lest](https://github.com/lest)) ## 0.6.1 (May 20, 2013) ## ### bug fix * Don't raise error when enumerized attribute is already defined. (by [@lest](https://github.com/lest)) ## 0.6.0 (May 16, 2013) ## ### enhancements * Use inclusion error message for invalid values (by [@lest](https://github.com/lest)) * Add `:only` and `except` options to the `Attribute#options` method. (by [@thehappycoder](https://github.com/thehappycoder) and [@randoum](https://github.com/randoum)) * ActiveRecord scopes. (by [@lest](https://github.com/lest), [@banyan](https://github.com/banyan) and [@nashby](https://github.com/nashby)) * Support for RailsAdmin (by [@drewda](https://github.com/drewda)) ### bug fix * Return correct default value for enumerized attribute using `default_scope` with generated scope [@nashby](https://github.com/nashby) * Allow either key or value as valid (by [aghull](https://github.com/aghull) and [@lest](https://github.com/lest)) * Use default enum value from db column (by [@lest](https://github.com/lest)) ## 0.5.1 (December 10, 2012) ## ### bug fix * Always return Enumerize::Set for multiple attributes (by [@nashby](https://github.com/nashby)) ## 0.5.0 (October 31, 2012) ## The previous method of adding enumerize to a class was deprecated. Please use `extend Enumerize` instead of `include Enumerize`. ### enhancements * SimpleForm support for multiple attributes. (by [@nashby](https://github.com/nashby)) * Formtastic support for multiple attributes. (by [@nashby](https://github.com/nashby)) * Array-like multiple attributes. (by [@lest](https://github.com/lest)) ## 0.4.0 (September 6, 2012) ## Legacy support was dropped. The following versions are supported: * Ruby 1.9.3+ (including JRuby and Rubinius) * Rails 3.2+ * Formtastic 2.2+ * SimpleForm 2+ * Mongoid 3+ ### enhancements * Ability to define predicate methods on enumerized object. (by [@lest](https://github.com/lest)) ## 0.3.0 (July 9, 2012) ## ### enhancements * Accept a values hash to store an attribute using custom values (e.g. integers) (by [@lest](https://github.com/lest)) ## 0.2.2 (May 22, 2012) ## ### bug fix * Correctly assign default value to handle mass assignment in Active Record (by [@lest](https://github.com/lest)) ## 0.2.1 (May 21, 2012) ## ### bug fix * Call super in attribute accessors if available (by [@lest](https://github.com/lest)) ## 0.2.0 (March 29, 2012) ## ### enhancements * Ability to enumerize attributes in a module and then include it into classes (by [@lest](https://github.com/lest)) * Add error to a model when attribute value is not included in allowed list (by [@lest](https://github.com/lest)) ### bug fix * Inheriting enumerized attributes (by [@cgunther](https://github.com/cgunther) and [@nashby](https://github.com/nashby)) * Don't cast nil to string (by [@jimryan](https://github.com/jimryan)) ## 0.1.1 (March 6, 2012) ## ### bug fix * I18n regression: Multiple calls to value #text return different results (by [@cgunther](https://github.com/cgunther) and [@lest](https://github.com/lest)) ## 0.1.0 (March 5, 2012) ## ### enhancements * Return humanized value if there are no translations (by [@nashby](https://github.com/nashby)) * Integration with SimpleForm (by [@nashby](https://github.com/nashby)) * Integration with Formtastic (by [@lest](https://github.com/lest)) ## 0.0.4 (February 8, 2012) ## ### bug fix * Make attribute accessors to work with ActiveRecord 3.1.x (by [@lest](https://github.com/lest)) ## 0.0.3 (February 8, 2012) ## ### enhancements * Mongoid support (by [@lest](https://github.com/lest)) * Boolean methods (by [@Dreamfa11](https://github.com/Dreamfa11)) enumerize-1.1.1/README.md0000644000004100000410000002242212677055751015045 0ustar www-datawww-data# Enumerize [![TravisCI](https://secure.travis-ci.org/brainspec/enumerize.png?branch=master)](http://travis-ci.org/brainspec/enumerize) [![Gemnasium](https://gemnasium.com/brainspec/enumerize.png)](https://gemnasium.com/brainspec/enumerize) Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper/Sequel support ## Installation Add this line to your application's Gemfile: gem 'enumerize' And then execute: $ bundle Or install it yourself as: $ gem install enumerize ## Usage Basic: ```ruby class User extend Enumerize enumerize :sex, in: [:male, :female] end ``` Note that enumerized values are just identificators so if you want to use multi-word, etc. values you should use `I18n` feature. ActiveRecord: ```ruby class CreateUsers < ActiveRecord::Migration def change create_table :users do |t| t.string :sex t.string :role t.timestamps end end end class User < ActiveRecord::Base extend Enumerize enumerize :sex, in: [:male, :female], default: lambda { |user| SexIdentifier.sex_for_name(user.name).to_sym } enumerize :role, in: [:user, :admin], default: :user end ``` Mongoid: ```ruby class User include Mongoid::Document extend Enumerize field :role enumerize :role, in: [:user, :admin], default: :user end ``` MongoMapper: ```ruby class User include MongoMapper::Document extend Enumerize key :role enumerize :role, in: [:user, :admin], default: :user end ``` I18n: ```ruby en: enumerize: user: sex: male: "Male" female: "Female" ``` or if you use `sex` attribute across several models you can use `defaults` scope: ```ruby en: enumerize: defaults: sex: male: "Male" female: "Female" ``` You can also pass `i18n_scope` option to specify scope (or array of scopes) storing the translations. ```ruby class Person extend Enumerize extend ActiveModel::Naming enumerize :sex, in: %w[male female], i18n_scope: "sex" enumerize :color, in: %w[black white], i18n_scope: ["various.colors", "colors"] end # localization file en: sex: male: "Male" female: "Female" various: colors: black: "Black" colors: white: "White" ``` Note that if you want to use I18n feature with plain Ruby object don't forget to extend it with `ActiveModel::Naming`: ```ruby class User extend Enumerize extend ActiveModel::Naming end ``` get attribute value: ```ruby @user.sex_text # or @user.sex.text ``` get all values for enumerized attribute: ```ruby User.sex.values # or User.enumerized_attributes[:sex].values ``` use it with forms (it supports `:only` and `:except` options): ```erb <%= form_for @user do |f| %> <%= f.select :sex, User.sex.options %> <% end %> ``` Boolean methods: ```ruby user.sex = :male user.sex.male? #=> true user.sex.female? #=> false ``` Predicate methods: ```ruby class User extend Enumerize enumerize :sex, in: %w(male female), predicates: true end user = User.new user.male? # => false user.female? # => false user.sex = 'male' user.male? # => true user.female? # => false ``` Using prefix: ```ruby class User extend Enumerize enumerize :sex, in: %w(male female), predicates: { prefix: true } end user = User.new user.sex = 'female' user.sex_female? # => true ``` Use `:only` and `:except` options to specify what values create predicate methods for. To make some attributes shared across different classes it's possible to define them in a separate module and then include it into classes: ```ruby module PersonEnumerations extend Enumerize enumerize :sex, in: %w[male female] end class Person include PersonEnumerations end class User include PersonEnumerations end ``` It's also possible to store enumerized attribute value using custom values (e.g. integers). You can pass a hash as `:in` option to achieve this: ```ruby class User < ActiveRecord::Base extend Enumerize enumerize :role, in: {:user => 1, :admin => 2} end user = User.new user.role = :user user.role #=> 'user' user.role_value #=> 1 User.role.find_value(:user).value #=> 1 User.role.find_value(:admin).value #=> 2 ``` ActiveRecord scopes: ```ruby class User < ActiveRecord::Base extend Enumerize enumerize :sex, :in => [:male, :female], scope: true enumerize :status, :in => { active: 1, blocked: 2 }, scope: :having_status end User.with_sex(:female) # SELECT "users".* FROM "users" WHERE "users"."sex" IN ('female') User.without_sex(:male) # SELECT "users".* FROM "users" WHERE "users"."sex" NOT IN ('male') User.having_status(:blocked).with_sex(:male, :female) # SELECT "users".* FROM "users" WHERE "users"."status" IN (2) AND "users"."sex" IN ('male', 'female') ``` :warning: It is not possible to define a scope when using the `:multiple` option. :warning: Array-like attributes with plain ruby objects: ```ruby class User extend Enumerize enumerize :interests, in: [:music, :sports], multiple: true end user = User.new user.interests << :music user.interests << :sports ``` and with ActiveRecord: ```ruby class User < ActiveRecord::Base extend Enumerize serialize :interests, Array enumerize :interests, in: [:music, :sports], multiple: true end ``` get an array of all text values: ```ruby @user.interests.texts # shortcut for @user.interests.map(&:text) ``` ### SimpleForm If you are using SimpleForm gem you don't need to specify input type (`:select` by default) and collection: ```erb <%= simple_form_for @user do |f| %> <%= f.input :sex %> <% end %> ``` and if you want it as radio buttons: ```erb <%= simple_form_for @user do |f| %> <%= f.input :sex, :as => :radio_buttons %> <% end %> ``` ### Formtastic If you are using Formtastic gem you also don't need to specify input type (`:select` by default) and collection: ```erb <%= semantic_form_for @user do |f| %> <%= f.input :sex %> <% end %> ``` and if you want it as radio buttons: ```erb <%= semantic_form_for @user do |f| %> <%= f.input :sex, :as => :radio %> <% end %> ``` ### RSpec Also you can use builtin RSpec matcher: ```ruby class User extend Enumerize enumerize :sex, in: [:male, :female] end describe User do it { should enumerize(:sex) } # or with RSpec 3 expect syntax it { is_expected.to enumerize(:sex) } end ``` #### Qualifiers ##### in Use `in` to test usage of the `:in` option. ```ruby class User extend Enumerize enumerize :sex, in: [:male, :female] end describe User do it { should enumerize(:sex).in(:male, :female) } end ``` You can test enumerized attribute value using custom values with the `in` qualifier. ```ruby class User extend Enumerize enumerize :sex, in: { male: 0, female: 1 } end describe User do it { should enumerize(:sex).in(male: 0, female: 1) } end ``` ##### with_default Use `with_default` to test usage of the `:default` option. ```ruby class User extend Enumerize enumerize :sex, in: [:male, :female], default: :female end describe User do it { should enumerize(:sex).in(:male, :female).with_default(:female) } end ``` ##### with_i18n_scope Use `with_i18n_scope` to test usage of the `:i18n_scope` option. ```ruby class User extend Enumerize enumerize :sex, in: [:male, :female], i18n_scope: 'sex' end describe User do it { should enumerize(:sex).in(:male, :female).with_i18n_scope('sex') } end ``` ##### with_predicates Use `with_predicates` to test usage of the `:predicates` option. ```ruby class User extend Enumerize enumerize :sex, in: [:male, :female], predicates: true end describe User do it { should enumerize(:sex).in(:male, :female).with_predicates(true) } end ``` You can text prefixed predicates with the `with_predicates` qualifiers. ```ruby class User extend Enumerize enumerize :sex, in: [:male, :female], predicates: { prefix: true } end describe User do it { should enumerize(:sex).in(:male, :female).with_predicates(prefix: true) } end ``` ##### with_scope Use `with_scope` to test usage of the `:scope` option. ```ruby class User extend Enumerize enumerize :sex, in: [:male, :female], scope: true end describe User do it { should enumerize(:sex).in(:male, :female).with_scope(true) } end ``` You can text custom scope with the `with_scope` qualifiers. ```ruby class User extend Enumerize enumerize :sex, in: [:male, :female], scope: :having_sex end describe User do it { should enumerize(:sex).in(:male, :female).with_scope(scope: :having_sex) } end ``` ##### with_multiple Use `with_multiple` to test usage of the `:multiple` option. ```ruby class User extend Enumerize enumerize :sex, in: [:male, :female], multiple: true end describe User do it { should enumerize(:sex).in(:male, :female).with_multiple(true) } end ``` ### Minitest with Shoulda You can use the RSpec matcher with shoulda in your tests by adding two lines in your `test_helper.rb` inside `class ActiveSupport::TestCase` definition: ```ruby class ActiveSupport::TestCase ActiveRecord::Migration.check_pending! require 'enumerize/integrations/rspec' extend Enumerize::Integrations::RSpec ... end ``` ### Other Integrations Enumerize integrates with the following automatically: * [RailsAdmin](https://github.com/sferik/rails_admin/) ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Added some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request