ordinary 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1bff706645249ee9b180396fa8dbd97c60de1a32
4
+ data.tar.gz: bef17919f5c25b578de54234e9b79d7611902a5b
5
+ SHA512:
6
+ metadata.gz: c59a7bc904f9b0bcaa687dec7fa6b779cc2b257e615179086ad6d433bd9b320e296a1330950b2261052c10b7ee4b348c9a6ca3ca648d97e2a0ff3579df2db6f0
7
+ data.tar.gz: 544ffa6acca8a2412426b7f4c5dfc8d91a4c03437a4e66fe6be70a5735f049486ec7150a3f8ca25d1d0db5204f1fe23d6a9dbce7cacaaea85e9f3a3a9d47c020
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/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ordinary.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Takahiro Kondo
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,232 @@
1
+ Ordinary
2
+ ========
3
+
4
+ Normalizer for any model
5
+
6
+ Installation
7
+ ------------
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'ordinary'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install ordinary
20
+
21
+ Usage
22
+ -----
23
+
24
+ First, you will include `Ordinary` to the model of the object. Following is an example of using ActiveModel.
25
+
26
+ ```ruby
27
+ require 'ordinary'
28
+
29
+ class Person
30
+ include ActiveModel::Model
31
+ include Ordinary
32
+
33
+ attr_accessor :name
34
+
35
+ normalizes :name do |value|
36
+ value.strip.squeeze(' ')
37
+ end
38
+ end
39
+ ```
40
+
41
+ You can get the normalized value with `#normalize_attribute` or `#normalized_ATTR_NAME`.
42
+
43
+ ```ruby
44
+ person = Person.new(:name => ' Koyomi Araragi ')
45
+ puts person.name # => " Koyomi Araragi "
46
+ puts person.normalize_attribute(:name) # => "Koyomi Araragi"
47
+ puts person.normalized_name # => "Koyomi Araragi"
48
+ ```
49
+
50
+ And you can get the normalized model with `#normalize`.
51
+
52
+ ```ruby
53
+ normalized_person = person.normalize
54
+ puts normalized_person.normalized? # => true
55
+ puts normalized_person.name # => "Koyomi Araragi"
56
+ ```
57
+
58
+ Off course, it doesn't affect the original model.
59
+
60
+ ```ruby
61
+ puts person.normalized? # => false
62
+ puts person.name # => " Koyomi Araragi "
63
+ ```
64
+
65
+ However, if you use `#normalize!`, the original model will also be normalized.
66
+
67
+ How to define normalization
68
+ ---------------------------
69
+
70
+ How to define normalization is from where you include `Ordinary`.
71
+
72
+ ```ruby
73
+ require 'ordinary'
74
+
75
+ class AnyModel
76
+ include Ordinary
77
+
78
+ # define normalization...
79
+ end
80
+ ```
81
+
82
+ Incidentally, in order to enable to read and write to a target attirbute, you must define `#ATTR_NAME` and `#ATTR_NAME=`.
83
+
84
+ Normalization defines with `.normalizes`.
85
+
86
+ ```ruby
87
+ class AnyModel
88
+ # ...
89
+
90
+ attr_accessor :attr1, :attr2
91
+
92
+ normalizes :attr1, :attr2 do |value|
93
+ # process for normalization
94
+ end
95
+
96
+ # ...
97
+ end
98
+ ```
99
+
100
+ You can define in a variety of ways.
101
+
102
+ ```ruby
103
+ class AnyModel
104
+ # ...
105
+
106
+ attr_accessor :attr1, :attr2
107
+
108
+ # specify process with a block
109
+ normalizes :attr1 do |value|
110
+ "#{value}_1"
111
+ end
112
+
113
+ # if define normalization to same attribute, normalization runs in the order
114
+ # in which you defined
115
+ normalizes :attr1 do |value|
116
+ "#{value}_2"
117
+ end
118
+
119
+ # If specify Proc to last argument, define composed unit in the Proc as
120
+ # process of normalization (units described later)
121
+ normalizes :attr2, lambda { lstrip | rstrip }
122
+
123
+ # also specify both block and Proc (position of process of block decides by
124
+ # block unit)
125
+ normalizes :attr2, lambda { block | squeeze(' ') } do |value|
126
+ "#{value}_3"
127
+ end
128
+
129
+ # also specify options
130
+ normalizes :attr2, if: lambda { !attr2.nil? }, with: lambda { block | at(0) } do |value|
131
+ (value.empty? or %w(0 false f).include?(value)) ? 'false' : 'true'
132
+ end
133
+
134
+ # ...
135
+ end
136
+ ```
137
+
138
+ How to create an units module
139
+ -----------------------------
140
+
141
+ You can create a module bundled some units. You'll use `Ordinary::Module` to do so.
142
+
143
+ ```ruby
144
+ require 'ordinary/module'
145
+
146
+ module AnyModule
147
+ extend Ordinary::Module
148
+
149
+ # define the module...
150
+ end
151
+ ```
152
+
153
+ And you can register to use the module with `Ordinary.register`.
154
+
155
+ ```ruby
156
+ require 'ordinary'
157
+
158
+ Ordinary.register(AnyModule)
159
+ ```
160
+
161
+ ### Define an unit
162
+
163
+ An unit can define with `.unit` in the module.
164
+
165
+ ```ruby
166
+ module AnyModule
167
+ # ...
168
+
169
+ unit :some_unit do |value|
170
+ # process for the unit...
171
+ end
172
+
173
+ # ...
174
+ end
175
+ ```
176
+
177
+ You can define in a variety of ways.
178
+
179
+ ```ruby
180
+ module AnyModule
181
+ # ...
182
+
183
+ # specify process with a block
184
+ unit :lstrip do |value|
185
+ value.lstrip
186
+ end
187
+
188
+ # okay as the argument
189
+ unit :rstrip, lambda { |value| value.rstrip }
190
+
191
+ # actually, above examples are okay at follows
192
+ unit :lstrip
193
+
194
+ # as aliasing
195
+ unit :ltrim, :lstrip
196
+
197
+ # by the way, units are defined as module functions, you can also see
198
+ p lstrip # => #<Ordinary::Unit:0x0x007ff6ec8e7610 AnyModule#lstrip>
199
+
200
+ # and compose units by #| (or #>>, #<<)
201
+ unit :strip, lstrip | rstrip
202
+
203
+ # ...
204
+ end
205
+ ```
206
+
207
+ ### Define a dependency
208
+
209
+ If exist dependencies to some libraries to units in the module, will resolve with `.requires`.
210
+
211
+ ```ruby
212
+ module AnyModule
213
+ # ...
214
+
215
+ requires 'nkf'
216
+
217
+ unit :to_half do |value|
218
+ NKF.nkf('-wWZ1', value)
219
+ end
220
+
221
+ # ...
222
+ end
223
+ ```
224
+
225
+ Contributing
226
+ ------------
227
+
228
+ 1. Fork it
229
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
230
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
231
+ 4. Push to the branch (`git push origin my-new-feature`)
232
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/lib/ordinary.rb ADDED
@@ -0,0 +1,160 @@
1
+ require 'ordinary/version'
2
+ require 'ordinary/builder'
3
+ require 'ordinary/normalizer'
4
+ require 'ordinary/module'
5
+
6
+ module Ordinary
7
+
8
+ # Normalize an attribute.
9
+ #
10
+ # @param [Symbol] attr_name an attribute to normalize
11
+ # @param [Symbol] context normalization context. defaults to nil
12
+ # @return [Object] the normalized attribute
13
+ def normalize_attribute(attr_name, context = nil)
14
+ value = __send__(attr_name)
15
+
16
+ unless value.nil?
17
+ self.class.normalizers[attr_name.to_sym].each do |normalizer|
18
+ next unless normalizer.coming_under?(self)
19
+ next unless normalizer.run_at?(context)
20
+ value = normalizer.normalize(value)
21
+ end
22
+ end
23
+
24
+ value
25
+ end
26
+
27
+ # Normalize all attributes and return the normalized object.
28
+ #
29
+ # @param [Symbol] context normalization context. defaults to nil
30
+ # @return [Object] the normalized object
31
+ def normalize(context = nil)
32
+ clone.normalize!(context)
33
+ end
34
+
35
+ # Normalize all attributes distructively.
36
+ #
37
+ # @param [Symbol] context normalization context. defaults to nil
38
+ # @return [Object] self
39
+ def normalize!(context = nil)
40
+ unless normalized?(context)
41
+ self.class.normalizers.keys.each do |attr_name|
42
+ __send__(:"#{attr_name}=", normalize_attribute(attr_name, context))
43
+ end
44
+
45
+ @normalization_context = context
46
+ end
47
+
48
+ self
49
+ end
50
+
51
+ # Determine if self is normalized.
52
+ #
53
+ # @param [Symbol] context normalization context. defaults to nil
54
+ # @return whether self is normalized
55
+ def normalized?(context = nil)
56
+ return false unless instance_variable_defined?(:@normalization_context)
57
+ @normalization_context.nil? or (@normalization_context == context)
58
+ end
59
+
60
+ # Register modules to the context of building.
61
+ #
62
+ # @scope class
63
+ # @param [Array<Ordinary::Module>] modules modules to register
64
+ def self.register(*modules)
65
+ Builder::Context.register(*modules)
66
+ end
67
+
68
+ # Unregister modules from the context of building.
69
+ #
70
+ # @scope class
71
+ # @param [Array<Ordinary::Module>] modules modules to unregister
72
+ def self.unregister(modules)
73
+ Builder::Context.unregister(*modules)
74
+ end
75
+
76
+ def self.included(klass)
77
+ klass.extend(ClassMethods)
78
+
79
+ if defined?(ActiveModel::Validations) and klass.include?(ActiveModel::Validations)
80
+ method = klass.instance_method(:run_validations!)
81
+
82
+ klass.__send__(:define_method, :run_validations!) do
83
+ context = validation_context
84
+ normalized?(context) ? method.bind(self).call : normalize(context).valid?(context)
85
+ end
86
+ end
87
+
88
+ if defined?(ActiveRecord::Base) and klass.include?(ActiveRecord::Base)
89
+ end
90
+ end
91
+
92
+ module ClassMethods
93
+
94
+ # @attribute [r] normalizers
95
+ # @return [Hash<Symbol, Array<Ordinary::Normalizer>>] normalizers for each
96
+ # attribute
97
+ def normalizers
98
+ @normalizers ||= {}
99
+ end
100
+
101
+ # Define normalization for attributes.
102
+ #
103
+ # @example define normalization with a builder for the normalizer
104
+ #
105
+ # normalizes :name, lambda { lstrip }
106
+ # normalizes :name, lambda { lstrip | rstrip }
107
+ #
108
+ # @example define normalization with a block
109
+ #
110
+ # normalizes :name do |value|
111
+ # value.squeeze(' ')
112
+ # end
113
+ #
114
+ # @example define normalization with a builder for the normalizer and a block
115
+ #
116
+ # normalizes :name, -> { lstrip | block | rstrip } do |value|
117
+ # value.squeeze(' ')
118
+ # end
119
+ #
120
+ # @param [Array<Symbol>] attr_names attirubte names to normalize
121
+ # @yield [value] normalize the attribute
122
+ # @yieldparam [Object] value value of the attribute to normalize
123
+ def normalizes(*attr_names, &block)
124
+ attr_names = attr_names.dup
125
+ buil = nil
126
+ options = {}
127
+
128
+ case attr_names.last
129
+ when Proc
130
+ build = attr_names.pop
131
+ when Hash
132
+ options = attr_names.pop.dup
133
+ build = options.delete(:with)
134
+ end
135
+
136
+ unless build or block
137
+ raise ArgumentError, 'process for building a normalizer' \
138
+ '(with the last argument or :with option) or ' \
139
+ 'an unit of a normalizer ' \
140
+ '(with block) are not given'
141
+ end
142
+
143
+ build ||= lambda { block }
144
+ unit = Builder.new(&block).build(&build)
145
+ normalizer = Normalizer.new(options, &unit)
146
+
147
+ attr_names.each do |attr_name|
148
+ raise ArgumentError, "##{attr_name} is not defined" unless method_defined?(attr_name)
149
+ raise ArgumentError, "##{attr_name}= is not defined" unless method_defined?(:"#{attr_name}=")
150
+
151
+ (normalizers[attr_name.to_sym] ||= []) << normalizer
152
+
153
+ define_method :"normalized_#{attr_name}" do |context = nil|
154
+ normalize_attribute(attr_name, context)
155
+ end
156
+ end
157
+ end
158
+
159
+ end
160
+ end
@@ -0,0 +1,79 @@
1
+ require 'ordinary/unit'
2
+ require 'set'
3
+
4
+ module Ordinary
5
+ class Builder
6
+
7
+ def initialize(&block)
8
+ @context = Context.new(block)
9
+ end
10
+
11
+ # @attribute [r] context
12
+ # @return [Ordinary::Builder::Context] the context of building
13
+ attr_reader :context
14
+
15
+ # Build units for a normalizer.
16
+ #
17
+ # @yield build units for a normalizer
18
+ # @return [Ordinary::Unit, Ordinary::Units] units for a normalizer
19
+ def build(&build)
20
+ @context.instance_exec(&build)
21
+ end
22
+
23
+ module Context
24
+ class << self
25
+ attr_reader :current, :modules
26
+ end
27
+
28
+ def self.update(modules)
29
+ @current = Class.new { include *[*modules, Context] }.freeze
30
+ @modules = modules.freeze
31
+ end
32
+ private_class_method :update
33
+
34
+ update(Set.new)
35
+
36
+ def self.register(*modules)
37
+ update(@modules | modules)
38
+ end
39
+
40
+ def self.unregister(*modules)
41
+ update(@modules - modules)
42
+ end
43
+
44
+ def self.new(*args, &block)
45
+ @current.new(*args, &block)
46
+ end
47
+
48
+ def initialize(block = nil)
49
+ @block = block ? Unit.new(nil, &block) : nil
50
+ end
51
+
52
+ def block
53
+ unless @block
54
+ e = BlockNotGiven.new("`block' unit cannot use if a block is not given")
55
+ e.set_backtrace(caller)
56
+ raise e
57
+ end
58
+
59
+ @block
60
+ end
61
+
62
+ def method_missing(method_name, *args, &block)
63
+ e = UnitNotDefined.new("`#{method_name}' unit is not defined")
64
+ e.set_backtrace(caller)
65
+ raise e
66
+ end
67
+
68
+ def inspect
69
+ header = "#{Context.name}:0x%014x" % (object_id << 1)
70
+ module_list = Context.modules.map(&:name).sort * ', '
71
+ with_block = @block ? ' with a block' : ''
72
+ "#<#{header} [#{module_list}]#{with_block}>"
73
+ end
74
+ end
75
+
76
+ class UnitNotDefined < StandardError; end
77
+ class BlockNotGiven < StandardError; end
78
+ end
79
+ end
@@ -0,0 +1,117 @@
1
+ require 'ordinary/unit'
2
+ require 'set'
3
+
4
+ module Ordinary
5
+ module Module
6
+
7
+ # @attribute [r] requirements
8
+ # @return [Ordinary::Module::Requirements] libraries that the module
9
+ # requires
10
+ def requirements
11
+ @requirements ||= Requirements.new
12
+ end
13
+
14
+ # Add libraries to the requirements.
15
+ #
16
+ # @param [Array<String>] libraries required libraries
17
+ #
18
+ # @see Ordinary::Module#requirements
19
+ def requires(*libraries)
20
+ requirements.add(*libraries)
21
+ end
22
+
23
+ # Define an unit for some normalizer.
24
+ #
25
+ # @example define an unit with a block
26
+ #
27
+ # unit :lstrip do |value|
28
+ # value.lstrip
29
+ # end
30
+ #
31
+ # # same as above
32
+ # unit :lstrip, lambda { |value| value.lstrip }
33
+ #
34
+ # @example define an unit simply
35
+ #
36
+ # # call .lstrip of a value
37
+ # unit :lstrip
38
+ #
39
+ # # and named "ltrim"
40
+ # unit :ltrim, :lstrip
41
+ #
42
+ # @example define an unit with existing units
43
+ #
44
+ # unit :lstrip
45
+ # unit :rstrip
46
+ #
47
+ # # use an existing unit
48
+ # unit :ltrim, lstrip
49
+ # unit :rtrim, rstrip
50
+ #
51
+ # # use by combining existing units (by #|, #>> or #<<)
52
+ # unit :trim, ltrim | rtrim
53
+ #
54
+ # @param [Symbol] name name of the unit
55
+ # @param [Symbol] unit
56
+ # @param [Proc] unit process of normalization that the unit plays
57
+ # @param [Ordinary::Unit, Ordinary::Units] unit an existing unit or
58
+ # combination existing units
59
+ # @yield [value, *args] process of normalization that the unit plays
60
+ # @yieldparam [Object] value a value to process
61
+ # @yieldparam [Array<Object>] args additional arguments
62
+ def unit(name, unit = nil, &block)
63
+ unit = unit.to_sym if unit.is_a?(String)
64
+
65
+ unit = if unit.nil? and block.nil?
66
+ unit_by_send(name)
67
+ elsif unit.is_a?(Symbol)
68
+ unit_by_send(unit)
69
+ elsif unit.is_a?(Proc)
70
+ create_unit(&unit)
71
+ elsif block_given?
72
+ create_unit(&block)
73
+ else
74
+ unit
75
+ end
76
+
77
+ unit.owned_by(self, name) unless unit.owned?
78
+ define_method(name) { |*args| args.empty? ? unit : unit.with(*args) }
79
+ module_function name
80
+ end
81
+
82
+ private
83
+
84
+ def unit_by_send(method_name)
85
+ create_unit { |value, *args| value.__send__(method_name, *args) }
86
+ end
87
+
88
+ def create_unit(&process)
89
+ Unit.new(nil, requirements, &process)
90
+ end
91
+
92
+ class Requirements
93
+ def initialize
94
+ @libraries = Set.new
95
+ @loaded = false
96
+ end
97
+
98
+ def add(*libraries)
99
+ @loaded &= !(Set.new(libraries) - @libraries).empty?
100
+ @libraries |= libraries
101
+ end
102
+
103
+ def delete(*libraries)
104
+ @libraries -= libraries
105
+ end
106
+
107
+ def loaded?
108
+ @loaded
109
+ end
110
+
111
+ def load
112
+ @libraries.each(&method(:require))
113
+ @loaded = true
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,46 @@
1
+ module Ordinary
2
+ class Normalizer
3
+
4
+ def initialize(options = {}, &process)
5
+ @determine = extract_determiner(options)
6
+ @context = options[:on]
7
+ @process = process
8
+ end
9
+
10
+ # Normalize a value by the normalizer.
11
+ #
12
+ # @param [Object] value a value to normalize
13
+ # @return [Object] a normalized value
14
+ def normalize(value)
15
+ @process.call(value)
16
+ end
17
+
18
+ # Determine if a model coming under a target of the normalizer.
19
+ #
20
+ # @param [ActiveModel::Model] model a model to determine if be a target of
21
+ # the normalizer
22
+ # @return whether the model is a target of the normalizer
23
+ def coming_under?(model)
24
+ @determine.nil? or !!@determine.call(model)
25
+ end
26
+
27
+ # Determine if
28
+ #
29
+ # @param [Symbol] context a context to determine
30
+ # @return whether
31
+ def run_at?(context)
32
+ @context.nil? or (@context == context)
33
+ end
34
+
35
+ private
36
+
37
+ def extract_determiner(options)
38
+ if determine = options[:if]
39
+ lambda { |model| model.instance_eval(&determine) }
40
+ elsif determine = options[:unless]
41
+ lambda { |model| !model.instance_eval(&determine) }
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,85 @@
1
+ module Ordinary
2
+ module Composable
3
+ def >>(other)
4
+ Units.new([*self, *other])
5
+ end
6
+ alias | >>
7
+
8
+ def <<(other)
9
+ other >> self
10
+ end
11
+
12
+ def owner
13
+ owned? ? "#{@module.name}##{@name}" : 'owner unknown'
14
+ end
15
+
16
+ def owned_by(mod, name)
17
+ @module = mod
18
+ @name = name
19
+ end
20
+
21
+ def owned?
22
+ @module and @name
23
+ end
24
+
25
+ def instance_id
26
+ "#{self.class.name}:0x%014x" % (object_id << 1)
27
+ end
28
+ end
29
+
30
+ class Unit
31
+ include Composable
32
+
33
+ def initialize(original_unit, requirements = nil, arguments = [], &process)
34
+ raise ArgumentError, 'block not supplied' unless block_given?
35
+ @original_unit = original_unit
36
+ @requirements = requirements
37
+ @arguments = arguments
38
+ @process = process
39
+ end
40
+
41
+ attr_reader :requirements
42
+
43
+ attr_reader :arguments
44
+
45
+ attr_reader :process
46
+
47
+ def with(*arguments)
48
+ self.class.new(self, @requirements, arguments, &@process)
49
+ end
50
+
51
+ def to_proc
52
+ @requirements.load if @requirements and !@requirements.loaded?
53
+ args = @arguments + (@original_unit ? @original_unit.arguments : [])
54
+ lambda { |value| @process.call(value, *args) }
55
+ end
56
+
57
+ def inspect
58
+ original_owner = ''
59
+
60
+ if @original_unit
61
+ argument_list = @arguments.map(&:inspect) * ', '
62
+ original_owner = " (#{@original_unit.owner} with [#{argument_list}])"
63
+ end
64
+
65
+ "#<#{instance_id} #{owner}#{original_owner}>"
66
+ end
67
+ end
68
+
69
+ class Units < Array
70
+ include Composable
71
+
72
+ def with(*arguments)
73
+ self.class.new(map { |unit| unit.with(*arguments) })
74
+ end
75
+
76
+ def to_proc
77
+ processes = map(&:to_proc)
78
+ lambda { |value| processes.reduce(value) { |v, p| p.call(v) } }
79
+ end
80
+
81
+ def inspect
82
+ "#<#{instance_id} #{owner} [#{map(&:inspect) * ', '}]>"
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,3 @@
1
+ module Ordinary
2
+ VERSION = '0.0.1'
3
+ end
data/ordinary.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ordinary/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'ordinary'
8
+ spec.version = Ordinary::VERSION
9
+ spec.authors = ['Takahiro Kondo']
10
+ spec.email = ['heartery@gmail.com']
11
+ spec.description = %q{It normalizes nondistructively specified attributes of any model}
12
+ spec.summary = %q{Normalizer for any model}
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'rake'
22
+ spec.add_development_dependency 'rspec'
23
+ spec.add_development_dependency 'activemodel'
24
+ end
@@ -0,0 +1,137 @@
1
+ require 'ordinary/builder'
2
+
3
+ describe Ordinary::Builder do
4
+ describe '#context' do
5
+ subject { described_class.new { }.context }
6
+
7
+ it { should be_an(Ordinary::Builder::Context.current) }
8
+ its(:block) { should_not be_nil }
9
+ end
10
+
11
+ describe '#build' do
12
+ it '' do
13
+ end
14
+
15
+ context '' do
16
+ # it '' do
17
+ # build = lambda { a }
18
+ # builder = Ordinary::Builder.new(build)
19
+ # builder.build
20
+ # end
21
+ end
22
+ end
23
+ end
24
+
25
+ describe Ordinary::Builder::Context do
26
+ before { described_class.__send__(:update, Set.new) }
27
+
28
+ def change_for_current_ancestors(*modules)
29
+ change(described_class, :current) do
30
+ described_class.current.ancestors.select { |mod| modules.include?(mod) }
31
+ end
32
+ end
33
+
34
+ def change_for_modules
35
+ change(described_class, :modules)
36
+ end
37
+
38
+ describe '.register' do
39
+ it do
40
+ expect {
41
+ described_class.register(Math)
42
+ }.to change_for_current_ancestors(Math).from([]).to([Math])
43
+ end
44
+
45
+ it do
46
+ expect {
47
+ described_class.register(Math)
48
+ }.to change_for_modules.from(Set.new).to(Set.new([Math]))
49
+ end
50
+ end
51
+
52
+ describe '.unregister' do
53
+ before { described_class.register(Math) }
54
+
55
+ it do
56
+ expect {
57
+ described_class.unregister(Math)
58
+ }.to change_for_current_ancestors(Math).from([Math]).to([])
59
+ end
60
+
61
+ it do
62
+ expect {
63
+ described_class.unregister(Math)
64
+ }.to change_for_modules.from(Set.new([Math])).to(Set.new)
65
+ end
66
+ end
67
+
68
+ describe '.new' do
69
+ before do
70
+ @original = described_class.current
71
+ described_class.instance_variable_set(:@current, Class.new)
72
+ end
73
+
74
+ after do
75
+ described_class.instance_variable_set(:@current, @original)
76
+ end
77
+
78
+ subject { described_class.new }
79
+
80
+ it { should be_a(described_class.current) }
81
+
82
+ it "should call #{described_class}.current.new with same arguments and same block" do
83
+ described_class.current.should_receive(:new).with('arg1', 'arg2').and_yield
84
+ described_class.new('arg1', 'arg2') { }
85
+ end
86
+ end
87
+
88
+ describe '#block' do
89
+ let (:sample_block) { lambda { } }
90
+
91
+ subject { context.block }
92
+
93
+ context 'with a block at construction' do
94
+ let (:context) { described_class.new(sample_block) }
95
+
96
+ it { should be_an(Ordinary::Unit) }
97
+ its(:process) { should be(sample_block) }
98
+ end
99
+
100
+ context 'with no block at construction' do
101
+ let (:context) { described_class.new }
102
+
103
+ it { expect { subject }.to raise_error(Ordinary::Builder::BlockNotGiven) }
104
+ end
105
+ end
106
+
107
+ describe '#undefined_method' do
108
+ it do
109
+ expect {
110
+ described_class.new.undefined_method
111
+ }.to raise_error(Ordinary::Builder::UnitNotDefined, "`undefined_method' unit is not defined")
112
+ end
113
+ end
114
+
115
+ describe '#inspect' do
116
+ let (:header) { "#{described_class.name}:0x%014x" % (context.object_id << 1) }
117
+ let (:module_list) { modules.map(&:name).sort * ', ' }
118
+ let (:modules) { [Math, Enumerable] }
119
+
120
+ subject { context.inspect }
121
+
122
+ before { described_class.register(*modules) }
123
+ after { described_class.unregister(*modules) }
124
+
125
+ context 'with a block at construction' do
126
+ let (:context) { described_class.new(lambda { }) }
127
+
128
+ it { should be == "#<#{header} [#{module_list}] with a block>" }
129
+ end
130
+
131
+ context 'with no block at construction' do
132
+ let (:context) { described_class.new }
133
+
134
+ it { should be == "#<#{header} [#{module_list}]>" }
135
+ end
136
+ end
137
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ordinary
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Takahiro Kondo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activemodel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: It normalizes nondistructively specified attributes of any model
56
+ email:
57
+ - heartery@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - lib/ordinary.rb
68
+ - lib/ordinary/builder.rb
69
+ - lib/ordinary/module.rb
70
+ - lib/ordinary/normalizer.rb
71
+ - lib/ordinary/unit.rb
72
+ - lib/ordinary/version.rb
73
+ - ordinary.gemspec
74
+ - spec/ordinary/builder_spec.rb
75
+ homepage: ''
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.0.3
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Normalizer for any model
99
+ test_files:
100
+ - spec/ordinary/builder_spec.rb