enumerize-2.2.2/0000755000004100000410000000000013313023144013542 5ustar www-datawww-dataenumerize-2.2.2/.travis.yml0000644000004100000410000000102113313023144015645 0ustar www-datawww-datalanguage: ruby sudo: false services: - postgresql - mongodb gemfile: - Gemfile - Gemfile.rails42 - Gemfile.rails50 - Gemfile.rails52 - Gemfile.mongo_mapper rvm: - 2.2.7 - 2.3.3 - 2.4.1 - jruby-9.1.14.0 env: global: - DB_USER=postgres - DB_PASS= matrix: - DB=sqlite3 - DB=postgresql matrix: fast_finish: true allow_failures: - rvm: jruby-9.1.14.0 exclude: - gemfile: Gemfile.mongo_mapper env: DB=postgresql branches: only: - master notifications: email: false enumerize-2.2.2/test/0000755000004100000410000000000013313023144014521 5ustar www-datawww-dataenumerize-2.2.2/test/mongo_mapper_test.rb0000644000004100000410000000267313313023144020600 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_be_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-2.2.2/test/attribute_test.rb0000644000004100000410000000743613313023144020122 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-2.2.2/test/predicates_test.rb0000644000004100000410000000325113313023144020231 0ustar www-datawww-datarequire 'test_helper' describe Enumerize::Predicates do let(:kklass) do Class.new do extend Enumerize end end let(:object) { kklass.new } it 'creates predicate methods' do kklass.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 kklass.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 kklass.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 kklass.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 kklass.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 kklass.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 kklass.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 kklass.enumerize(:foo, in: %w(a b), predicates: { except: :a }) object.wont_respond_to :a? object.must_respond_to :b? end end enumerize-2.2.2/test/attribute_map_test.rb0000644000004100000410000000262113313023144020746 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-2.2.2/test/multiple_test.rb0000644000004100000410000000264213313023144017744 0ustar www-datawww-datarequire 'test_helper' describe Enumerize::Base do let(:kklass) do Class.new do extend Enumerize end end let(:subklass) do Class.new(kklass) end let(:object) { kklass.new } it 'returns [] when not set' do kklass.enumerize :foos, in: %w(a b), multiple: true object.foos.must_equal [] end it 'returns setted array' do kklass.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 kklass.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 kklass.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 kklass.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 kklass.enumerize :foos, in: %w(a b c), multiple: true object.wont_respond_to :foos_text end it "doesn't define _value method" do kklass.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 kklass.enumerize :foos, in: %w(a b c), multiple: true, scope: true end end end enumerize-2.2.2/test/activerecord_test.rb0000644000004100000410000003260413313023144020564 0ustar www-datawww-data# frozen_string_literal: true require 'test_helper' require 'active_record' require 'logger' db = (ENV['DB'] || 'sqlite3').to_sym silence_warnings do ActiveRecord::Migration.verbose = false ActiveRecord::Base.logger = Logger.new(nil) ActiveRecord::Base.configurations = { 'sqlite3' => { 'adapter' => 'sqlite3', 'database' => ':memory:' }, 'postgresql' => { 'adapter' => 'postgresql', 'username' => ENV['DB_USER'], 'password' => ENV['DB_PASSD'], 'database' => 'enumerize_test' }, 'postgresql_master' => { 'adapter' => 'postgresql', 'username' => ENV['DB_USER'], 'password' => ENV['DB_PASS'], 'database' => 'template1', 'schema_search_path' => 'public' } } if db == :postgresql ActiveRecord::Base.establish_connection(:postgresql_master) ActiveRecord::Base.connection.recreate_database('enumerize_test') end ActiveRecord::Base.establish_connection(db) 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.integer :user_id t.string :visibility t.integer :status 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 belongs_to :user enumerize :status, in: {draft: 1, release: 2} 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] # There is no column for relationship enumeration for testing purposes: model # should not be broken even if the associated column does not exist yet. enumerize :relationship, :in => [:single, :married] has_many :documents end class UniqStatusUser < User validates :status, uniqueness: true validates :sex, presence: true end class InterestsRequiredUser < User validates :interests, 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_be_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_be_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 'validates presence with multiple attributes' do user = InterestsRequiredUser.new user.interests = [] user.valid? user.errors[:interests].wont_be :empty? user.interests = [''] user.valid? user.errors[:interests].wont_be :empty? user.interests = [:dancing, :programming] user.valid? user.errors[:interests].must_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 it 'does not change by the practical same value' do user = User.create!(status: 'active') user.reload user.status = 'active' user.changes.must_be_empty end it 'allows using update_all' do User.delete_all user = User.create(status: :active, account_type: :premium) User.update_all(status: :blocked) user.reload user.status.must_equal 'blocked' User.update_all(status: :active, account_type: :basic) user.reload user.status.must_equal 'active' user.account_type.must_equal 'basic' end it 'allows using update_all for multiple enumerize' do User.delete_all klass = Class.new(User) klass.enumerize :interests, in: { music: 0, sports: 1, dancing: 2, programming: 3}, multiple: true user = klass.create(status: :active) klass.update_all(status: :blocked, interests: [:music, :dancing]) user = klass.find(user.id) user.status.must_equal 'blocked' user.interests.must_equal %w(music dancing) end it 'allows using update_all with values' do User.delete_all user = User.create(status: :active) User.update_all(status: 2) user.reload user.status.must_equal 'blocked' end it 'allows using update_all on relation objects' do User.delete_all user = User.create(status: :active, account_type: :premium) User.all.update_all(status: :blocked) user.reload user.status.must_equal 'blocked' end it 'allows using update_all on association relation objects' do User.delete_all Document.delete_all user = User.create document = Document.create(user: user, status: :draft) user.documents.update_all(status: :release) document.reload document.status.must_equal 'release' end it 'preserves string usage of update_all' do User.delete_all user = User.create(name: "Fred") User.update_all("name = 'Frederick'") user.reload user.name.must_equal 'Frederick' end it 'preserves interpolated array usage of update_all' do User.delete_all user = User.create(name: "Fred") User.update_all(["name = :name", {name: 'Frederick'}]) user.reload user.name.must_equal 'Frederick' end it 'sets attribute to nil if given one is not valid' do User.delete_all user = User.create(status: :active) User.update_all(status: :foo) user.reload user.status.must_be_nil end it 'supports AR types serialization' do type = User.type_for_attribute('status') type.must_be_instance_of Enumerize::ActiveRecordSupport::Type serialized = type.serialize('blocked') serialized.must_equal 2 end it 'has AR type itself JSON serializable' do type = User.type_for_attribute('status') type.as_json['attr'].must_equal 'status' end it "doesn't break YAML serialization" do user = YAML.load(User.create(status: :blocked).to_yaml) user.status.must_equal 'blocked' end # https://github.com/brainspec/enumerize/issues/304 it "fallbacks to a raw passed value if AR type can't find value in the attribute" do table = User.arel_table sql = User.where(table[:account_type].matches '%foo%').to_sql sql.must_include 'LIKE \'%foo%\'' end end enumerize-2.2.2/test/sequel_test.rb0000644000004100000410000001705613313023144017414 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 plugin :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 plugin :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_be_nil end it 'saves value' do User.filter{ true }.delete user = User.new user.sex = :female user.save user.sex.must_equal 'female' end it 'loads value' do User.filter{ true }.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{ true }.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{ true }.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_be_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{ true }.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{ true }.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{ true }.delete document = Document.new document.visibility = :protected document.visibility.must_equal 'protected' end it 'supports defining enumerized scopes on abstract class' do Document.filter{ true }.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{ true }.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-2.2.2/test/activemodel_test.rb0000644000004100000410000000526213313023144020406 0ustar www-datawww-datarequire 'test_helper' if defined?(::ActiveModel::Attributes) describe Enumerize do class ActiveModelUser include ActiveModel::Model include ActiveModel::Attributes extend Enumerize attribute :name, :string enumerize :sex, :in => %w[male female] enumerize :role, :in => %w[admin user], :default => 'user' enumerize :interests, :in => [:music, :sports, :dancing, :programming], :multiple => true end class InterestsRequiredActiveModelUser < ActiveModelUser validates :interests, presence: true end let(:model) { ActiveModelUser } it 'initialize value' do user = model.new(:name => 'active_model_user', :sex => :male, :role => :user, :interests => [:music, :programming]) user.sex.must_equal 'male' user.sex_text.must_equal 'Male' user.role.must_equal 'user' user.role_text.must_equal 'User' user.interests.must_equal %w(music programming) end it 'sets nil if invalid value is passed' do user = model.new user.sex = :invalid user.sex.must_be_nil end it 'stores value' do user = model.new user.sex = :female user.sex.must_equal 'female' 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 'supports multiple attributes' do user = ActiveModelUser.new user.interests.must_be_instance_of Enumerize::Set user.interests.must_be_empty user.interests << :music 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 = ActiveModelUser.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 = ActiveModelUser.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 'validates presence with multiple attributes' do user = InterestsRequiredActiveModelUser.new user.interests = [] user.valid? user.errors[:interests].wont_be :empty? user.interests = [''] user.valid? user.errors[:interests].wont_be :empty? user.interests = [:dancing, :programming] user.valid? user.errors[:interests].must_be_empty end end else # Skip end enumerize-2.2.2/test/set_test.rb0000644000004100000410000000610713313023144016704 0ustar www-datawww-datarequire 'test_helper' require 'yaml' describe Enumerize::Set do let(:kklass) do Class.new do extend Enumerize enumerize :foo, :in => %w(a b c), :multiple => true end end let(:object) { kklass.new } def build_set(values) @set = Enumerize::Set.new(object, kklass.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, kklass.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-2.2.2/test/value_test.rb0000644000004100000410000000775013313023144017232 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-2.2.2/test/support/0000755000004100000410000000000013313023144016235 5ustar www-datawww-dataenumerize-2.2.2/test/support/view_test_helper.rb0000644000004100000410000000126613313023144022137 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-2.2.2/test/support/mock_controller.rb0000644000004100000410000000054113313023144021756 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 def polymorphic_mappings {} end end enumerize-2.2.2/test/simple_form_test.rb0000644000004100000410000000725713313023144020434 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 class Registration < Struct.new(:sex) extend Enumerize enumerize :sex, in: [:male, :female] 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 it 'renders select with enumerized values for non-ActiveModel object' do concat(simple_form_for(Registration.new, as: 'registration', url: '/') do |f| f.input(:sex) end) assert_select 'select option[value=male]' assert_select 'select option[value=female]' end it 'does not affect forms without object' do concat(simple_form_for('') do |f| f.input(:name) end) assert_select 'input.string' end end enumerize-2.2.2/test/rails_admin_test.rb0000644000004100000410000000127513313023144020374 0ustar www-datawww-datarequire 'test_helper' class RailsAdminSpec < MiniTest::Spec let(:kklass) do Class.new do extend Enumerize end end let(:object) { kklass.new } it 'defines enum method' do store_translations(:en, :enumerize => {:foo => {:a => 'a text', :b => 'b text'}}) do kklass.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 kklass.enumerize(:foo, in: {:a => 1, :b => 2}) object.foo_enum.must_equal [['a text', 'a'], ['b text', 'b']] end end end enumerize-2.2.2/test/test_helper.rb0000644000004100000410000000163113313023144017365 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-2.2.2/test/formtastic_test.rb0000644000004100000410000000717113313023144020266 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 class Registration < Struct.new(:sex) extend Enumerize enumerize :sex, in: [:male, :female] 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 it 'renders select with enumerized values for non-ActiveModel object' do concat(semantic_form_for(Registration.new, as: 'registration', url: '/') do |f| f.input(:sex) end) assert_select 'select option[value=male]' assert_select 'select option[value=female]' end it 'does not affect forms without object' do concat(semantic_form_for('') do |f| f.input(:name) end) assert_select 'input[type=text]' end end enumerize-2.2.2/test/module_attributes_test.rb0000644000004100000410000000244713313023144021647 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-2.2.2/test/base_test.rb0000644000004100000410000001226613313023144017026 0ustar www-datawww-datarequire 'test_helper' describe Enumerize::Base do let(:kklass) do Class.new do extend Enumerize end end let(:subklass) do Class.new(kklass) end let(:object) { kklass.new } it 'returns nil when not set' do kklass.enumerize(:foo, :in => [:a, :b]) object.foo.must_be_nil end it 'returns value that was set' do kklass.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 kklass.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 kklass.enumerize(:foo, :in => [:a, :b]) object.foo_text.must_be_nil end end it 'scopes translation by i18n key' do def kklass.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 kklass.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 kklass.enumerize(:foo, :in => [:a, :b]) object.foo = :a object.foo_text.must_equal 'A' end end it 'stores value as string' do kklass.enumerize(:foo, :in => [:a, :b]) object.foo = :a object.instance_variable_get(:@foo).must_be_instance_of String end it 'handles default value' do kklass.enumerize(:foo, :in => [:a, :b], :default => :b) object.foo.must_equal 'b' end it 'handles default value with lambda' do kklass.enumerize(:foo, :in => [:a, :b], :default => lambda { :b }) object.foo.must_equal 'b' end it 'injects object instance into lamda default value' do kklass.enumerize(:foo, :in => [:a, :b], :default => lambda { |obj| :b if obj.is_a? kklass }) object.foo.must_equal 'b' end it 'raises exception on invalid default value' do proc { kklass.enumerize(:foo, :in => [:a, :b], :default => :c) }.must_raise ArgumentError end it 'has enumerized attributes' do kklass.enumerized_attributes.must_be_empty kklass.enumerize(:foo, :in => %w[a b]) kklass.enumerized_attributes[:foo].must_be_instance_of Enumerize::Attribute end it "doesn't override existing method" do method = kklass.method(:name) kklass.enumerize(:name, :in => %w[a b], :default => 'a') kklass.method(:name).must_equal method end it "inherits enumerized attributes from a parent class" do kklass.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 kklass.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 kklass.enumerize(:foo, :in => %w[a b]) subklass.enumerize(:bar, :in => %w[c d]) kklass.enumerized_attributes[:bar].must_be_nil end it 'adds new parent class attributes to subclass' do subklass = Class.new(kklass) kklass.enumerize :foo, :in => %w[a b] subklass.enumerized_attributes[:foo].must_be_instance_of Enumerize::Attribute end it 'stores nil value' do kklass.enumerize(:foo, :in => [:a, :b]) object.foo = nil object.instance_variable_get(:@foo).must_be_nil end it 'casts value to string for validation' do kklass.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 kklass.enumerize(:foo, :in => [:a, :b]) object.foo = nil object.read_attribute_for_validation(:foo).must_be_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({}) object.foo = 'test' object.foo.must_equal 'test' object.attributes.must_equal(:foo => 'test') end it 'stores hash values' do kklass.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 kklass.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-2.2.2/test/mongoid_test.rb0000644000004100000410000000645113313023144017547 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_be_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 'does not set default value for not selected attributes' do model.delete_all model.create!(sex: :male) assert_equal ['_id'], model.only(:id).first.attributes.keys 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-2.2.2/.rspec0000644000004100000410000000003613313023144014656 0ustar www-datawww-data--color --require spec_helper enumerize-2.2.2/README.md0000644000004100000410000002374013313023144015027 0ustar www-datawww-data# Enumerize [![TravisCI](https://secure.travis-ci.org/brainspec/enumerize.svg?branch=master)](http://travis-ci.org/brainspec/enumerize) [![Gemnasium](https://gemnasium.com/brainspec/enumerize.svg)](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 ## Supported Versions - Ruby 2.2+ - Rails 4.2+ ## 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 ``` :warning: If `enumerize` is used with Mongoid, it's not recommended to use `"writer"` as a field value since `writer?` is defined by Mongoid. [See more](https://github.com/brainspec/enumerize/issues/235). :warning: 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) ``` Also, the reader method can be overridden, referencing the enumerized attribute value using `super`: ```ruby def sex if current_user.admin? "Super#{super}" else super end 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 %> ``` Please note that Enumerize overwrites the I18n keys of SimpleForm collections. The enumerized keys are used instead of the SimpleForm ones for inputs concerning enumerized attributes. If you don't want this just pass `:collection` option to the `input` call. ### 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 enumerize-2.2.2/spec/0000755000004100000410000000000013313023144014474 5ustar www-datawww-dataenumerize-2.2.2/spec/enumerize/0000755000004100000410000000000013313023144016477 5ustar www-datawww-dataenumerize-2.2.2/spec/enumerize/integrations/0000755000004100000410000000000013313023144021205 5ustar www-datawww-dataenumerize-2.2.2/spec/enumerize/integrations/rspec/0000755000004100000410000000000013313023144022321 5ustar www-datawww-dataenumerize-2.2.2/spec/enumerize/integrations/rspec/matcher_spec.rb0000644000004100000410000001740213313023144025307 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-2.2.2/spec/spec_helper.rb0000644000004100000410000000127113313023144017313 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-2.2.2/CHANGELOG.md0000644000004100000410000002745113313023144015364 0ustar www-datawww-data## master ### enhancements ### bug fix ## 2.2.2 (March 6, 2018) ### bug fix * Support non-ActiveModel objects in SimpleForm/Formtastic integration. (by [@nashby](https://github.com/nashby)) ## 2.2.1 (February 15, 2018) ### bug fix * Fix issue with SimpleForm/Formtastic forms without object. (by [@nashby](https://github.com/nashby)) ## 2.2.0 (February 13, 2018) ### enhancements * Add integration with active_interaction. (by [@runephilosof](https://github.com/runephilosof)) * Allow using `plugin :enumerize` with Sequel. (by [@jnylen](https://github.com/jnylen)) * Support ActiveModel::Attributes from Rails 5.2. (by [@troter](https://github.com/troter)) * Support Sequel 5.2.0. (by [@troter](https://github.com/troter)) ### bug fix * Fix RailsAdmin integration when enumerated field used on edit form and enumerated value wasn't set. (by [@nashby](https://github.com/nashby)) * Fallback to a raw passed value instead of nil if AR type can't find value in the attribute. (by [@nashby](https://github.com/nashby)) ## 2.1.2 (May 18, 2017) ### bug fix * Support YAML serialization for the custom AR type. (by [@lest](https://github.com/lest)) ## 2.1.1 (May 1, 2017) ### enhancements * Run tests with multiple DBs (SQLite and PostgreSQL). (by [tkawa](https://github.com/tkawa)) ### bug fix * Support deserialize and Rails 4.2 methods in the custom AR::Type class. (by [@lest](https://github.com/lest)) * Support dumping custom AR type to JSON. (by [@lest](https://github.com/lest)) ## 2.1.0 (March 31, 2017) ### enhancements * Support Active Record types serialization. (by [@lest](https://github.com/lest)) ## 2.0.1 (October 18, 2016) ### bug fix * Support enumerized attributes in #update_all on relation objects. (by [@lest](https://github.com/lest)) ## 2.0.0 (August 10, 2016) ### enhancements * Drop support for Ruby older than 2.2. Support only Ruby 2.2+. (by [@nashby](https://github.com/nashby)) * Drop support for Rails 4.0 and 4.1. Support only Rails 4.2 and newer. (by [@lest](https://github.com/lest)) * Support Rails 5.0. (by [@nashby](https://github.com/nashby) and [@lest](https://github.com/lest)) * Allow to pass enumerize values to `ActiveRecord#update_all` (by [@DmitryTsepelev](https://github.com/DmitryTsepelev) and [@ianwhite](https://github.com/ianwhite)) ```ruby User.update_all(status: :blocked) ``` ### bug fix * Rescue MissingAttributeError on attribute writing. (by [@embs](https://github.com/embs)) * Fix presence validation for multiple attributes when the list contains a blank string. (by [@smoriwaki](https://github.com/smoriwaki)) * Replace deprecated alias_method_chain with Module#prepend. (by [@koenpunt](https://github.com/koenpunt) and [@akm](https://github.com/akm)) * Make it compatible with `globalize` gem. (by [@falm](https://github.com/falm)) * Prevent method getter from being called when no default_value is being set. (by [@arjan0307](https://github.com/arjan0307)) ## 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-2.2.2/Gemfile.rails420000644000004100000410000000041213313023144016311 0ustar www-datawww-dataeval_gemfile('Gemfile.global') gem 'minitest', '~> 5.8' gem 'rails', '4.2.8', :require => false gem 'activerecord-jdbcsqlite3-adapter', '~> 1.3.0', platform: :jruby gem 'activerecord-jdbcpostgresql-adapter', '~> 1.3.0', platform: :jruby gem 'mongoid', '~> 5.0' enumerize-2.2.2/.gitignore0000644000004100000410000000035213313023144015532 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-2.2.2/Gemfile.mongo_mapper0000644000004100000410000000040413313023144017515 0ustar www-datawww-dataeval_gemfile('Gemfile.global') gem 'minitest', '~> 5.8' gem 'rails', '4.2.8', :require => false gem 'activerecord-jdbcsqlite3-adapter', '~> 1.3.0', platform: :jruby gem 'activerecord-jdbcpostgresql-adapter', '~> 1.3.0', platform: :jruby gem 'mongo_mapper' enumerize-2.2.2/Gemfile.rails500000644000004100000410000000037213313023144016315 0ustar www-datawww-dataeval_gemfile('Gemfile.global') gem 'minitest', '~> 5.8' gem 'rails', '5.0.6', require: false gem 'activerecord-jdbcsqlite3-adapter', '~> 51.0', platform: :jruby gem 'activerecord-jdbcpostgresql-adapter', '~> 51.0', platform: :jruby gem 'mongoid' enumerize-2.2.2/Rakefile0000644000004100000410000000041013313023144015202 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-2.2.2/Gemfile.rails520000644000004100000410000000057613313023144016325 0ustar www-datawww-dataeval_gemfile('Gemfile.global') gem 'minitest', '~> 5.8' gem 'rails', '5.2.0.rc1', require: false gem 'activerecord-jdbcsqlite3-adapter', github: 'jruby/activerecord-jdbc-adapter', branch: 'master', platform: :jruby gem 'activerecord-jdbcpostgresql-adapter', github: 'jruby/activerecord-jdbc-adapter', branch: 'master', platform: :jruby gem 'mongoid', github: 'mongodb/mongoid' enumerize-2.2.2/lib/0000755000004100000410000000000013313023144014310 5ustar www-datawww-dataenumerize-2.2.2/lib/enumerize/0000755000004100000410000000000013313023144016313 5ustar www-datawww-dataenumerize-2.2.2/lib/enumerize/predicatable.rb0000644000004100000410000000070713313023144021263 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-2.2.2/lib/enumerize/version.rb0000644000004100000410000000011013313023144020315 0ustar www-datawww-data# frozen_string_literal: true module Enumerize VERSION = '2.2.2' end enumerize-2.2.2/lib/enumerize/attribute_map.rb0000644000004100000410000000115513313023144021502 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-2.2.2/lib/enumerize/mongoid.rb0000644000004100000410000000043313313023144020274 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-2.2.2/lib/enumerize/set.rb0000644000004100000410000000263713313023144017443 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-2.2.2/lib/enumerize/attribute.rb0000644000004100000410000001213013313023144020640 0ustar www-datawww-datamodule Enumerize class Attribute attr_reader :klass, :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.reject(&:blank?).map(&:to_s) : values #{name} end RUBY end end end enumerize-2.2.2/lib/enumerize/integrations/0000755000004100000410000000000013313023144021021 5ustar www-datawww-dataenumerize-2.2.2/lib/enumerize/integrations/rails_admin.rb0000644000004100000410000000051213313023144023626 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}].options end RUBY end end end end enumerize-2.2.2/lib/enumerize/integrations/rspec/0000755000004100000410000000000013313023144022135 5ustar www-datawww-dataenumerize-2.2.2/lib/enumerize/integrations/rspec/matcher.rb0000644000004100000410000001100513313023144024102 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.public_send(expected_attr).is_a?(Enumerize::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-2.2.2/lib/enumerize/integrations/rspec.rb0000644000004100000410000000045713313023144022470 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-2.2.2/lib/enumerize/value.rb0000644000004100000410000000172413313023144017760 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 end end def i18n_scopes @attr.i18n_scopes.map { |s| :"#{s}.#{self}" } end end end enumerize-2.2.2/lib/enumerize/base.rb0000644000004100000410000000547713313023144017567 0ustar www-datawww-datamodule Enumerize module Base def self.included(base) base.extend ClassMethods base.singleton_class.prepend ClassMethods::Hook if base.respond_to?(:validate) base.validate :_validate_enumerized_attributes 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 module Hook def inherited(subclass) enumerized_attributes.add_dependant subclass.enumerized_attributes super 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| next if attr.default_value.nil? begin 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 rescue ActiveModel::MissingAttributeError end end end end end enumerize-2.2.2/lib/enumerize/module_attributes.rb0000644000004100000410000000035513313023144022376 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-2.2.2/lib/enumerize/activerecord.rb0000644000004100000410000000605513313023144021320 0ustar www-datawww-datamodule Enumerize module ActiveRecordSupport def enumerize(name, options={}) super _enumerize_module.dependent_eval do if self < ::ActiveRecord::Base include InstanceMethods const_get(:ActiveRecord_Relation).include(RelationMethods) const_get(:ActiveRecord_AssociationRelation).include(RelationMethods) const_get(:ActiveRecord_Associations_CollectionProxy).include(RelationMethods) # 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' unless options[:multiple] decorate_attribute_type(name, :enumerize) do |subtype| Type.new(enumerized_attributes[name], subtype) end end end end end module InstanceMethods # https://github.com/brainspec/enumerize/issues/74 def write_attribute(attr_name, value, *options) 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| # Rescue when column associated to the enum does not exist. begin became.send("#{attr.name}=", send(attr.name)) rescue ActiveModel::MissingAttributeError end end became end end module RelationMethods def update_all(updates) if updates.is_a?(Hash) enumerized_attributes.each do |attr| next if updates[attr.name].blank? || attr.kind_of?(Enumerize::Multiple) enumerize_value = attr.find_value(updates[attr.name]) updates[attr.name] = enumerize_value && enumerize_value.value end end super(updates) end end class Type < ActiveRecord::Type::Value delegate :type, to: :@subtype def initialize(attr, subtype) @attr = attr @subtype = subtype end def serialize(value) v = @attr.find_value(value) (v && v.value) || value end alias type_cast_for_database serialize def deserialize(value) @attr.find_value(value) end alias type_cast_from_database deserialize def as_json(options = nil) {attr: @attr.name, subtype: @subtype}.as_json(options) end def encode_with(coder) coder[:class_name] = @attr.klass.name coder[:attr_name] = @attr.name coder[:subtype] = @subtype end def init_with(coder) initialize( coder[:class_name].constantize.enumerized_attributes[coder[:attr_name]], coder[:subtype] ) end end end end enumerize-2.2.2/lib/enumerize/sequel.rb0000644000004100000410000000350013313023144020134 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-2.2.2/lib/enumerize/scope/0000755000004100000410000000000013313023144017424 5ustar www-datawww-dataenumerize-2.2.2/lib/enumerize/scope/mongoid.rb0000644000004100000410000000165413313023144021413 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-2.2.2/lib/enumerize/scope/activerecord.rb0000644000004100000410000000177713313023144022437 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-2.2.2/lib/enumerize/scope/sequel.rb0000644000004100000410000000213513313023144021250 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-2.2.2/lib/enumerize/hooks/0000755000004100000410000000000013313023144017436 5ustar www-datawww-dataenumerize-2.2.2/lib/enumerize/hooks/uniqueness.rb0000644000004100000410000000100113313023144022152 0ustar www-datawww-datarequire 'active_support/concern' module Enumerize module Hooks module UniquenessValidator def validate_each(record, name, value) klass = record.to_model.class if klass.respond_to?(:enumerized_attributes) && (attr = klass.enumerized_attributes[name]) value = attr.find_value(value).try(:value) end super(record, name, value) end end end end ::ActiveRecord::Validations::UniquenessValidator.send :prepend, Enumerize::Hooks::UniquenessValidator enumerize-2.2.2/lib/enumerize/hooks/simple_form.rb0000644000004100000410000000214413313023144022300 0ustar www-datawww-datarequire 'active_support/concern' module Enumerize module Hooks module SimpleFormBuilderExtension def input(attribute_name, options={}, &block) add_input_options_for_enumerized_attribute(attribute_name, options) super(attribute_name, options, &block) end def input_field(attribute_name, options={}) add_input_options_for_enumerized_attribute(attribute_name, options) super(attribute_name, options) end private def add_input_options_for_enumerized_attribute(attribute_name, options) enumerized_object = convert_to_model(object) klass = enumerized_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 :prepend, Enumerize::Hooks::SimpleFormBuilderExtension enumerize-2.2.2/lib/enumerize/hooks/formtastic.rb0000644000004100000410000000134113313023144022135 0ustar www-datawww-datarequire 'active_support/concern' module Enumerize module Hooks module FormtasticFormBuilderExtension def input(method, options={}) enumerized_object = convert_to_model(object) klass = enumerized_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 super(method, options) end end end end ::Formtastic::FormBuilder.send :prepend, Enumerize::Hooks::FormtasticFormBuilderExtension enumerize-2.2.2/lib/enumerize/hooks/sequel_dataset.rb0000644000004100000410000000045413313023144022771 0ustar www-datawww-datamodule Enumerize module Hooks module SequelDataset def literal_append(sql, v) if v.is_a?(Enumerize::Value) super(sql, v.value) else super(sql, v) end end end end end ::Sequel::Dataset.send :prepend, Enumerize::Hooks::SequelDataset enumerize-2.2.2/lib/enumerize/predicates.rb0000644000004100000410000000314513313023144020766 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-2.2.2/lib/enumerize/module.rb0000644000004100000410000000106113313023144020123 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-2.2.2/lib/enumerize/activemodel.rb0000644000004100000410000000177613313023144021147 0ustar www-datawww-datamodule Enumerize module ActiveModelAttributesSupport def enumerize(name, options={}) super _enumerize_module.dependent_eval do if self.included_modules.include? ::ActiveModel::Attributes include InstanceMethods attribute name, Enumerize::ActiveModelAttributesSupport::Type.new(enumerized_attributes[name]) end end end module InstanceMethods # https://github.com/brainspec/enumerize/issues/74 def write_attribute(attr_name, value, *options) if self.class.enumerized_attributes[attr_name] _enumerized_values_for_validation[attr_name.to_s] = value end super end end class Type < ActiveModel::Type::Value def type :enumerize end def initialize(attr) @attr = attr end def serialize(value) v = @attr.find_value(value) v && v.value end def deserialize(value) @attr.find_value(value) end end end end enumerize-2.2.2/lib/enumerize.rb0000644000004100000410000000445613313023144016651 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 :ActiveModelAttributesSupport, 'enumerize/activemodel' 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?(::ActiveModel::Attributes) base.extend Enumerize::ActiveModelAttributesSupport end 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-2.2.2/lib/sequel/0000755000004100000410000000000013313023144015606 5ustar www-datawww-dataenumerize-2.2.2/lib/sequel/plugins/0000755000004100000410000000000013313023144017267 5ustar www-datawww-dataenumerize-2.2.2/lib/sequel/plugins/enumerize.rb0000644000004100000410000000055213313023144021621 0ustar www-datawww-datamodule Sequel module Plugins module Enumerize # Depend on the def_dataset_method plugin def self.apply(model) model.plugin(:def_dataset_method) unless model.respond_to?(:def_dataset_method) end module InstanceMethods def self.included(base) base.extend ::Enumerize end end end end end enumerize-2.2.2/enumerize.gemspec0000644000004100000410000000162513313023144017116 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.licenses = ['MIT'] 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-2.2.2/Gemfile.global0000644000004100000410000000055413313023144016300 0ustar www-datawww-datasource 'https://rubygems.org' gemspec gem 'rake' gem 'rspec', :require => false gem 'sqlite3', :platform => [:ruby, :mswin, :mingw] gem 'pg', '~> 0.21.0', :platform => [:ruby, :mswin, :mingw] 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-2.2.2/Gemfile0000644000004100000410000000037213313023144015037 0ustar www-datawww-dataeval_gemfile('Gemfile.global') gem 'minitest', '~> 5.8' gem 'rails', '5.1.4', require: false gem 'activerecord-jdbcsqlite3-adapter', '~> 51.0', platform: :jruby gem 'activerecord-jdbcpostgresql-adapter', '~> 51.0', platform: :jruby gem 'mongoid' enumerize-2.2.2/MIT-LICENSE0000644000004100000410000000205213313023144015175 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.