ruby-features 1.1.2 → 1.2.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 27643cb1fa6b12baf10bf86fbc40226e2e70bc08
4
+ data.tar.gz: 2be53a6cc1404b1709b910fb8390663f4fc2d801
5
+ SHA512:
6
+ metadata.gz: c03d3cef6917da453e06c12184e31988366f42183ed170a6308049ce87dd8790dfafb3a41df9151a49672c7d1a161359634638f3873f11b60d0695cbdc89f6d0
7
+ data.tar.gz: 170853e803e73904e1755fc688e24032d45df28304a5f12427f4e9a3f259b3de9a6978afb6f67c36af5ee4da7fb12836a894a786abc078ccba58c22383ba8a44
data/README.md CHANGED
@@ -5,10 +5,10 @@ Ruby Features
5
5
  [![Climate](https://codeclimate.com/github/stokarenko/ruby-features/badges/gpa.svg)](https://codeclimate.com/github/stokarenko/ruby-features)
6
6
  [![Coverage](https://codeclimate.com/github/stokarenko/ruby-features/badges/coverage.svg)](https://codeclimate.com/github/stokarenko/ruby-features/coverage)
7
7
 
8
- Ruby Features makes the extending of Ruby classes and modules to be easy, safe and controlled.
8
+ Ruby Features allow the extending of Ruby classes and modules to become easy, safe and controlled.
9
9
 
10
10
  ## Why?
11
- Lets ask, is good to write the code like this:
11
+ Lets ask, is that good to write the code like this:
12
12
  ```ruby
13
13
  String.send :include, MyStringExtension
14
14
  ```
@@ -22,7 +22,7 @@ Object.class_eval do
22
22
  end
23
23
  ```
24
24
 
25
- The question is about motivation to write such things. Lets skip well-known reason like
25
+ The matter is in motivation to write such things. Lets skip the well-known reasons like
26
26
  > Because I can! That is Ruby baby, lets make some anarchy!
27
27
 
28
28
  but say:
@@ -37,12 +37,12 @@ library, infected by massive patches to core entities.
37
37
  Ruby Features goal is to take that under control.
38
38
 
39
39
  The main features are:
40
- * No any dependencies;
40
+ * No dependencies;
41
41
  * Built-in lazy load;
42
42
  * Supports ActiveSupport lazy load as well;
43
43
  * Stimulates the clear extending, but prevents monkey patching;
44
44
  * Gives the control what core extensions to apply;
45
- * Any moment gives the knowledge who and how exactly affected to programming entities.
45
+ * Gives the understading who and how exactly affected to programming entities.
46
46
 
47
47
  ## requirements
48
48
  * Ruby >= 1.9.3
@@ -68,7 +68,7 @@ to apply third-party features.
68
68
 
69
69
  ## Usage
70
70
  ### Feature definition
71
- Feature file name should ends with `_feature.rb`.
71
+ Feature file name should end with `_feature.rb`.
72
72
 
73
73
  Lets define the feature in `lib/features/something_useful_feature.rb`:
74
74
  ```ruby
@@ -80,6 +80,16 @@ RubyFeatures.define 'some_namespace/something_useful' do
80
80
  attr_accessor :useful_variable
81
81
  end
82
82
 
83
+ rewrite_instance_methods do
84
+ # rewrite instance methods
85
+ # call `super` to reach the rewritten method
86
+ def existing_instance_method
87
+ # some code before super
88
+ super
89
+ # some code after super
90
+ end
91
+ end
92
+
83
93
  instance_methods do
84
94
  # instance methods
85
95
  def useful_instance_method
@@ -91,17 +101,17 @@ RubyFeatures.define 'some_namespace/something_useful' do
91
101
  def useful_class_method
92
102
  end
93
103
  end
104
+ end
94
105
 
95
- apply_to 'ActiveRecord::Relation' do
96
- # feature can contain several apply_to definition
97
- end
98
-
106
+ apply_to 'ActiveRecord::Relation' do
107
+ # feature can contain several apply_to definition
99
108
  end
109
+
100
110
  end
101
111
  ```
102
112
 
103
113
  ### Dependencies
104
- The dependencies from other Ruby Features can be defined like:
114
+ The dependencies on other Ruby Features can be defined like:
105
115
  ```ruby
106
116
  RubyFeatures.define 'main_feature' do
107
117
  dependency 'dependent_feature1'
@@ -110,7 +120,7 @@ end
110
120
  ```
111
121
 
112
122
  ### Conditions
113
- Sometimes is required to apply different things, dependent on some criteria:
123
+ Sometimes it`s required to apply different things, depending on some criteria:
114
124
  ```ruby
115
125
  RubyFeatures.define 'some_namespace/something_useful' do
116
126
  apply_to 'ActiveRecord::Base' do
@@ -131,7 +141,7 @@ end
131
141
  ```
132
142
 
133
143
  It's bad to do like that, because the mixin applied by Ruby Features became to be not static.
134
- That cause not predictable behavior.
144
+ That causes unpredictable behavior.
135
145
 
136
146
  Ruby Features provides the `conditions` mechanism to avoid such problem:
137
147
  ```ruby
@@ -156,7 +166,7 @@ RubyFeatures.define 'some_namespace/something_useful' do
156
166
  end
157
167
  ```
158
168
 
159
- All feature definition helpers supports the conditions:
169
+ All DSL methods support the conditions:
160
170
  ```ruby
161
171
  apply_to 'ActiveRecord::Base', if: :first_criteria do; end
162
172
 
@@ -218,14 +228,14 @@ RubyFeatures.find_in_path(File.expand_path('../lib/features', __FILE__))
218
228
  ```
219
229
 
220
230
  ### Feature applying
221
- Feature can be applied immediately after it's definition:
231
+ Feature can be applied immediately after its definition:
222
232
  ```ruby
223
233
  RubyFeatures.define 'some_namespace/something_useful' do
224
234
  # definition
225
235
  end.apply
226
236
  ```
227
237
 
228
- Features can be applied right after loading from path:
238
+ Features can be applied immediately after loading from path:
229
239
  ```ruby
230
240
  RubyFeatures.find_in_path(File.expand_path('../lib/features', __FILE__)).apply_all
231
241
  ```
@@ -238,12 +248,12 @@ RubyFeatures.apply 'some_namespace/something_useful'
238
248
  ```
239
249
 
240
250
  ## Changes
251
+ ### v1.2.0
252
+ * Added rewrite_instance_methods.
253
+
241
254
  ### v1.1.0
242
255
  * Added conditions.
243
256
  * Added dependencies.
244
257
 
245
- ## TODO
246
- * ActionDispatch with ActiveSupport lazy_load
247
-
248
258
  ## License
249
259
  MIT License. Copyright (c) 2015 Sergey Tokarenko
@@ -33,18 +33,29 @@ module RubyFeatures
33
33
  _methods('Include', asserts, block)
34
34
  end
35
35
 
36
+ def rewrite_instance_methods(asserts = {}, &block)
37
+ _methods('RewriteInstance', asserts, block)
38
+ end
39
+
36
40
  def _apply_methods(target_class)
37
41
  constants.each do |constant|
38
- mixin_method, existing_methods_method = case(constant)
39
- when /^Extend/ then [:extend, :methods]
40
- when /^Include/ then [:include, :instance_methods]
42
+ mixin_method, existing_methods_method, existing_methods_check = case(constant)
43
+ when /^Extend/ then [:extend, :methods, :exclusion]
44
+ when /^Include/ then [:include, :instance_methods, :exclusion]
45
+ when /^RewriteInstance/ then [:prepend, :instance_methods, :inclusion]
41
46
  else raise ArgumentError.new("Wrong mixin constant: #{constant}")
42
47
  end
43
48
 
44
49
  mixin = const_get(constant)
45
50
 
46
- common_methods = target_class.public_send(existing_methods_method) & mixin.instance_methods
47
- raise NameError.new("Tried to #{mixin_method} already existing methods: #{common_methods.inspect}") unless common_methods.empty?
51
+ case(existing_methods_check)
52
+ when :exclusion
53
+ existing_methods = mixin.instance_methods & target_class.public_send(existing_methods_method)
54
+ raise NameError.new("Tried to #{mixin_method} already existing methods: #{existing_methods.inspect}") unless existing_methods.empty?
55
+ when :inclusion
56
+ not_existing_methods = mixin.instance_methods - target_class.public_send(existing_methods_method)
57
+ raise NameError.new("Tried to #{mixin_method} not existing methods: #{not_existing_methods.inspect}") unless not_existing_methods.empty?
58
+ end
48
59
 
49
60
  target_class.send(mixin_method, mixin)
50
61
  end
@@ -1,3 +1,3 @@
1
1
  module RubyFeatures
2
- VERSION = '1.1.2'.freeze
2
+ VERSION = '1.2.0'.freeze
3
3
  end
data/spec/define_spec.rb CHANGED
@@ -31,6 +31,28 @@ describe RubyFeatures::Concern::Feature do
31
31
  )
32
32
  end
33
33
 
34
+ it 'should apply rewrite instance methods' do
35
+ test_class.class_eval do
36
+ def test_rewrite_instance_method
37
+ 2
38
+ end
39
+ end
40
+
41
+ expect{
42
+ define_test_feature('rewrite_instance_methods_feature') do
43
+ rewrite_instance_methods do
44
+ def test_rewrite_instance_method
45
+ 3 * super
46
+ end
47
+ end
48
+ end.apply
49
+ }.to change{test_class.new.test_rewrite_instance_method}.from(2).to(6)
50
+
51
+ expect(test_class.included_modules).to include(
52
+ RubyFeatures::Mixins::DefineTestModule::DefineTestClass::RewriteInstanceMethodsFeature::DefineTestModule::DefineTestClass::RewriteInstance
53
+ )
54
+ end
55
+
34
56
  it 'should process applied block' do
35
57
  expect{
36
58
  define_test_feature('applied_block') do
@@ -75,4 +97,14 @@ describe RubyFeatures::Concern::Feature do
75
97
  }.to raise_error(/Tried to include already existing methods: \[:existing_instance_method\]/)
76
98
  end
77
99
 
100
+ it 'should raise error if target has no feature rewrite instance method' do
101
+ expect{
102
+ define_test_feature('not_existing_rewrite_instance_method') do
103
+ rewrite_instance_methods do
104
+ def not_existing_instance_method; end
105
+ end
106
+ end.apply
107
+ }.to raise_error(/Tried to prepend not existing methods: \[:not_existing_instance_method\]/)
108
+ end
109
+
78
110
  end
metadata CHANGED
@@ -1,30 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-features
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
5
- prerelease:
4
+ version: 1.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Sergey Tokarenko
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2015-06-01 00:00:00.000000000 Z
11
+ date: 2016-08-26 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  description: Makes extending of Ruby classes and modules to be easy, safe and controlled.
@@ -33,23 +30,23 @@ executables: []
33
30
  extensions: []
34
31
  extra_rdoc_files: []
35
32
  files:
33
+ - LICENSE
34
+ - README.md
36
35
  - lib/generators/ruby_features/install_generator.rb
37
36
  - lib/generators/ruby_features/templates/ruby-features.rb
37
+ - lib/ruby-features.rb
38
38
  - lib/ruby-features/concern/apply_to.rb
39
39
  - lib/ruby-features/concern/feature.rb
40
40
  - lib/ruby-features/conditions.rb
41
41
  - lib/ruby-features/container.rb
42
42
  - lib/ruby-features/lazy.rb
43
43
  - lib/ruby-features/mixins.rb
44
+ - lib/ruby-features/utils.rb
44
45
  - lib/ruby-features/utils/const_accessor_19.rb
45
46
  - lib/ruby-features/utils/const_accessor_20.rb
46
47
  - lib/ruby-features/utils/inflector.rb
47
48
  - lib/ruby-features/utils/inflector_active_support.rb
48
- - lib/ruby-features/utils.rb
49
49
  - lib/ruby-features/version.rb
50
- - lib/ruby-features.rb
51
- - LICENSE
52
- - README.md
53
50
  - spec/conditions_spec.rb
54
51
  - spec/define_spec.rb
55
52
  - spec/find_and_apply_spec.rb
@@ -62,27 +59,26 @@ files:
62
59
  homepage: https://github.com/stokarenko/ruby-features
63
60
  licenses:
64
61
  - MIT
62
+ metadata: {}
65
63
  post_install_message:
66
64
  rdoc_options: []
67
65
  require_paths:
68
66
  - lib
69
67
  required_ruby_version: !ruby/object:Gem::Requirement
70
- none: false
71
68
  requirements:
72
- - - ! '>='
69
+ - - ">="
73
70
  - !ruby/object:Gem::Version
74
- version: 1.9.3
71
+ version: 2.0.0
75
72
  required_rubygems_version: !ruby/object:Gem::Requirement
76
- none: false
77
73
  requirements:
78
- - - ! '>='
74
+ - - ">="
79
75
  - !ruby/object:Gem::Version
80
76
  version: '0'
81
77
  requirements: []
82
78
  rubyforge_project:
83
- rubygems_version: 1.8.23.2
79
+ rubygems_version: 2.5.1
84
80
  signing_key:
85
- specification_version: 3
81
+ specification_version: 4
86
82
  summary: Makes extending of Ruby classes and modules to be easy, safe and controlled.
87
83
  test_files:
88
84
  - spec/conditions_spec.rb