enumattr 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in enumattr.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'rspec'
8
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 aisuii
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # Enumattr
2
+
3
+ * manage constants by enum like object
4
+ * simplify [SelectableAttr](https://github.com/akm/selectable_attr)
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'enumattr'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install enumattr
19
+
20
+ ## Usage
21
+
22
+ ### defining
23
+
24
+ * `include Enumattr::Base` and declare `enum_attr_for some_attribute do ... end`
25
+ * `enum :symbol, value` in block
26
+
27
+
28
+ <pre>
29
+ class User
30
+ include Enumattr::Base
31
+
32
+ attr_accessor :status
33
+
34
+ enum_attr_for :status do
35
+ enum :active, 1
36
+ enum :suspend, 2
37
+ enum :deleted, 3
38
+ end
39
+
40
+ def initialize(status)
41
+ @status = status
42
+ end
43
+ end
44
+ </pre>
45
+
46
+ ### defined methods
47
+
48
+ #### class methods
49
+
50
+ * `SomeClass.#{some_attribute}_enums` return enum set
51
+ * `SomeClass.#{some_attribute}_keys` return key set
52
+ * `SomeClass.#{some_attribute}_values` return value set
53
+
54
+ <pre>
55
+ User.status_enums
56
+ #=&gt; #&lt;Set: {#&lt;Enumattr::Enum:0x8a8d13c @key=:active, @value=1&gt;, #&lt;Enumattr::Enum:0x8a8d100 @key=:suspend, @value=2&gt;, #&lt;Enumattr::Enum:0x8a8d0ec @key=:deleted, @value=3&gt;}&gt;
57
+
58
+ User.status_keys
59
+ #=&gt; #&lt;Set: {:active, :suspend, :deleted}&gt;
60
+
61
+ User.status_values
62
+ #=&gt; #&lt;Set: {1, 2, 3}&gt;
63
+ </pre>
64
+
65
+ * `SomeClass.#{some_attribute}_enum_by_key(:symbol)` return an enum
66
+ * `SomeClass.#{some_attribute}_value_by_key(:symbol)` return a value
67
+
68
+ <pre>
69
+ User.status_enum_by_key :active
70
+ #=&gt; #&lt;Enumattr::Enum:0x8a8d13c @key=:active, @value=1&gt;
71
+
72
+ User.status_enum_by_key :suspend
73
+ #=&gt; #&lt;Enumattr::Enum:0x8a8d100 @key=:suspend, @value=2&gt;
74
+
75
+ User.status_enum_by_key :dummy
76
+ #=&gt; nil
77
+
78
+ User.status_value_by_key :active
79
+ #=&gt; 1
80
+
81
+ User.status_value_by_key :suspend
82
+ #=&gt; 2
83
+
84
+ User.status_value_by_key :dummy
85
+ #=&gt; nil
86
+ </pre>
87
+
88
+ #### instance methods
89
+
90
+ * alias `#{some_attribute}_value` `some_attribute`
91
+ * `#{some_attribute}_key` return symbol
92
+ * `#{some_attribute}_enum` return enum
93
+
94
+ <pre>
95
+ user = User.new(1)
96
+ #=&gt; #&lt;User:0x8e17dac @status=1&gt;
97
+
98
+ user.status
99
+ #=&gt; 1
100
+
101
+ user.status_value # alias
102
+ #=&gt; 1
103
+
104
+ user.status_key
105
+ #=&gt; :active
106
+
107
+ user.status_enum
108
+ #=&gt; #&lt;Enumattr::Enum:0x8de2e68 @key=:active, @value=1&gt;
109
+ </pre>
110
+
111
+
112
+ * define query method
113
+ * `#{some_attribute}_#{some_symbol}?` return bool
114
+
115
+ <pre>
116
+ user.status_active?
117
+ #=&gt; true
118
+
119
+ user.status_suspend?
120
+ #=&gt; false
121
+
122
+ user.status_deleted?
123
+ #=&gt; false
124
+
125
+ user.status_dummy?
126
+ NoMethodError: undefined method `status_dummy?' for #&lt;User:0x8e17dac @status=1&gt;
127
+ </pre>
128
+
129
+
130
+ ## Contributing
131
+
132
+ 1. Fork it
133
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
134
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
135
+ 4. Push to the branch (`git push origin my-new-feature`)
136
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+
5
+ task :default => :spec
6
+
7
+ desc "Run all specs in spec directory"
8
+ RSpec::Core::RakeTask.new(:spec)
data/enumattr.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/enumattr/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["aisuii"]
6
+ gem.email = ["aisuiiaisuii@gmail.com"]
7
+ gem.description = %q{simple enum}
8
+ gem.summary = %q{manage constants by enum like object}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "enumattr"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Enumattr::VERSION
17
+ end
data/examples/user.rb ADDED
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ class User
4
+ include Enumattr::Base
5
+
6
+ attr_accessor :status
7
+
8
+ enum_attr_for :status do
9
+ enum :active, 1
10
+ enum :suspend, 2
11
+ enum :deleted, 3
12
+ end
13
+
14
+ def initialize(status)
15
+ @status = status
16
+ end
17
+ end
@@ -0,0 +1,82 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Enumattr
4
+ module Base
5
+ def self.included(klass)
6
+ klass.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ private
11
+ def enum_attr_for(enum_attr_name, &block)
12
+ enum_attrs[enum_attr_name] = Enums.new(&block)
13
+ define_class_methods enum_attr_name
14
+ define_instance_methods enum_attr_name
15
+ define_instance_query_methods enum_attr_name
16
+ end
17
+
18
+ def enum_attrs
19
+ @enum_attrs ||= {}
20
+ end
21
+
22
+ def define_class_methods(enum_attr_name)
23
+ enums = enum_attrs[enum_attr_name]
24
+ method_prefix = "#{enum_attr_name}_"
25
+
26
+ mod = Module.new do
27
+ define_method("#{method_prefix}enums") do
28
+ enums.enums
29
+ end
30
+
31
+ define_method("#{method_prefix}keys") do
32
+ enums.keys
33
+ end
34
+
35
+ define_method("#{method_prefix}values") do
36
+ enums.values
37
+ end
38
+
39
+ define_method("#{method_prefix}enum_by_key") do |key|
40
+ enums.enum_by_key(key)
41
+ end
42
+
43
+ define_method("#{method_prefix}value_by_key") do |key|
44
+ enum = enums.enum_by_key(key)
45
+ enum && enum.value
46
+ end
47
+ end
48
+
49
+ extend mod
50
+ end
51
+
52
+ def define_instance_methods(enum_attr_name)
53
+ enums = enum_attrs[enum_attr_name]
54
+ method_prefix = "#{enum_attr_name}_"
55
+
56
+ define_method("#{method_prefix}enum") do
57
+ value = __send__ enum_attr_name
58
+ enums.enum_by_value(value)
59
+ end
60
+
61
+ define_method("#{method_prefix}key") do
62
+ enum = __send__ "#{method_prefix}enum"
63
+ enum.key
64
+ end
65
+
66
+ alias_method :"#{method_prefix}value", enum_attr_name
67
+ end
68
+
69
+ def define_instance_query_methods(enum_attr_name)
70
+ enums = enum_attrs[enum_attr_name]
71
+ method_prefix = "#{enum_attr_name}_"
72
+
73
+ enums.enums.each do |enum|
74
+ define_method("#{method_prefix}#{enum.key}?") do
75
+ value = __send__ enum_attr_name
76
+ value == enum.value
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Enumattr
4
+ class Enum
5
+ attr_reader :key, :value
6
+
7
+ def initialize(key, value)
8
+ @key = key.to_sym
9
+ @value = value
10
+ end
11
+
12
+ def hash
13
+ @key.hash
14
+ end
15
+
16
+ def eql?(other)
17
+ @key == other.key
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'set'
3
+
4
+ module Enumattr
5
+ class Enums
6
+ def initialize(&block)
7
+ @set = Set.new
8
+ instance_eval(&block)
9
+ freeze
10
+ end
11
+
12
+ def enums
13
+ @set.clone
14
+ end
15
+
16
+ def keys
17
+ Set.new @set.map(&:key)
18
+ end
19
+
20
+ def values
21
+ Set.new @set.map(&:value)
22
+ end
23
+
24
+ def enum_by_key(key)
25
+ @set.find{|enum| enum.key == key }
26
+ end
27
+
28
+ def enum_by_value(value)
29
+ @set.find{|enum| enum.value == value }
30
+ end
31
+
32
+ private
33
+ def enum(key, value)
34
+ @set.add Enum.new(key, value)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module Enumattr
2
+ VERSION = "0.0.1"
3
+ end
data/lib/enumattr.rb ADDED
@@ -0,0 +1,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require "enumattr/version"
3
+
4
+ module Enumattr
5
+ autoload :Base, 'enumattr/base'
6
+ autoload :Enums, 'enumattr/enums'
7
+ autoload :Enum, 'enumattr/enum'
8
+ end
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe Enumattr::Enum do
5
+ let(:one_enum) { Enumattr::Enum.new(:my_key, 1) }
6
+ let(:same_key_enum) { Enumattr::Enum.new(:my_key, 2) }
7
+ let(:another_enum) { Enumattr::Enum.new(:another, 3) }
8
+
9
+ describe "getters" do
10
+ subject { one_enum }
11
+ its(:key) { should == :my_key }
12
+ its(:value) { should == 1 }
13
+ end
14
+
15
+ describe "in hash key" do
16
+ context "when hash has same key enum as hash key" do
17
+ subject do
18
+ hash = {}
19
+ hash[one_enum] = 1
20
+ hash[same_key_enum] = 2 # only value overrided
21
+ hash[another_enum] = 3
22
+ hash
23
+ end
24
+
25
+ its(:keys) { should include one_enum }
26
+ its(:keys) { should_not include same_key_enum }
27
+ its(:keys) { should include another_enum }
28
+
29
+ its(:values) { should_not include 1 }
30
+ its(:values) { should include 2 }
31
+ its(:values) { should include 3 }
32
+
33
+ it "should have 2 items" do
34
+ subject.should have(2).items
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,84 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe Enumattr::Enums do
5
+ let(:enums) do
6
+ Enumattr::Enums.new do
7
+ enum :key1, 1
8
+ enum :key2, 2
9
+ enum :key3, 3
10
+ end
11
+ end
12
+
13
+ describe "#enums" do
14
+ subject { enums.enums }
15
+ it { should be_a Set }
16
+ it { should have(3).items }
17
+ it "should have Enumattr::Enum instances" do
18
+ should satisfy { |enums|
19
+ enums.all?{|item| item.is_a? Enumattr::Enum }
20
+ }
21
+ end
22
+ end
23
+
24
+ describe "#keys" do
25
+ subject { enums.keys }
26
+ it { should be_a Set }
27
+ it { should have(3).items }
28
+ it "should have Symbol instances" do
29
+ should satisfy { |keys|
30
+ keys.all?{|item| item.is_a? Symbol }
31
+ }
32
+ end
33
+ end
34
+
35
+ describe "#values" do
36
+ subject { enums.values }
37
+ it { should be_a Set }
38
+ it { should have(3).items }
39
+ it "should have Numeric instances" do
40
+ should satisfy { |values|
41
+ values.all?{|item| item.is_a? Numeric }
42
+ }
43
+ end
44
+ end
45
+
46
+ describe "find methods" do
47
+ shared_examples "#enum_by_foo(foo) each items" do
48
+ it { should be_a Enumattr::Enum }
49
+ its(:key) { should == expects[:key] }
50
+ its(:value) { should == expects[:value] }
51
+ end
52
+
53
+ samples = [
54
+ {:key => :key1, :value => 1},
55
+ {:key => :key2, :value => 2},
56
+ {:key => :key3, :value => 3},
57
+ ]
58
+
59
+ describe "#enum_by_key(key)" do
60
+ subject { enums.enum_by_key(key) }
61
+ samples.each do |sample|
62
+ context "key: #{sample[:key]}" do
63
+ let(:key) { sample[:key] }
64
+ let(:expects) { sample }
65
+
66
+ include_examples "#enum_by_foo(foo) each items"
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "#enum_by_value(value)" do
72
+ subject { enums.enum_by_value(value) }
73
+
74
+ samples.each do |sample|
75
+ context "value: #{sample[:value]}" do
76
+ let(:value) { sample[:value] }
77
+ let(:expects) { sample }
78
+
79
+ include_examples "#enum_by_foo(foo) each items"
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,116 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'user'
4
+
5
+ describe User do
6
+ describe "class methods" do
7
+ describe '.status_enums as #{enum_attr_name}_enums' do
8
+ subject { described_class.status_enums }
9
+
10
+ it { should be_a Set }
11
+ it { should have(3).items }
12
+ it "should have Enum instances" do
13
+ should satisfy { |enums|
14
+ enums.all?{|item| item.is_a? Enumattr::Enum }
15
+ }
16
+ end
17
+ end
18
+
19
+ describe '.status_keys as #{enum_attr_name}_keys' do
20
+ subject { described_class.status_keys }
21
+
22
+ it { should be_a Set }
23
+ it { should have(3).items }
24
+ it "should have Symbol instances" do
25
+ should satisfy { |keys|
26
+ keys.all?{|item| item.is_a? Symbol }
27
+ }
28
+ end
29
+ end
30
+
31
+ describe '.status_values as #{enum_attr_name}_values' do
32
+ subject { described_class.status_values }
33
+
34
+ it { should be_a Set }
35
+ it { should have(3).items }
36
+ it "should have Numeric instances" do
37
+ should satisfy { |values|
38
+ values.all?{|item| item.is_a? Numeric }
39
+ }
40
+ end
41
+ end
42
+
43
+ describe '.status_enum_by_key as #{enum_attr_name}_enum_by_key' do
44
+ subject { described_class.status_enum_by_key(:active) }
45
+
46
+ it { should be_a Enumattr::Enum }
47
+ its(:key) { should == :active }
48
+ its(:value) { should == 1 }
49
+ end
50
+
51
+ describe '.status_value_by_key as #{enum_attr_name}_value_by_key' do
52
+ context "present key" do
53
+ subject { described_class.status_value_by_key(:active) }
54
+
55
+ it { should == 1 }
56
+ end
57
+
58
+ context "not present key" do
59
+ subject { described_class.status_value_by_key(:not_present_key) }
60
+
61
+ it { should be_nil }
62
+ end
63
+ end
64
+ end
65
+
66
+
67
+ describe "instance methods" do
68
+ let(:user) { User.new(1) }
69
+
70
+ describe "#status" do
71
+ subject { user.status }
72
+
73
+ it { should == 1 }
74
+ end
75
+
76
+ describe '#status_enum as #{enum_attr_name}_enum' do
77
+ subject { user.status_enum }
78
+
79
+ it { should be_a Enumattr::Enum }
80
+ its(:key) { should == :active }
81
+ its(:value) { should == 1 }
82
+ end
83
+
84
+ describe '#status_key as #{enum_attr_name}_key' do
85
+ subject { user.status_key }
86
+
87
+ it { should be_a Symbol }
88
+ it { should == :active }
89
+ end
90
+
91
+ describe '#status_value as #{enum_attr_name}_value' do
92
+ subject { user.status_value }
93
+
94
+ it { should be_a Numeric }
95
+ it { should == 1 }
96
+ end
97
+
98
+ describe '#status_active? as #{enum_attr_name}_#{status_key}?' do
99
+ subject { user.status_active? }
100
+
101
+ it { should be_true }
102
+ end
103
+
104
+ describe '#status_suspend? as #{enum_attr_name}_#{other_status_key}?' do
105
+ subject { user.status_suspend? }
106
+
107
+ it { should be_false }
108
+ end
109
+
110
+ describe '#status_deleted? as #{enum_attr_name}_#{other_status_key}?' do
111
+ subject { user.status_deleted? }
112
+
113
+ it { should be_false }
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,17 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'examples'))
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+
5
+ require 'enumattr'
6
+
7
+ # This file was generated by the `rspec --init` command. Conventionally, all
8
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
9
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
10
+ # loaded once.
11
+ #
12
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
13
+ RSpec.configure do |config|
14
+ config.treat_symbols_as_metadata_keys_with_true_values = true
15
+ config.run_all_when_everything_filtered = true
16
+ config.filter_run :focus
17
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enumattr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - aisuii
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-27 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: simple enum
15
+ email:
16
+ - aisuiiaisuii@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - .rspec
23
+ - Gemfile
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - enumattr.gemspec
28
+ - examples/user.rb
29
+ - lib/enumattr.rb
30
+ - lib/enumattr/base.rb
31
+ - lib/enumattr/enum.rb
32
+ - lib/enumattr/enums.rb
33
+ - lib/enumattr/version.rb
34
+ - spec/enumattr/enum_spec.rb
35
+ - spec/enumattr/enums_spec.rb
36
+ - spec/enumattr/included_spec.rb
37
+ - spec/spec_helper.rb
38
+ homepage: ''
39
+ licenses: []
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 1.8.21
59
+ signing_key:
60
+ specification_version: 3
61
+ summary: manage constants by enum like object
62
+ test_files:
63
+ - spec/enumattr/enum_spec.rb
64
+ - spec/enumattr/enums_spec.rb
65
+ - spec/enumattr/included_spec.rb
66
+ - spec/spec_helper.rb