super_module 1.2.2 → 1.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 80fcc01874eafdb2bf870cd3e06f55a135d830d1
4
- data.tar.gz: 7c9b6e1a8b5f16b19ff60755c2258b3e67da3484
2
+ SHA256:
3
+ metadata.gz: 70513ad566652aaf58d9da92fe22c598be383f3df25700a25245b0862e9b5580
4
+ data.tar.gz: 3002cb8ce8d0e853b1228f29f952034a7f9c2520c9635806860bde0959fe448b
5
5
  SHA512:
6
- metadata.gz: e0f9ac72e8ae4aaf4fee64d9aaae54a996de85d7e18b3f5de523bef20bc0b1362bca31bc3317888fe1de405468cc43ef117de47098792ffbb98642deb42de3d5
7
- data.tar.gz: 9e0dd6a4468c5719a99197a2136c4a9b5078009c2b78aa5fb0feb5674f322b2020648658fa279bd43caad6b68074f32eeb2e2836c23927d61c428dcd4985b9d3
6
+ metadata.gz: e20a35408bb4be154120310d932fe679d0ddc1224817886c1235cfdcb89750a6fd9655d9b0432e9f5441504122d714042da22527ac8ebb1316f3f3e6b1359021
7
+ data.tar.gz: 04db18d5c5991a8342d868a56aa8143b71b4775dd7f7f4a4cb919f9fb0c1073775602441fe41e0d19630bac5f690f52ce9c4cca5170d58bc3af1fafda87a862e
@@ -0,0 +1,35 @@
1
+ # Change Log
2
+
3
+ ## 1.3.0
4
+
5
+ - Dropped support for SuperModule 2 Beta syntax, reverting to V1 syntax as the default
6
+ - Added `included_super_module` method to allow modules to call it if they need to redefine `self.included` for meta-programming.
7
+
8
+ ## 1.2.2
9
+
10
+ * Relaxed dependency on `method_source` gem version
11
+
12
+ ## v2 Beta (v1.2.1)
13
+
14
+ * Standalone super module usage (e.g. direct class method invocation)
15
+
16
+ ## v2 Beta (v1.2.0)
17
+
18
+ * New `super_module(name)` syntax
19
+ * Much simpler implementation with guaranteed correctness and no performance hit
20
+ * Less memory footprint by not requiring method_source Ruby gem for v2 syntax
21
+ * Backwards compatibility with v1 syntax
22
+
23
+ ## v1.1.1
24
+
25
+ * Added support for private and protected methods
26
+ * Added many more RSpec test cases, including testing of empty and comment containing singleton methods
27
+
28
+ ## v1.1.0
29
+
30
+ * Brand new `self`-friendly algorithm that ensures true mixing of super module singleton methods into the including base class or module, thus always returning the actual base class or module `self` when invoking a super module inherited singleton method (thanks to [Banister](https://github.com/banister) for [reporting previous limitation on Reddit and providing suggestions](http://www.reddit.com/r/ruby/comments/30j66y/step_aside_activesupportconcern_supermodule_is/))
31
+ * New `included_super_modules` inherited singleton method that provides developer with a list of all included super modules similar to the Ruby `included_modules` method.
32
+ * No more use for method_missing (Thanks to Marc-André Lafortune for bringing up as a previous limitation in [AirPair article reviews](https://www.airpair.com/ruby/posts/step-aside-activesupportconcern-supermodule-is-the-new-sheriff-in-town))
33
+ * New dependency on [Banister](https://github.com/banister)'s [method_source](https://github.com/banister/method_source) library to have the self-friendly algorithm eval inherited class method sources into the including base class or module.
34
+ * Refactorings, including break-up of the original SuperModule into 3 modules in separate files
35
+ * More RSpec test coverage, including additional method definition scenarios, such as when adding dynamically via `class_eval` and `define_method`
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
- # <img src="https://raw.githubusercontent.com/AndyObtiva/super_module/master/SuperModule.jpg" alt="SuperModule" align="left" height="50" /> &nbsp; SuperModule 2 Beta
1
+ # <img src="https://raw.githubusercontent.com/AndyObtiva/super_module/master/SuperModule.jpg" alt="SuperModule" align="left" height="50" /> &nbsp; SuperModule 1.3
2
2
  [![Gem Version](https://badge.fury.io/rb/super_module.svg)](http://badge.fury.io/rb/super_module)
3
+ [![Build Status](https://api.travis-ci.org/AndyObtiva/super_module.svg?branch=master)](https://travis-ci.org/AndyObtiva/super_module)
3
4
  [![Coverage Status](https://coveralls.io/repos/AndyObtiva/super_module/badge.svg?branch=master)](https://coveralls.io/r/AndyObtiva/super_module?branch=master)
4
5
  [![Code Climate](https://codeclimate.com/github/AndyObtiva/super_module.svg)](https://codeclimate.com/github/AndyObtiva/super_module)
5
6
 
@@ -9,7 +10,9 @@ Ruby offers one workaround in the form of implementing the hook method [`Module.
9
10
 
10
11
  Another workaround is [`ActiveSupport::Concern`](http://api.rubyonrails.org/classes/ActiveSupport/Concern.html), a Rails library that attempts to ease some of the boilerplate pain by offering a [DSL](http://www.infoq.com/news/2007/06/dsl-or-not) layer on top of [`Module.included(base)`](http://ruby-doc.org/core-2.2.1/Module.html#method-i-included). Unfortunately, while it helps improve readability a bit, it adds even more boilerplate idiom cruft, thus feeling no more than putting a band-aid on the problem.
11
12
 
12
- But do not fear, [SuperModule](https://rubygems.org/gems/super_module) comes to the rescue! By declaring your module as a `super_module`, it will simply behave as one would expect and automatically include class methods along with instance methods, without any further work needed.
13
+ But do not fear, [SuperModule](https://rubygems.org/gems/super_module) comes to the rescue! By declaring your module as a SuperModule, it will simply behave as one would expect and automatically include class methods along with instance methods, without any further work needed.
14
+
15
+ Used in my other project: [Glimmer](https://github.com/AndyObtiva/Glimmer) (Ruby Desktop GUI Library)
13
16
 
14
17
  ## Introductory Comparison
15
18
 
@@ -73,7 +76,8 @@ A step forward that addresses the boiler-plate repetitive code concern, but is o
73
76
  #### 3) [SuperModule](https://github.com/AndyObtiva/super_module)
74
77
 
75
78
  ```ruby
76
- super_module :UserIdentifiable do
79
+ module UserIdentifiable
80
+ include SuperModule
77
81
  include ActiveModel::Model
78
82
 
79
83
  belongs_to :user
@@ -88,28 +92,19 @@ super_module :UserIdentifiable do
88
92
  end
89
93
  end
90
94
  ```
91
- Using `super_module`, developers can directly add class method invocations and definitions inside the module's body, and [`SuperModule`](https://github.com/AndyObtiva/super_module) takes care of automatically mixing them into classes that include the module.
95
+ By including `SuperModule` (following Ruby's basic convention of relying on a module), developers can directly add class method invocations and definitions inside the module's body, and [`SuperModule`](https://github.com/AndyObtiva/super_module) takes care of automatically mixing them into classes that include the module.
92
96
 
93
97
  As a result, [SuperModule](https://rubygems.org/gems/super_module) collapses the difference between extending a super class and including a super module, thus encouraging developers to write simpler code while making better Object-Oriented Design decisions.
94
98
 
95
99
  In other words, [SuperModule](https://rubygems.org/gems/super_module) furthers Ruby's goal of making programmers happy.
96
100
 
97
- By the way, SuperModule 2 Beta supports an alternate syntax as well:
98
-
99
- ```ruby
100
- UserIdentifiable = super_module do
101
- end
102
- ```
103
-
104
-
105
-
106
101
  ## Instructions
107
102
 
108
103
  #### 1) Install and require gem
109
104
 
110
105
  <b>Using [Bundler](http://bundler.io/)</b>
111
106
 
112
- Add the following to Gemfile: <pre>gem 'super_module', '1.2.2'</pre>
107
+ Add the following to Gemfile: <pre>gem 'super_module', '1.3.0'</pre>
113
108
 
114
109
  And run the following command: <pre>bundle</pre>
115
110
 
@@ -123,10 +118,11 @@ Run the following command: <pre>gem install super_module</pre>
123
118
 
124
119
  Add the following at the top of your [Ruby](https://www.ruby-lang.org/en/) file: <pre>require 'super_module'</pre>
125
120
 
126
- #### 2) Call `super_module(name)` and pass it the super module body in a block
121
+ #### 2) Simply include SuperModule in your module (just like you would do any other Ruby module)
127
122
 
128
123
  ```ruby
129
- super_module :UserIdentifiable do
124
+ module UserIdentifiable
125
+ include SuperModule
130
126
  include ActiveModel::Model
131
127
 
132
128
  belongs_to :user
@@ -151,7 +147,8 @@ end
151
147
  class CourseEnrollment < ActiveRecord::Base
152
148
  include UserIdentifiable
153
149
  end
154
- super_module :Accountable do
150
+ module Accountable
151
+ include SuperModule
155
152
  include UserIdentifiable
156
153
  end
157
154
  class Activity < ActiveRecord::Base
@@ -194,7 +191,8 @@ Create a ruby file called super_module_irb_example.rb with the following content
194
191
  require 'rubygems' # to be backwards compatible with Ruby 1.8.7
195
192
  require 'super_module'
196
193
 
197
- super_module :RequiresAttributes do
194
+ module RequiresAttributes
195
+ include SuperModule
198
196
 
199
197
  def self.requires(*attributes)
200
198
  attributes.each {|attribute| required_attributes << attribute}
@@ -267,58 +265,35 @@ V2 has a much simpler algorithm than V1 that goes as follows:
267
265
  3. Assign the cloned `SuperModule` to a new constant as defined by name (e.g. 'Utilities::Printer') under a class, module, or the top-level Ruby scope
268
266
  4. When calling `include` on the module later on, its stored super_module_body attribute is retrieved and run in the including class or module body via `class_eval`
269
267
 
270
- ## Limitations and Caveats
268
+ ## Warnings
269
+
270
+ 1) [SuperModule](https://rubygems.org/gems/super_module) by definition has been designed to be used only in the initial code declaration of a module, not later mixing or re-opening of a module.
271
271
 
272
- * [SuperModule](https://rubygems.org/gems/super_module) has been designed to be used only in the initial code definition of a module (not supporting later re-opening of the module.)
272
+ 2) Given [SuperModule](https://rubygems.org/gems/super_module)'s implementation relies on `self.included(base)`, sub-modules must not hook into it.
273
273
 
274
- * Given [SuperModule](https://rubygems.org/gems/super_module)'s implementation relies on `self.included(base)`, if an including super module (or a super module including another super module) must hook into <code>self.included(base)</code> for meta-programming cases that require it, such as conditional `include` statements or method definitions, it would have to alias <code>self.included(base)</code> and then invoke the aliased version in every super module that needs it like in this example:
274
+ In very rare occasions when an including module needs to redefine <code>self.included(base)</code> for meta-programming purposes, you may do so at your own peril by first invoking <code>self.included_super_module(base)</code> like in this example:
275
275
  ```ruby
276
- super_module :AdminIdentifiable do
276
+ module AdminIdentifiable
277
+ include SuperModule
277
278
  include UserIdentifiable
278
279
 
279
280
  class << self
280
- alias included_super_module included
281
281
  def included(base)
282
282
  included_super_module(base)
283
- # do some extra work
283
+ # do some extra rare meta-programming work
284
284
  # like conditional inclusion of other modules
285
285
  # or conditional definition of methods
286
286
  end
287
287
  end
288
288
  end
289
289
  ```
290
- In the future, [SuperModule](https://rubygems.org/gems/super_module) could perhaps provide robust built-in facilities for allowing super modules to easily hook into <code>self.included(base)</code> without interfering with [SuperModule](https://rubygems.org/gems/super_module) behavior.
290
+ This does not work for all cases (like multiple levels of super module nesting), and is not recommended, likely causing problems.
291
291
 
292
- ## What's New?
292
+ Avoid hooking into `self.included(base)` at all costs.
293
293
 
294
- ### v2 Beta (v1.2.2)
294
+ ## Change Log
295
295
 
296
- * Relaxed dependency on `method_source` gem version
297
-
298
- ### v2 Beta (v1.2.1)
299
-
300
- * Standalone super module usage (e.g. direct class method invocation)
301
-
302
- ### v2 Beta (v1.2.0)
303
-
304
- * New `super_module(name)` syntax
305
- * Much simpler implementation with guaranteed correctness and no performance hit
306
- * Less memory footprint by not requiring method_source Ruby gem for v2 syntax
307
- * Backwards compatibility with v1 syntax
308
-
309
- ### v1.1.1
310
-
311
- * Added support for private and protected methods
312
- * Added many more RSpec test cases, including testing of empty and comment containing singleton methods
313
-
314
- ### v1.1.0
315
-
316
- * Brand new `self`-friendly algorithm that ensures true mixing of super module singleton methods into the including base class or module, thus always returning the actual base class or module `self` when invoking a super module inherited singleton method (thanks to [Banister](https://github.com/banister) for [reporting previous limitation on Reddit and providing suggestions](http://www.reddit.com/r/ruby/comments/30j66y/step_aside_activesupportconcern_supermodule_is/))
317
- * New `included_super_modules` inherited singleton method that provides developer with a list of all included super modules similar to the Ruby `included_modules` method.
318
- * No more use for method_missing (Thanks to Marc-André Lafortune for bringing up as a previous limitation in [AirPair article reviews](https://www.airpair.com/ruby/posts/step-aside-activesupportconcern-supermodule-is-the-new-sheriff-in-town))
319
- * New dependency on [Banister](https://github.com/banister)'s [method_source](https://github.com/banister/method_source) library to have the self-friendly algorithm eval inherited class method sources into the including base class or module.
320
- * Refactorings, including break-up of the original SuperModule into 3 modules in separate files
321
- * More RSpec test coverage, including additional method definition scenarios, such as when adding dynamically via `class_eval` and `define_method`
296
+ [CHANGELOG.md](https://raw.githubusercontent.com/AndyObtiva/super_module/master/CHANGELOG.md)
322
297
 
323
298
  ## Feedback and Contribution
324
299
 
@@ -332,6 +307,11 @@ The library is quite new and can use all the feedback and help it can get. So, p
332
307
  * 2015-03-27 - [AirPair](http://www.airpair.com) Article: [Step aside ActiveSupport::Concern. SuperModule is the new sheriff in town!](https://www.airpair.com/ruby/posts/step-aside-activesupportconcern-supermodule-is-the-new-sheriff-in-town)
333
308
  * 2014-03-27 - [Code Painter](http://andymaleh.blogspot.com) Blog Post: [Ruby SuperModule Comes To The Rescue!!](http://andymaleh.blogspot.ca/2014/03/ruby-supermodule-comes-to-rescue.html)
334
309
 
310
+ ## TODO
311
+
312
+ - Fix issue where class methods cannot get called from super_module directly (when used with "CONSTANT = super_module do" approach)
313
+ - Fix issue where a super module (declared with super_module) can get included in one class only where class methods work, but the next class that includes the super module does not have class methods work
314
+
335
315
  ## Copyright
336
316
 
337
317
  Copyright (c) 2014-2016 Andy Maleh. See LICENSE.txt for
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.2
1
+ 1.3.0
@@ -8,50 +8,12 @@
8
8
 
9
9
  # Avoiding require_relative for backwards compatibility with Ruby 1.8.7
10
10
 
11
+ require_relative 'super_module/v1'
12
+
11
13
  module SuperModule
12
14
  class << self
13
- V1_LIBRARY = File.expand_path(File.join(File.dirname(__FILE__), 'super_module', 'v1'))
14
-
15
- attr_accessor :super_module_body
16
-
17
- def define(&super_module_body)
18
- clone.tap { |super_module| super_module.super_module_body = super_module_body }
19
- end
20
-
21
15
  def included(original_base)
22
- if super_module_body
23
- original_base.class_eval(&super_module_body)
24
- else
25
- require V1_LIBRARY
26
- original_base.send(:include, SuperModule::V1)
27
- end
28
- end
29
-
30
- def __super_module_parent(name, ancestor)
31
- name_tokens = name.to_s.split('::')
32
- name_token_count = name_tokens.size
33
- if name_token_count == 1
34
- ancestor
35
- else
36
- top_ancestor = ancestor.const_get(name_tokens.first)
37
- sub_module_name = name_tokens[1, name_token_count].join('::')
38
- __super_module_parent(sub_module_name, top_ancestor)
39
- end
40
- end
41
-
42
- end
43
-
44
- end
45
-
46
- def super_module(name=nil, &super_module_body)
47
- initial_ancestor = self.class == Object ? Object : self
48
- SuperModule.define(&super_module_body).tap do |new_super_module|
49
- if name
50
- parent = SuperModule.__super_module_parent(name, initial_ancestor)
51
- module_name = name.to_s.split('::').last
52
- parent.const_set(module_name, new_super_module)
53
- super_module_body = new_super_module.super_module_body
54
- new_super_module.class_eval(&super_module_body)
16
+ original_base.send(:include, SuperModule::V1)
55
17
  end
56
18
  end
57
19
  end
@@ -28,10 +28,10 @@ module SuperModule
28
28
  __define_super_module_singleton_methods(base)
29
29
  __invoke_module_body_method_calls(base)
30
30
  end
31
+ alias included_super_module included
31
32
  end
32
33
  end
33
34
  end
34
35
  end
35
36
  end
36
37
  end
37
-
@@ -26,7 +26,8 @@ module SuperModule
26
26
  :dbg_print, #debugger library friendly exclusion
27
27
  :dbg_puts, #debugger library friendly exclusion
28
28
  :define,
29
- :included,
29
+ :included,
30
+ :included_super_module,
30
31
  :included_super_modules,
31
32
  :singleton_method_added,
32
33
  :super_module_body
@@ -36,7 +37,7 @@ module SuperModule
36
37
  def __super_module_singleton_methods
37
38
  @__super_module_singleton_methods ||= []
38
39
  end
39
-
40
+
40
41
  def __singleton_method_body_for(super_module, method_name)
41
42
  super_module.__super_module_singleton_methods.detect {|sm_method_name, sm_method_body| sm_method_name == method_name}[1]
42
43
  end
@@ -78,7 +79,7 @@ module SuperModule
78
79
 
79
80
  def __singleton_method_body(method_name)
80
81
  super_module_having_method = __super_module_having_method(method_name)
81
- super_module_having_method ? __singleton_method_body_for(super_module_having_method, method_name) : __build_singleton_method_body_source(method_name)
82
+ super_module_having_method ? __singleton_method_body_for(super_module_having_method, method_name) : __build_singleton_method_body_source(method_name)
82
83
  end
83
84
 
84
85
  def __overwrite_singleton_method_from_current_super_module(method_name, method_body)
@@ -91,7 +92,7 @@ module SuperModule
91
92
  def singleton_method_added(method_name)
92
93
  unless __super_module_singleton_methods_excluded_from_base_definition.include?(method_name)
93
94
  method_body = __singleton_method_body(method_name)
94
- __super_module_singleton_methods << [method_name, method_body]
95
+ __super_module_singleton_methods << [method_name, method_body]
95
96
  __overwrite_singleton_method_from_current_super_module(method_name, method_body)
96
97
  end
97
98
  end
@@ -1,219 +1,256 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe SuperModule do
3
+ class V1::FakeActiveRecord
4
+ include ::V1::FakeActiveModel
5
+ end
4
6
 
5
- ['V1',
6
- 'V2',
7
- 'V2Alt'
8
- ].each do |version|
9
- Object.send(:remove_const, :SupportVersion) rescue nil
10
- SupportVersion = Support.const_get(version)
11
-
12
- Object.send(:remove_const, :FakeActiveRecord) rescue nil
13
- class FakeActiveRecord
14
- include SupportVersion::FakeActiveModel
15
- end
7
+ class V1::FooActiveRecord < V1::FakeActiveRecord
8
+ include ::V1::Foo
9
+ end
16
10
 
17
- Object.send(:remove_const, :FooActiveRecord) rescue nil
18
- class FooActiveRecord < FakeActiveRecord
19
- include SupportVersion::Foo
20
- end
11
+ class V1::BarActiveRecord < V1::FakeActiveRecord
12
+ include ::V1::Bar
13
+ end
14
+
15
+ class V1::BazActiveRecord < V1::FakeActiveRecord
16
+ include ::V1::Baz
17
+ end
18
+
19
+ module V1::SummarizedActiveModel
20
+ include SuperModule
21
21
 
22
- Object.send(:remove_const, :BarActiveRecord) rescue nil
23
- class BarActiveRecord < FakeActiveRecord
24
- include SupportVersion::Bar
22
+ def self.included(klass)
23
+ included_super_module(klass)
24
+ if klass.name.split(/::/).last.start_with?('Fake')
25
+ klass.extend(FakeClassMethods)
25
26
  end
27
+ end
28
+
29
+ def self.validates(attribute, options)
30
+ super # test that singleton class inheritance works
31
+ end
32
+
33
+ def self.validations
34
+ super # test that singleton class inheritance works
35
+ end
36
+
37
+ def self.summary
38
+ validations.flatten.map(&:to_s).join("/")
39
+ end
26
40
 
27
- Object.send(:remove_const, :BazActiveRecord) rescue nil
28
- class BazActiveRecord < FakeActiveRecord
29
- include SupportVersion::Baz
41
+ module FakeClassMethods
42
+ def fake_summary
43
+ 'This is a fake summary.'
30
44
  end
45
+ end
46
+ end
31
47
 
32
- context version do
48
+ class V1::SummarizedActiveRecord < V1::FakeActiveRecord
49
+ include ::V1::SummarizedActiveModel
50
+ end
33
51
 
34
- context "standalone module usage" do
35
- subject { Support::V2::FakeActiveModel }
52
+ class V1::FakeSummarizedActiveRecord < V1::FakeActiveRecord
53
+ include ::V1::SummarizedActiveModel
54
+ end
36
55
 
37
- it 'allows invoking class methods' do
38
- subject.validates 'foo', {:presence => true}
39
- expect(subject.validations).to include(['foo', {:presence => true}])
40
- end
56
+ describe SuperModule do
57
+ context V1 do
58
+ context "standalone module usage" do
59
+ subject { V1::FakeActiveModel }
41
60
 
61
+ it 'allows invoking class methods' do
62
+ subject.validates 'foo', {:presence => true}
63
+ expect(subject.validations).to include(['foo', {:presence => true}])
42
64
  end
65
+ end
43
66
 
44
- context "included by a module (Foo) that is included by a class (FooActiveRecord)" do
67
+ context "included by a module (Foo) that is included by a class (FooActiveRecord)" do
45
68
 
46
- subject { FooActiveRecord }
69
+ subject { V1::FooActiveRecord }
47
70
 
48
- it 'allows invoking class methods' do
49
- expect(subject.validations).to include(['foo', {:presence => true}])
50
- end
71
+ it 'allows invoking class methods' do
72
+ expect(subject.validations).to include(['foo', {:presence => true}])
73
+ end
51
74
 
52
- it 'includes class method declared via "self.method_name"' do
53
- expect(subject.foo).to eq('self.foo')
54
- end
75
+ it 'includes class method declared via "self.method_name"' do
76
+ expect(subject.foo).to eq('self.foo')
77
+ end
55
78
 
56
- it 'includes class method declared via "self.method_name" taking a single parameter' do
57
- expect(subject.foo_single_param('param1_value')).to eq('self.foo(param1_value)')
58
- end
79
+ it 'includes class method declared via "self.method_name" taking a single parameter' do
80
+ expect(subject.foo_single_param('param1_value')).to eq('self.foo(param1_value)')
81
+ end
59
82
 
60
- it 'includes class method declared via "self.method_name" taking multiple parameters' do
61
- expect(subject.foo_multi_params('param1_value', 'param2_value', 'param3_value')).to eq('self.foo(param1_value,param2_value,param3_value)')
62
- end
83
+ it 'includes class method declared via "self.method_name" taking multiple parameters' do
84
+ expect(subject.foo_multi_params('param1_value', 'param2_value', 'param3_value')).to eq('self.foo(param1_value,param2_value,param3_value)')
85
+ end
63
86
 
64
- it 'includes class method declared via "self.method_name" taking a block' do
65
- formatter = Proc.new {|value| "Block formatted #{value}"}
66
- expect(subject.foo_block(&formatter)).to eq('Block formatted self.foo')
67
- end
87
+ it 'includes class method declared via "self.method_name" taking a block' do
88
+ formatter = Proc.new {|value| "Block formatted #{value}"}
89
+ expect(subject.foo_block(&formatter)).to eq('Block formatted self.foo')
90
+ end
68
91
 
69
- it 'includes class method declared via "self.method_name" taking a single paramter and a block' do
70
- formatter = Proc.new {|value, param1| "Block formatted #{value} with #{param1}"}
71
- expect(subject.foo_single_param_block('param1_value', &formatter)).to eq('Block formatted self.foo with param1_value')
72
- end
92
+ it 'includes class method declared via "self.method_name" taking a single paramter and a block' do
93
+ formatter = Proc.new {|value, param1| "Block formatted #{value} with #{param1}"}
94
+ expect(subject.foo_single_param_block('param1_value', &formatter)).to eq('Block formatted self.foo with param1_value')
95
+ end
73
96
 
74
- it 'includes class method declared via "self.method_name" taking multiple paramters and a block' do
75
- formatter = Proc.new {|value, param1, param2, param3| "Block formatted #{value} with #{param1},#{param2},#{param3}"}
76
- expect(subject.foo_multi_params_block('param1_value', 'param2_value', 'param3_value', &formatter)).to eq('Block formatted self.foo with param1_value,param2_value,param3_value')
77
- end
97
+ it 'includes class method declared via "self.method_name" taking multiple paramters and a block' do
98
+ formatter = Proc.new {|value, param1, param2, param3| "Block formatted #{value} with #{param1},#{param2},#{param3}"}
99
+ expect(subject.foo_multi_params_block('param1_value', 'param2_value', 'param3_value', &formatter)).to eq('Block formatted self.foo with param1_value,param2_value,param3_value')
100
+ end
78
101
 
79
- it 'includes class method declared via "self.method_name" on one line' do
80
- expect(subject.foo_one_line).to eq('self.foo_one_line')
81
- end
102
+ it 'includes class method declared via "self.method_name" on one line' do
103
+ expect(subject.foo_one_line).to eq('self.foo_one_line')
104
+ end
82
105
 
83
- it 'includes class method declared via "class < self"' do
84
- expect(subject.foo_class_self).to eq('self.foo_class_self')
85
- end
106
+ it 'includes class method declared via "class < self"' do
107
+ expect(subject.foo_class_self).to eq('self.foo_class_self')
108
+ end
86
109
 
87
- it 'includes class method declared via "class < self" using define_method' do
88
- expect(subject.foo_class_self_define_method).to eq('self.foo_class_self_define_method')
89
- end
110
+ it 'includes class method declared via "class < self" using define_method' do
111
+ expect(subject.foo_class_self_define_method).to eq('self.foo_class_self_define_method')
112
+ end
90
113
 
91
- it 'includes private class method' do
92
- expect{subject.foo_private}.to raise_error
93
- expect(subject.private_methods.map(&:to_s)).to include('foo_private')
94
- expect(subject.send(:foo_private)).to eq('self.foo_private')
95
- end
114
+ it 'includes private class method' do
115
+ expect{subject.foo_private}.to raise_error
116
+ expect(subject.private_methods.map(&:to_s)).to include('foo_private')
117
+ expect(subject.send(:foo_private)).to eq('self.foo_private')
118
+ end
96
119
 
97
- it 'includes protected class method (declared using protected :method_name)' do
98
- expect{subject.foo_protected}.to raise_error
99
- expect(subject.protected_methods.map(&:to_s)).to include('foo_protected')
100
- expect(subject.send(:foo_protected)).to eq('self.foo_protected')
101
- end
120
+ it 'includes protected class method (declared using protected :method_name)' do
121
+ expect{subject.foo_protected}.to raise_error
122
+ expect(subject.protected_methods.map(&:to_s)).to include('foo_protected')
123
+ expect(subject.send(:foo_protected)).to eq('self.foo_protected')
124
+ end
102
125
 
103
- it 'includes empty class method' do
104
- expect(subject.empty).to eq(nil)
105
- end
126
+ it 'includes empty class method' do
127
+ expect(subject.empty).to eq(nil)
128
+ end
106
129
 
107
- it 'includes empty class method with one empty line' do
108
- expect(subject.empty_one_empty_line).to eq(nil)
109
- end
130
+ it 'includes empty class method with one empty line' do
131
+ expect(subject.empty_one_empty_line).to eq(nil)
132
+ end
110
133
 
111
- it 'includes empty class method with comment' do
112
- expect(subject.empty_with_comment).to eq(nil)
113
- end
134
+ it 'includes empty class method with comment' do
135
+ expect(subject.empty_with_comment).to eq(nil)
136
+ end
114
137
 
115
- it 'includes empty class method one line definition' do
116
- expect(subject.empty_one_line_definition).to eq(nil)
117
- end
138
+ it 'includes empty class method one line definition' do
139
+ expect(subject.empty_one_line_definition).to eq(nil)
140
+ end
118
141
 
119
- it 'includes empty class method one line definition with spaces' do
120
- expect(subject.empty_one_line_definition_with_spaces).to eq(nil)
121
- end
142
+ it 'includes empty class method one line definition with spaces' do
143
+ expect(subject.empty_one_line_definition_with_spaces).to eq(nil)
144
+ end
122
145
 
123
- it 'includes instance methods' do
124
- instance = subject.new
146
+ it 'includes instance methods' do
147
+ instance = subject.new
125
148
 
126
- expect(instance.foo).to eq('foo')
127
- end
149
+ expect(instance.foo).to eq('foo')
150
+ end
128
151
 
129
- it 'provides class method self as the including base class as in the class method (meh)' do
130
- expect(subject.meh).to eq(subject)
131
- end
152
+ it 'provides class method self as the including base class as in the class method (meh)' do
153
+ expect(subject.meh).to eq(subject)
132
154
  end
155
+ end
133
156
 
134
- context "included by a module (Foo) that is included by a second module (Bar) that is included by a class (BarActiveRecord)" do
157
+ context "included by a module (Foo) that is included by a second module (Bar) that is included by a class (BarActiveRecord)" do
135
158
 
136
- subject { BarActiveRecord }
159
+ subject { V1::BarActiveRecord }
137
160
 
138
- it 'allows invoking class methods' do
139
- expect(subject.validations).to include(['foo', {:presence => true}])
140
- expect(subject.validations).to include(['bar', {:presence => true}])
141
- end
161
+ it 'allows invoking class methods' do
162
+ expect(subject.validations).to include(['foo', {:presence => true}])
163
+ expect(subject.validations).to include(['bar', {:presence => true}])
164
+ end
142
165
 
143
- it 'includes class methods declared via "class << self"' do
144
- expect(subject.foo).to eq('self.foo')
145
- expect(subject.bar).to eq('self.bar')
146
- end
166
+ it 'includes class methods declared via "class << self"' do
167
+ expect(subject.foo).to eq('self.foo')
168
+ expect(subject.bar).to eq('self.bar')
169
+ end
147
170
 
148
- it 'includes instance methods' do
149
- instance = subject.new
171
+ it 'includes instance methods' do
172
+ instance = subject.new
150
173
 
151
- expect(instance.foo).to eq('foo')
152
- expect(instance.bar).to eq('bar')
153
- end
174
+ expect(instance.foo).to eq('foo')
175
+ expect(instance.bar).to eq('bar')
176
+ end
154
177
 
155
- it 'can include a basic module (Forwardable) into singleton class by placing in class << self' do
156
- instance = subject.new
157
- expect(instance.length).to eq(3)
158
- end
178
+ it 'can include a basic module (Forwardable) into singleton class by placing in class << self' do
179
+ instance = subject.new
180
+ expect(instance.length).to eq(3)
181
+ end
159
182
 
160
- it 'applies super module (Bar) class method invocation (make_barrable) on including class (BarActiveRecord), whereby the method that is defined in the same super module that declares it (Bar)' do
161
- expect(subject.barrable).to eq(true)
162
- end
183
+ it 'applies super module (Bar) class method invocation (make_barrable) on including class (BarActiveRecord), whereby the method that is defined in the same super module that declares it (Bar)' do
184
+ expect(subject.barrable).to eq(true)
185
+ end
163
186
 
164
- it 'can include a basic module (Comparable)' do
165
- now = Time.now
166
- allow(Time).to receive(:now).and_return(now)
167
- instance = subject.new
168
- allow(Time).to receive(:now).and_return(now + 100)
169
- instance2 = subject.new
187
+ it 'can include a basic module (Comparable)' do
188
+ now = Time.now
189
+ allow(Time).to receive(:now).and_return(now)
190
+ instance = subject.new
191
+ allow(Time).to receive(:now).and_return(now + 100)
192
+ instance2 = subject.new
170
193
 
171
- expect(instance2 > instance).to eq(true)
172
- end
194
+ expect(instance2 > instance).to eq(true)
195
+ end
173
196
 
174
- it 'provides class method self as the including base class as in the class method (meh)' do
175
- expect(subject.meh).to eq(subject)
176
- end
197
+ it 'provides class method self as the including base class as in the class method (meh)' do
198
+ expect(subject.meh).to eq(subject)
177
199
  end
200
+ end
201
+
202
+ context "(with SuperModule.define alternate syntax in Baz) included by a module (Foo), included by another module (Bar), included by a third module (Baz) that is included by a class (BazActiveRecord)" do
178
203
 
179
- context "(with SuperModule.define alternate syntax in Baz) included by a module (Foo), included by another module (Bar), included by a third module (Baz) that is included by a class (BazActiveRecord)" do
204
+ subject { V1::BazActiveRecord }
180
205
 
181
- subject { BazActiveRecord }
206
+ it 'allows invoking class methods' do
207
+ expect(subject.validations).to include(['foo', {:presence => true}])
208
+ expect(subject.validations).to include(['bar', {:presence => true}])
209
+ expect(subject.validations).to include(['baz', {:presence => true}])
210
+ end
182
211
 
183
- it 'allows invoking class methods' do
184
- expect(subject.validations).to include(['foo', {:presence => true}])
185
- expect(subject.validations).to include(['bar', {:presence => true}])
186
- expect(subject.validations).to include(['baz', {:presence => true}])
187
- end
212
+ it 'includes class methods declared via "class << self"' do
213
+ expect(subject.foo).to eq('self.foo')
214
+ expect(subject.bar).to eq('self.bar')
215
+ expect(subject.baz).to eq('self.baz')
216
+ end
188
217
 
189
- it 'includes class methods declared via "class << self"' do
190
- expect(subject.foo).to eq('self.foo')
191
- expect(subject.bar).to eq('self.bar')
192
- expect(subject.baz).to eq('self.baz')
193
- end
218
+ it 'includes instance methods' do
219
+ instance = subject.new(100)
194
220
 
195
- it 'includes instance methods' do
196
- instance = BazActiveRecord.new(100)
221
+ expect(instance.foo).to eq('foo')
222
+ expect(instance.bar).to eq('bar')
223
+ expect(instance.baz).to eq('baz')
224
+ end
197
225
 
198
- expect(instance.foo).to eq('foo')
199
- expect(instance.bar).to eq('bar')
200
- expect(instance.baz).to eq('baz')
201
- end
226
+ it 'invokes singleton method (make_barrable) from super module' do
227
+ expect(subject.barrable).to eq(true)
228
+ end
202
229
 
203
- it 'invokes singleton method (make_barrable) from super module' do
204
- expect(subject.barrable).to eq(true)
205
- end
230
+ it 'can override super module behavior (<=>)' do
231
+ instance = subject.new(50)
232
+ instance2 = subject.new(7)
206
233
 
207
- it 'can override super module behavior (<=>)' do
208
- instance = subject.new(50)
209
- instance2 = subject.new(7)
234
+ expect(instance2 > instance).to eq(false)
235
+ end
210
236
 
211
- expect(instance2 > instance).to eq(false)
212
- end
237
+ it 'provides class method self as the including base class as in the class method (meh)' do
238
+ expect(subject.meh).to eq(subject)
239
+ end
240
+ end
213
241
 
214
- it 'provides class method self as the including base class as in the class method (meh)' do
215
- expect(subject.meh).to eq(subject)
216
- end
242
+ context 'meta-programming included' do
243
+ it 'returns summary' do
244
+ V1::SummarizedActiveRecord.validates 'foo', {:presence => true}
245
+ V1::SummarizedActiveRecord.validates 'bar', {:presence => true}
246
+ expect(V1::SummarizedActiveRecord.summary).to eq('foo/{:presence=>true}/bar/{:presence=>true}')
247
+ expect{V1::SummarizedActiveRecord.fake_summary}.to raise_error
248
+ end
249
+ it 'returns fake summary' do
250
+ V1::FakeSummarizedActiveRecord.validates 'foo', {:presence => true}
251
+ V1::FakeSummarizedActiveRecord.validates 'bar', {:presence => true}
252
+ expect(V1::FakeSummarizedActiveRecord.summary).to eq('foo/{:presence=>true}/bar/{:presence=>true}')
253
+ expect(V1::FakeSummarizedActiveRecord.fake_summary).to eq('This is a fake summary.')
217
254
  end
218
255
  end
219
256
  end