Skip to content

Commit c868073

Browse files
committed
basic version that works with activemodel
1 parent 8e52278 commit c868073

10 files changed

+181
-3
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ spec/reports
1515
test/tmp
1616
test/version_tmp
1717
tmp
18+
vendor/bundle

Gemfile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
source 'https://rubygems.org'
22

3-
# Specify your gem's dependencies in enumerize.gemspec
43
gemspec
4+
5+
gem 'minitest', '~> 2.11.0'

Rakefile

+9
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,11 @@
11
#!/usr/bin/env rake
22
require "bundler/gem_tasks"
3+
4+
require 'rake/testtask'
5+
Rake::TestTask.new do |t|
6+
t.libs << 'test'
7+
t.pattern = 'test/*_test.rb'
8+
t.verbose = true
9+
end
10+
11+
task :default => :test

enumerize.gemspec

+2
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ Gem::Specification.new do |gem|
1414
gem.name = "enumerize"
1515
gem.require_paths = ["lib"]
1616
gem.version = Enumerize::VERSION
17+
18+
gem.add_dependency('activesupport', '>= 3.1.3')
1719
end

lib/enumerize.rb

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1-
require "enumerize/version"
1+
require 'active_support/concern'
2+
require 'i18n'
3+
require 'enumerize/version'
24

35
module Enumerize
4-
# Your code goes here...
6+
autoload :Attribute, 'enumerize/attribute'
7+
autoload :Value, 'enumerize/value'
8+
9+
extend ActiveSupport::Concern
10+
11+
module ClassMethods
12+
def enumerize(*args, &block)
13+
Attribute.new(self, *args).attach!
14+
end
15+
end
516
end

lib/enumerize/attribute.rb

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module Enumerize
2+
class Attribute
3+
attr_reader :name, :values
4+
5+
def initialize(klass, name, options={})
6+
raise ArgumentError, ':in option is required' unless options[:in]
7+
8+
@klass = klass
9+
@name = name
10+
@values = Array(options[:in]).map { |v| Value.new(self, v) }
11+
end
12+
13+
def attach!
14+
attr = self
15+
@klass.singleton_class.class_eval do
16+
define_method("#{attr.name}") { attr }
17+
end
18+
19+
@klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
20+
attr_reader :#{name}
21+
22+
def #{name}_text
23+
#{name}.text
24+
end
25+
26+
def #{name}=(new_value)
27+
@#{name} = self.class.#{name}.find_value(new_value)
28+
end
29+
RUBY
30+
end
31+
32+
def find_value(value)
33+
value = value.to_s
34+
values.find { |v| v == value }
35+
end
36+
37+
def i18n_suffix
38+
@klass.model_name.i18n_key if @klass.respond_to?(:model_name)
39+
end
40+
41+
def options
42+
values.map { |v| [v.text, v.to_s] }
43+
end
44+
end
45+
end

lib/enumerize/value.rb

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module Enumerize
2+
class Value < String
3+
def initialize(attr, value)
4+
singleton_class.class_eval do
5+
define_method(:attr) { attr }
6+
end
7+
8+
super(value.to_s)
9+
freeze
10+
end
11+
12+
def text
13+
i18n_keys = ['']
14+
i18n_keys.unshift "#{attr.i18n_suffix}." if attr.i18n_suffix
15+
i18n_keys.map! { |k| :"enumerize.#{k}#{attr.name}.#{self}" }
16+
I18n.t(i18n_keys.shift, :default => i18n_keys)
17+
end
18+
19+
if YAML::ENGINE.yamler == 'syck'
20+
def to_yaml(opts={})
21+
to_s.to_yaml(opts)
22+
end
23+
end
24+
end
25+
end

test/basic_test.rb

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
require 'test_helper'
2+
require 'syck'
3+
4+
describe Enumerize do
5+
let(:klass) do
6+
Class.new do
7+
include Enumerize
8+
end
9+
end
10+
11+
let(:object) { klass.new }
12+
13+
it 'defines method that returns nil' do
14+
klass.enumerize(:foo, :in => [:a, :b])
15+
object.foo.must_equal nil
16+
end
17+
18+
it 'defines setter method' do
19+
klass.enumerize(:foo, :in => [:a, :b])
20+
object.foo = :a
21+
object.foo.must_equal 'a'
22+
end
23+
24+
it 'returns translation' do
25+
I18n.backend.store_translations(:en, :enumerize => {:foo => {:a => 'a text'}})
26+
klass.enumerize(:foo, :in => [:a, :b])
27+
object.foo = :a
28+
object.foo.text.must_equal 'a text'
29+
object.foo_text.must_equal 'a text'
30+
end
31+
32+
it 'scopes translation by i18 key' do
33+
I18n.backend.store_translations(:en, :enumerize => {:example_class => {:foo => {:a => 'a text scoped'}}})
34+
def klass.model_name
35+
name = "ExampleClass"
36+
def name.i18n_key
37+
'example_class'
38+
end
39+
40+
name
41+
end
42+
klass.enumerize(:foo, :in => [:a, :b])
43+
object.foo = :a
44+
object.foo.text.must_equal 'a text scoped'
45+
object.foo_text.must_equal 'a text scoped'
46+
end
47+
48+
it 'returns options for select' do
49+
I18n.backend.store_translations(:en, :enumerize => {:foo => {:a => 'a text', :b => 'b text'}})
50+
klass.enumerize(:foo, :in => [:a, :b])
51+
klass.foo.options.must_equal [['a text', 'a'], ['b text', 'b']]
52+
end
53+
54+
it 'dumpes value to yaml using' do
55+
klass.enumerize(:foo, :in => [:a, :b])
56+
object.foo = :a
57+
YAML.dump(object.foo).must_equal YAML.dump('a')
58+
end
59+
end

test/test_helper.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require 'minitest/autorun'
2+
require 'minitest/spec'
3+
4+
$VERBOSE=true
5+
YAML::ENGINE.yamler = ENV['YAMLER'] if ENV['YAMLER']
6+
7+
require 'enumerize'

test/value_test.rb

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
require 'test_helper'
2+
require 'yaml'
3+
4+
describe Enumerize::Value do
5+
let(:value) { value = Enumerize::Value.new(nil, 'test_value') }
6+
7+
it 'is a string' do
8+
value.must_be_kind_of String
9+
end
10+
11+
it 'is compared to string' do
12+
value.must_be :==, 'test_value'
13+
end
14+
15+
it 'is frozen' do
16+
value.must_be :frozen?
17+
end
18+
end

0 commit comments

Comments
 (0)