enumerize-1.0.0/ 0000755 0000041 0000041 00000000000 12560050170 013537 5 ustar www-data www-data enumerize-1.0.0/Rakefile 0000644 0000041 0000041 00000000470 12560050170 015205 0 ustar www-data www-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('default') do |t|
t.pattern = 'test/rspec_spec.rb'
end
task :default => :test
enumerize-1.0.0/Gemfile 0000644 0000041 0000041 00000000660 12560050170 015034 0 ustar www-data www-data source 'https://rubygems.org'
gemspec
gem 'rake'
gem 'minitest', '~> 5.5.1'
gem 'rspec', :require => false
gem 'rails', '4.2.0', :require => false
gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
platforms :rbx do
gem 'rubysl', '~> 2.0'
gem 'psych'
gem 'rubinius-developer_tools'
gem 'rubysl-test-unit'
end
gem 'mongoid'
gem 'simple_form'
gem 'formtastic'
enumerize-1.0.0/enumerize.gemspec 0000644 0000041 0000041 00000001567 12560050170 017120 0 ustar www-data www-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.0.0/MIT-LICENSE 0000644 0000041 0000041 00000002052 12560050170 015172 0 ustar www-data www-data Copyright (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.0.0/.travis.yml 0000644 0000041 0000041 00000000620 12560050170 015646 0 ustar www-data www-data language: 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.0.0/lib/ 0000755 0000041 0000041 00000000000 12560050170 014305 5 ustar www-data www-data enumerize-1.0.0/lib/enumerize.rb 0000644 0000041 0000041 00000003641 12560050170 016641 0 ustar www-data www-data require '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 :MongoidSupport, 'enumerize/mongoid'
module Scope
autoload :ActiveRecord, 'enumerize/scope/activerecord'
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?(::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.0.0/lib/enumerize/ 0000755 0000041 0000041 00000000000 12560050170 016310 5 ustar www-data www-data enumerize-1.0.0/lib/enumerize/predicatable.rb 0000644 0000041 0000041 00000000707 12560050170 021260 0 ustar www-data www-data module 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.0.0/lib/enumerize/integrations/ 0000755 0000041 0000041 00000000000 12560050170 021016 5 ustar www-data www-data enumerize-1.0.0/lib/enumerize/integrations/rails_admin.rb 0000644 0000041 0000041 00000000544 12560050170 023630 0 ustar www-data www-data module 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.0.0/lib/enumerize/integrations/rspec/ 0000755 0000041 0000041 00000000000 12560050170 022132 5 ustar www-data www-data enumerize-1.0.0/lib/enumerize/integrations/rspec/matcher.rb 0000644 0000041 0000041 00000003627 12560050170 024112 0 ustar www-data www-data module Enumerize
module Integrations
module RSpec
class Matcher
attr_accessor :attr, :values, :subject, :default
def initialize(attr)
self.attr = attr
end
def in(*values)
self.values = values.map(&:to_s).sort
self
end
def with_default(default)
self.default = default.to_s
self
end
def failure_message
message = " expected :#{attr} to allow value#{values.size == 1 ? nil : 's'}: #{quote_values(values)},"
message += " but it allows #{quote_values(enumerized_values)} instead"
if default && !matches_default_value?
message = " expected :#{attr} to have #{default.inspect} as default value,"
message += " but it sets #{enumerized_default.inspect} instead"
end
message
end
def description
description = "enumerize :#{attr} in: #{quote_values(values)}"
description += " with #{default.inspect} as default value" if default
description
end
def matches?(subject)
self.subject = subject
matches = true
matches &= matches_attributes?
matches &= matches_default_value? if default
matches
end
private
def matches_attributes?
values == enumerized_values
end
def matches_default_value?
default == enumerized_default
end
def enumerized_values
@enumerized_values ||= attributes[attr.to_s].values.sort
end
def enumerized_default
@enumerized_default ||= attributes[attr.to_s].default_value
end
def attributes
subject.class.enumerized_attributes.attributes
end
def quote_values(values)
values.map(&:inspect).join(', ')
end
end
end
end
end
enumerize-1.0.0/lib/enumerize/integrations/rspec.rb 0000644 0000041 0000041 00000000457 12560050170 022465 0 ustar www-data www-data require '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.0.0/lib/enumerize/predicates.rb 0000644 0000041 0000041 00000003130 12560050170 020755 0 ustar www-data www-data require '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}?" }
end
def build(klass)
klass.delegate(*names, to: @attr.name, prefix: @options[:prefix], allow_nil: true)
end
end
end
end
enumerize-1.0.0/lib/enumerize/set.rb 0000644 0000041 0000041 00000002577 12560050170 017443 0 ustar www-data www-data require '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.collect { |value| value.text }
end
delegate :join, to: :to_ary
def ==(other)
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.0.0/lib/enumerize/value.rb 0000644 0000041 0000041 00000001740 12560050170 017753 0 ustar www-data www-data require '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.0.0/lib/enumerize/module.rb 0000644 0000041 0000041 00000001061 12560050170 020120 0 ustar www-data www-data module 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.0.0/lib/enumerize/hooks/ 0000755 0000041 0000041 00000000000 12560050170 017433 5 ustar www-data www-data enumerize-1.0.0/lib/enumerize/hooks/simple_form.rb 0000644 0000041 0000041 00000002417 12560050170 022300 0 ustar www-data www-data require '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.0.0/lib/enumerize/hooks/formtastic.rb 0000644 0000041 0000041 00000001461 12560050170 022135 0 ustar www-data www-data require '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.0.0/lib/enumerize/hooks/uniqueness.rb 0000644 0000041 0000041 00000001210 12560050170 022151 0 ustar www-data www-data require '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.0.0/lib/enumerize/version.rb 0000644 0000041 0000041 00000000051 12560050170 020316 0 ustar www-data www-data module Enumerize
VERSION = "1.0.0"
end
enumerize-1.0.0/lib/enumerize/scope/ 0000755 0000041 0000041 00000000000 12560050170 017421 5 ustar www-data www-data enumerize-1.0.0/lib/enumerize/scope/mongoid.rb 0000644 0000041 0000041 00000001654 12560050170 021410 0 ustar www-data www-data module 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.0.0/lib/enumerize/scope/activerecord.rb 0000644 0000041 0000041 00000001777 12560050170 022434 0 ustar www-data www-data module 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.0.0/lib/enumerize/module_attributes.rb 0000644 0000041 0000041 00000000355 12560050170 022373 0 ustar www-data www-data module 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.0.0/lib/enumerize/mongoid.rb 0000644 0000041 0000041 00000000433 12560050170 020271 0 ustar www-data www-data module 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.0.0/lib/enumerize/base.rb 0000644 0000041 0000041 00000005776 12560050170 017566 0 ustar www-data www-data module 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]
else
super
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.0.0/lib/enumerize/activerecord.rb 0000644 0000041 0000041 00000002247 12560050170 021314 0 ustar www-data www-data module 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.0.0/lib/enumerize/attribute_map.rb 0000644 0000041 0000041 00000001155 12560050170 021477 0 ustar www-data www-data module 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.0.0/lib/enumerize/attribute.rb 0000644 0000041 0000041 00000012077 12560050170 020647 0 ustar www-data www-data module 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.0.0/Gemfile.rails40 0000644 0000041 0000041 00000000656 12560050170 016316 0 ustar www-data www-data source 'https://rubygems.org'
gemspec
gem 'rake'
gem 'minitest', '~> 4.1'
gem 'rspec', :require => false
gem 'rails', '4.0.1', :require => false
gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
platforms :rbx do
gem 'rubysl', '~> 2.0'
gem 'psych'
gem 'rubinius-developer_tools'
gem 'rubysl-test-unit'
end
gem 'mongoid'
gem 'simple_form'
gem 'formtastic'
enumerize-1.0.0/metadata.yml 0000644 0000041 0000041 00000006203 12560050170 016043 0 ustar www-data www-data --- !ruby/object:Gem::Specification
name: enumerize
version: !ruby/object:Gem::Version
version: 1.0.0
platform: ruby
authors:
- Sergey Nartimov
autorequire:
bindir: bin
cert_chain: []
date: 2015-08-02 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: activesupport
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '3.2'
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '3.2'
description: Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper
support
email: team@brainspec.com
executables: []
extensions: []
extra_rdoc_files: []
files:
- ".gitignore"
- ".travis.yml"
- CHANGELOG.md
- Gemfile
- Gemfile.mongo_mapper
- Gemfile.rails40
- MIT-LICENSE
- README.md
- Rakefile
- enumerize.gemspec
- lib/enumerize.rb
- lib/enumerize/activerecord.rb
- lib/enumerize/attribute.rb
- lib/enumerize/attribute_map.rb
- lib/enumerize/base.rb
- lib/enumerize/hooks/formtastic.rb
- lib/enumerize/hooks/simple_form.rb
- lib/enumerize/hooks/uniqueness.rb
- lib/enumerize/integrations/rails_admin.rb
- lib/enumerize/integrations/rspec.rb
- lib/enumerize/integrations/rspec/matcher.rb
- lib/enumerize/module.rb
- lib/enumerize/module_attributes.rb
- lib/enumerize/mongoid.rb
- lib/enumerize/predicatable.rb
- lib/enumerize/predicates.rb
- lib/enumerize/scope/activerecord.rb
- lib/enumerize/scope/mongoid.rb
- lib/enumerize/set.rb
- lib/enumerize/value.rb
- lib/enumerize/version.rb
- test/activerecord_test.rb
- test/attribute_map_test.rb
- test/attribute_test.rb
- test/base_test.rb
- test/formtastic_test.rb
- test/module_attributes_test.rb
- test/mongo_mapper_test.rb
- test/mongoid_test.rb
- test/multiple_test.rb
- test/predicates_test.rb
- test/rails_admin_test.rb
- test/rspec_matcher_test.rb
- test/rspec_spec.rb
- test/set_test.rb
- test/simple_form_test.rb
- test/support/mock_controller.rb
- test/support/view_test_helper.rb
- test/test_helper.rb
- test/value_test.rb
homepage: https://github.com/brainspec/enumerize
licenses: []
metadata: {}
post_install_message:
rdoc_options: []
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 1.9.3
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '0'
requirements: []
rubyforge_project:
rubygems_version: 2.4.7
signing_key:
specification_version: 4
summary: Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper support
test_files:
- test/activerecord_test.rb
- test/attribute_map_test.rb
- test/attribute_test.rb
- test/base_test.rb
- test/formtastic_test.rb
- test/module_attributes_test.rb
- test/mongo_mapper_test.rb
- test/mongoid_test.rb
- test/multiple_test.rb
- test/predicates_test.rb
- test/rails_admin_test.rb
- test/rspec_matcher_test.rb
- test/rspec_spec.rb
- test/set_test.rb
- test/simple_form_test.rb
- test/support/mock_controller.rb
- test/support/view_test_helper.rb
- test/test_helper.rb
- test/value_test.rb
enumerize-1.0.0/test/ 0000755 0000041 0000041 00000000000 12560050170 014516 5 ustar www-data www-data enumerize-1.0.0/test/mongo_mapper_test.rb 0000644 0000041 0000041 00000002676 12560050170 020600 0 ustar www-data www-data require '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.0.0/test/attribute_map_test.rb 0000644 0000041 0000041 00000002621 12560050170 020743 0 ustar www-data www-data require '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.0.0/test/simple_form_test.rb 0000644 0000041 0000041 00000006205 12560050170 020421 0 ustar www-data www-data require '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.0.0/test/rspec_matcher_test.rb 0000644 0000041 0000041 00000004417 12560050170 020727 0 ustar www-data www-data require 'test_helper'
require 'enumerize/integrations/rspec'
describe Enumerize::Integrations::RSpec do
class Should
include Enumerize::Integrations::RSpec
end
let(:klass) do
Class.new do
extend Enumerize
end
end
let(:should) { Should.new }
let(:object) { klass.new }
describe '#description' do
before do
klass.enumerize(:sex, :in => [:male, :female])
end
it 'returns description without default value' do
matcher = should.enumerize(:sex).in(:male, :female)
matcher.description.must_equal 'enumerize :sex in: "female", "male"'
end
it 'returns description with default value' do
matcher = should.enumerize(:sex).in(:male, :female).with_default(:male)
matcher.description.must_equal 'enumerize :sex in: "female", "male" with "male" as default value'
end
end
describe '#matches?' do
before do
klass.enumerize(:sex, :in => [:male, :female])
end
it 'returns true' do
matcher = should.enumerize(:sex).in(:male, :female)
matcher.matches?(object).must_equal true
end
it 'returns false' do
matcher = should.enumerize(:sex).in(:bar)
matcher.matches?(object).must_equal false
end
end
describe '#failure_message' do
before do
klass.enumerize(:sex, :in => [:male, :female], :default => :male)
end
it 'returns failure message for invalid :in option' do
matcher = should.enumerize(:sex).in(:bar)
matcher.subject = object
expected = ' expected :sex to allow value: "bar", but it allows "female", "male" instead'
matcher.failure_message.must_equal expected
end
it 'returns failure message for invalid :with_default option' do
matcher = should.enumerize(:sex).in(:male, :female).with_default(:foo)
matcher.subject = object
expected = ' expected :sex to have "foo" as default value, but it sets "male" instead'
matcher.failure_message.must_equal expected
end
it 'returns failure message for ivalid :in option with default value' do
matcher = should.enumerize(:sex).in(:bar).with_default(:male)
matcher.subject = object
expected = ' expected :sex to allow value: "bar", but it allows "female", "male" instead'
matcher.failure_message.must_equal expected
end
end
end
enumerize-1.0.0/test/rails_admin_test.rb 0000644 0000041 0000041 00000001265 12560050170 020370 0 ustar www-data www-data require '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.0.0/test/module_attributes_test.rb 0000644 0000041 0000041 00000002447 12560050170 021644 0 ustar www-data www-data require '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.0.0/test/formtastic_test.rb 0000644 0000041 0000041 00000006107 12560050170 020261 0 ustar www-data www-data require '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.0.0/test/predicates_test.rb 0000644 0000041 0000041 00000002676 12560050170 020240 0 ustar www-data www-data require '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 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.0.0/test/set_test.rb 0000644 0000041 0000041 00000006103 12560050170 016675 0 ustar www-data www-data require '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.0.0/test/test_helper.rb 0000644 0000041 0000041 00000001631 12560050170 017362 0 ustar www-data www-data require '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.0.0/test/rspec_spec.rb 0000644 0000041 0000041 00000000451 12560050170 017171 0 ustar www-data www-data require 'rails'
require 'enumerize'
require 'rspec'
class RSpecUser
extend Enumerize
enumerize :sex, in: [:male, :female], default: :male
end
describe RSpecUser do
it { should enumerize(:sex).in(:male, :female) }
it { should enumerize(:sex).in(:male, :female).with_default(:male) }
end
enumerize-1.0.0/test/mongoid_test.rb 0000644 0000041 0000041 00000006250 12560050170 017541 0 ustar www-data www-data require 'test_helper'
begin
silence_warnings do
require 'mongoid'
end
Mongoid.configure do |config|
config.sessions = { :default => { :database => 'enumerize-test-suite', hosts: ['127.0.0.1:27017'] } }
config.use_utc = true
config.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.0.0/test/base_test.rb 0000644 0000041 0000041 00000012256 12560050170 017022 0 ustar www-data www-data require '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.0.0/test/activerecord_test.rb 0000644 0000041 0000041 00000021452 12560050170 020560 0 ustar www-data www-data require '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.0.0/test/value_test.rb 0000644 0000041 0000041 00000007570 12560050170 017227 0 ustar www-data www-data require 'test_helper'
require 'yaml'
describe Enumerize::Value do
let(:attr) { Struct.new(:values).new([]) }
let(:value) { Enumerize::Value.new(attr, 'test_value', 1) }
it 'is a string' do
value.must_be_kind_of String
end
describe 'equality' do
it 'is compared to string' do
value.must_be :==, 'test_value'
value.wont_be :==, 'not_value'
end
it 'is compared to symbol' do
value.must_be :==, :test_value
value.wont_be :==, :not_value
end
it 'is compared to integer' do
value.must_be :==, 1
value.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
value.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
value.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
value.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
value.text.must_be :==, "Model Specific translation"
end
end
it 'uses simply humanized value when translation is undefined' do
store_translations(:en, :enumerize => {}) do
value.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
value.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
value.text.must_be :==, "Scope specific translation"
end
end
end
describe 'boolean methods comparison' do
before do
attr.values = [value, Enumerize::Value.new(attr, 'other_value')]
end
it 'returns true if value equals method' do
value.test_value?.must_equal true
end
it 'returns false if value does not equal method' do
value.other_value?.must_equal false
end
it 'raises NoMethodError if there are no values like boolean method' do
proc {
value.some_method?
}.must_raise NoMethodError
end
it 'raises ArgumentError if arguments are passed' do
proc {
value.other_value?('<3')
}.must_raise ArgumentError
end
it 'responds to methods for existing values' do
value.must_respond_to :test_value?
value.must_respond_to :other_value?
end
it 'returns a method object' do
value.method(:test_value?).must_be_instance_of Method
end
it "doesn't respond to a method for not existing value" do
value.wont_respond_to :some_method?
end
end
describe 'serialization' do
let(:value) { Enumerize::Value.new(attr, 'test_value') }
it 'should be serialized to yaml as string value' do
assert_equal YAML.dump('test_value'), YAML.dump(value)
end
end
end
enumerize-1.0.0/test/multiple_test.rb 0000644 0000041 0000041 00000002627 12560050170 017744 0 ustar www-data www-data require '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.0.0/test/support/ 0000755 0000041 0000041 00000000000 12560050170 016232 5 ustar www-data www-data enumerize-1.0.0/test/support/view_test_helper.rb 0000644 0000041 0000041 00000001266 12560050170 022134 0 ustar www-data www-data require '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.0.0/test/support/mock_controller.rb 0000644 0000041 0000041 00000000470 12560050170 021754 0 ustar www-data www-data class 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.0.0/test/attribute_test.rb 0000644 0000041 0000041 00000007436 12560050170 020117 0 ustar www-data www-data require '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.0.0/.gitignore 0000644 0000041 0000041 00000000352 12560050170 015527 0 ustar www-data www-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.0.0/Gemfile.mongo_mapper 0000644 0000041 0000041 00000000665 12560050170 017523 0 ustar www-data www-data source 'https://rubygems.org'
gemspec
gem 'rake'
gem 'minitest', '~> 5.5.1'
gem 'rspec', :require => false
gem 'rails', '4.2.0', :require => false
gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
platforms :rbx do
gem 'rubysl', '~> 2.0'
gem 'psych'
gem 'rubinius-developer_tools'
gem 'rubysl-test-unit'
end
gem 'mongo_mapper'
gem 'simple_form'
gem 'formtastic'
enumerize-1.0.0/CHANGELOG.md 0000644 0000041 0000041 00000020761 12560050170 015356 0 ustar www-data www-data ## master
### enhancements
### 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.0.0/README.md 0000644 0000041 0000041 00000015677 12560050170 015036 0 ustar www-data www-data # Enumerize [](http://travis-ci.org/brainspec/enumerize) [](https://gemnasium.com/brainspec/enumerize)
Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper 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) storring the translations. Note that `i18n_scope` option does not accept scope as array:
```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
```
### 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], default: :male
end
describe User do
it { should enumerize(:sex).in(:male, :female) }
it { should enumerize(:sex).in(:male, :female).with_default(:male) }
# or with RSpec 3 expect syntax
it { is_expected.to enumerize(:sex).in(:male, :female) }
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