context-pattern 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 160ec1333c94272d332b55acccaee5b32435a2d6
4
+ data.tar.gz: 96a764e13dec3cad58a5e43639f59946daf63bb2
5
+ SHA512:
6
+ metadata.gz: ae92a3e686f0164548e11d882c4e19bec842ed29198a62b432e0868524e95b719aee3125e152e17e91cf20758aec29d7f448cc9fde994ecf22d56195f123b7a2
7
+ data.tar.gz: 7d2f947aaf3a9e3a4ca66de889e0a78e597e2df35824acb1da4cf34acf71ac229aef9b62d3345fb8bc1a443a1013f25009fd5bd911256ac6670a4a08186c17a9
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ .DS_Store
3
+ .ruby-version
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ # The AR environment variable lets you test against different
5
+ # versions of Rails. For example:
6
+ #
7
+ # AR=3.2.13 rm Gemfile.lock && bundle install && bundle exec rspec
8
+ # AR=4.0.0 rm Gemfile.lock && bundle install && bundle exec rspec
9
+ #
10
+ if ENV['AR']
11
+ gem 'activerecord', ENV['AR']
12
+ end
@@ -0,0 +1,22 @@
1
+ The MIT LICENSE
2
+
3
+ Copyright (c) 2019 Appfolio Inc.
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.
@@ -0,0 +1 @@
1
+ # context-pattern
@@ -0,0 +1,6 @@
1
+ desc 'Run tests'
2
+ task :test do |t|
3
+ sh 'rspec spec'
4
+ end
5
+
6
+ task :default => :test
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'rubygems' unless defined? Gem
3
+ require File.dirname(__FILE__) + "/lib/context/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "context-pattern"
7
+ s.version = Context::VERSION
8
+ s.authors = ["Barun Singh"]
9
+ s.email = "bsingh@wegowise.com"
10
+ s.homepage = "http://github.com/barunio/context-pattern"
11
+ s.summary = "Start using the Context Pattern in your Rails app"
12
+ s.description = "Start using the Context Pattern in your Rails app"
13
+ s.required_rubygems_version = ">= 1.3.6"
14
+ s.files = `git ls-files`.split("\n")
15
+ s.require_paths = ['lib']
16
+ s.extra_rdoc_files = ["README.md", "LICENSE.txt"]
17
+ s.license = 'MIT'
18
+
19
+ s.add_dependency('rails', '>= 3.2', '< 5.2')
20
+ s.add_dependency('memoizer')
21
+
22
+ s.add_development_dependency('rspec', '~> 3.0')
23
+ s.add_development_dependency('rake', '>= 10.4')
24
+ end
@@ -0,0 +1,4 @@
1
+ require 'context/base_context'
2
+ require 'context/controller'
3
+
4
+ require 'context/railtie' if defined?(Rails)
@@ -0,0 +1,121 @@
1
+ require 'rails'
2
+ require 'memoizer'
3
+
4
+ module Context
5
+ class MethodOverrideError < ::StandardError
6
+ def initialize(context_class, method_names)
7
+ @context_class = context_class
8
+ @method_names = method_names
9
+ end
10
+
11
+ def message
12
+ "#{@context_class.name} can not overwrite methods already defined in "\
13
+ "the context chain: #{@method_names}"
14
+ end
15
+ end
16
+
17
+ class BaseContext
18
+ include Memoizer
19
+ delegate :link_to, to: 'ActionController::Base.helpers'
20
+
21
+ class << self
22
+ include Memoizer
23
+
24
+ def decorate(ancestor_context_method, decorator:, args: [], memoize: false)
25
+ define_method(ancestor_context_method) do
26
+ decorator.new(
27
+ @parent_context.public_send(ancestor_context_method),
28
+ *(args.map { |arg| instance_eval(arg.to_s) })
29
+ )
30
+ end
31
+
32
+ @decorated_methods ||= []
33
+ @decorated_methods << ancestor_context_method.to_sym
34
+
35
+ if memoize
36
+ public_send(:memoize, ancestor_context_method)
37
+ @decorated_methods << "_unmemoized_#{ancestor_context_method}".to_sym
38
+ end
39
+ end
40
+
41
+ def is_decorated?(method_name)
42
+ @decorated_methods.is_a?(Array) &&
43
+ @decorated_methods.include?(method_name.to_sym)
44
+ end
45
+
46
+ def has_view_helper?(method_name)
47
+ @view_helpers.is_a?(Array) && @view_helpers.include?(method_name.to_sym)
48
+ end
49
+
50
+ def view_helpers(*method_names)
51
+ @view_helpers ||= []
52
+ @view_helpers += method_names.map(&:to_sym)
53
+ end
54
+
55
+ def wrap(parent_context, **args)
56
+ existing_public_methods = parent_context.context_method_mapping.keys
57
+ new_public_methods = public_instance_methods(false)
58
+ redefined_methods = existing_public_methods & new_public_methods
59
+ redefined_methods.reject! { |method| is_decorated?(method) }
60
+
61
+ unless redefined_methods.empty?
62
+ raise Context::MethodOverrideError.new(self, redefined_methods)
63
+ end
64
+
65
+ new(parent_context: parent_context, **args)
66
+ end
67
+ end
68
+
69
+ attr_accessor :parent_context
70
+
71
+ def initialize(attributes = {})
72
+ attributes.each do |k, v|
73
+ if respond_to?(:"#{k}=")
74
+ then public_send(:"#{k}=", v)
75
+ else raise ArgumentError, "unknown attribute: #{k}"
76
+ end
77
+ end
78
+ end
79
+
80
+ def context_class_chain
81
+ @context_class_chain ||=
82
+ ((@parent_context.try(:context_class_chain) || []) + [self.class.name])
83
+ end
84
+
85
+ def has_view_helper?(method_name)
86
+ self.class.has_view_helper?(method_name) ||
87
+ (@parent_context.present? &&
88
+ @parent_context.has_view_helper?(method_name))
89
+ end
90
+
91
+ def context_method_mapping
92
+ @context_method_mapping ||=
93
+ (@parent_context.try(:context_method_mapping) || {})
94
+ .merge(get_context_method_mapping)
95
+ end
96
+
97
+ def method_missing(method_name, *args, &block)
98
+ if @parent_context
99
+ @parent_context.public_send(method_name, *args, &block)
100
+ else
101
+ super
102
+ end
103
+ end
104
+
105
+ def respond_to_missing?(method_name, include_private = false)
106
+ @parent_context&.respond_to?(method_name, include_private)
107
+ end
108
+
109
+ def whereis(method_name)
110
+ context_method_mapping[method_name.to_sym]
111
+ end
112
+
113
+ private
114
+
115
+ def get_context_method_mapping
116
+ self.class.public_instance_methods(false).reduce({}) do |hash, method_name|
117
+ hash.merge!(method_name => self.class.name)
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,16 @@
1
+ module Context
2
+ module Controller
3
+ def self.included(base)
4
+ base.send(:prepend_before_action, :__set_base_context)
5
+ end
6
+
7
+ def extend_context(context, **args)
8
+ context_class = "#{context}Context".constantize
9
+ @context = context_class.wrap(@context, **args)
10
+ end
11
+
12
+ def __set_base_context
13
+ @context = Context::BaseContext.new
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ module Context
2
+ class Railtie < Rails::Railtie
3
+
4
+ initializer 'context-pattern.include_url_helpers_in_base_context' do
5
+ ActiveSupport.on_load :active_record do
6
+ Context::BaseContext.send :include, Rails.application.routes.url_helpers
7
+ end
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Context
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,391 @@
1
+ require 'context-pattern'
2
+
3
+ class TestDecorator
4
+ attr_accessor :decorator_val
5
+
6
+ def initialize(str, other_str = '')
7
+ self.decorator_val = "#{str}..#{other_str}"
8
+ end
9
+ end
10
+
11
+ class TestContext < Context::BaseContext
12
+ view_helpers :method1,
13
+ :method2
14
+
15
+ attr_accessor :foo
16
+
17
+ def method1
18
+ 'method1'
19
+ end
20
+
21
+ def method2
22
+ 'method2'
23
+ end
24
+
25
+ def method3
26
+ 'method3'
27
+ end
28
+
29
+ def bowie
30
+ "ziggy#{Random.rand}"
31
+ end
32
+
33
+ def random
34
+ Random.rand
35
+ end
36
+
37
+ def rolling
38
+ 'rolling'
39
+ end
40
+
41
+ protected
42
+
43
+ attr_accessor :bar1
44
+
45
+ def protected_method
46
+ 'protected_method'
47
+ end
48
+
49
+ private
50
+
51
+ def private_method
52
+ 'private_method'
53
+ end
54
+ end
55
+
56
+ class TestContext2 < Context::BaseContext
57
+ decorate :bowie, decorator: TestDecorator
58
+ decorate :random, decorator: TestDecorator, memoize: true
59
+ decorate :rolling, decorator: TestDecorator, args: [:stones]
60
+
61
+ attr_accessor :blah
62
+
63
+ private
64
+
65
+ def stones
66
+ 'stones'
67
+ end
68
+ end
69
+
70
+ class TestContext3 < Context::BaseContext
71
+ def alpha
72
+ 'alpha'
73
+ end
74
+ end
75
+
76
+ describe Context::BaseContext do
77
+ describe '.new' do
78
+ it 'accepts attributes when there are associated public setter methods' do
79
+ context = TestContext.new(foo: 1)
80
+ expect(context.foo).to eq(1)
81
+ end
82
+
83
+ it 'raises an ArgumentError if the setter is protected' do
84
+ method = :bar1
85
+ expect(TestContext.instance_methods.include?(method)).to eq(true)
86
+ expect { TestContext.new(method => 1) }
87
+ .to raise_error(ArgumentError, "unknown attribute: #{method}")
88
+ end
89
+
90
+ it 'raises an ArgumentError if the setter is private' do
91
+ method = :bar2
92
+ expect(TestContext.new.instance_eval("#{method} = 1")).to eq(1)
93
+ expect { TestContext.new(method => 1) }
94
+ .to raise_error(ArgumentError, "unknown attribute: #{method}")
95
+ end
96
+ end
97
+
98
+ describe '.has_view_helper?' do
99
+ it 'is true for declared view helpers' do
100
+ expect(TestContext.has_view_helper?(:method1)).to eq(true)
101
+ expect(TestContext.has_view_helper?('method2')).to eq(true)
102
+ end
103
+
104
+ it 'is false for public methods that are not declared as view helpers' do
105
+ method = :method3
106
+ expect(TestContext.public_instance_methods.include?(method)).to eq(true)
107
+ expect(TestContext.has_view_helper?(method)).to eq(false)
108
+ end
109
+ end
110
+
111
+ describe '.wrap' do
112
+ it 'returns a new instance with the `parent_context` attribute set to '\
113
+ 'the supplied context' do
114
+ contextA = TestContext.new
115
+ contextB = TestContext2.wrap(contextA)
116
+
117
+ expect(contextB.class).to eq(TestContext2)
118
+ expect(contextB.class.superclass).to eq(Context::BaseContext)
119
+ expect(contextB.parent_context).to eq(contextA)
120
+ end
121
+
122
+ it 'allows setting attributes when wrapping a context' do
123
+ contextA = TestContext.new
124
+ contextB = TestContext2.wrap(contextA, blah: 1)
125
+
126
+ expect(contextB.blah).to eq(1)
127
+ end
128
+
129
+ it 'allows accessing attributes of parent contexts after wrapping' do
130
+ contextA = TestContext.new(foo: 1)
131
+ contextB = TestContext2.wrap(contextA)
132
+
133
+ expect(contextB.foo).to eq(1)
134
+ end
135
+
136
+ it 'allows setting attributes of parent contexts when wrapping a context' do
137
+ contextA = TestContext.new
138
+ contextB = TestContext2.wrap(contextA, foo: 1)
139
+
140
+ expect(contextA.foo).to eq(1)
141
+ expect(contextB.foo).to eq(1)
142
+ end
143
+
144
+ it 'raises a MethodOverrideError if a context attempts to overwrite a '\
145
+ 'public instance method defined in a parent context' do
146
+ contextA = TestContext.new
147
+ other_context_class = Class.new(Context::BaseContext) do
148
+ def self.name
149
+ 'BadContext'
150
+ end
151
+
152
+ def method1
153
+ 'overwrite'
154
+ end
155
+ end
156
+
157
+ expect { other_context_class.wrap(contextA) }.to raise_error(
158
+ Context::MethodOverrideError,
159
+ 'BadContext can not overwrite methods already defined in the '\
160
+ 'context chain: [:method1]'
161
+ )
162
+ end
163
+
164
+ it 'allows overwriting non-public methods' do
165
+ contextA = TestContext.new
166
+ other_context_class = Class.new(Context::BaseContext) do
167
+ def private_method
168
+ 'overwrite'
169
+ end
170
+
171
+ def protected_method
172
+ 'overwrite'
173
+ end
174
+ end
175
+
176
+ expect { other_context_class.wrap(contextA) }.not_to raise_error
177
+ end
178
+ end
179
+
180
+ describe '.decorate is used in conjunction with `wrap` to provide an '\
181
+ 'explicit interface for decorating method values retrieved from earlier in '\
182
+ 'the context chain' do
183
+ let(:instance) { TestContext.new }
184
+ let(:instance2) { TestContext2.wrap(instance) }
185
+ let(:instance3) { TestContext3.wrap(instance2) }
186
+
187
+ it 'works when there are no arguments' do
188
+ allow(Random).to receive(:rand).and_return(1)
189
+
190
+ expect(instance.bowie).to eq('ziggy1')
191
+
192
+ decorated = instance2.bowie
193
+ expect(decorated).to be_a(TestDecorator)
194
+ expect(decorated.decorator_val).to eq('ziggy1..')
195
+ end
196
+
197
+ it 'works when there are arguments supplied to the decorator, with the '\
198
+ 'arguments coming from method evaluations in the context' do
199
+ expect(instance.rolling).to eq('rolling')
200
+
201
+ decorated = instance2.rolling
202
+ expect(decorated).to be_a(TestDecorator)
203
+ expect(decorated.decorator_val).to eq('rolling..stones')
204
+ end
205
+
206
+ it 'does not memoize by default' do
207
+ allow(Random).to receive(:rand).and_return(1, 2, 3)
208
+
209
+ expect(instance2.bowie.decorator_val).to eq('ziggy1..')
210
+ expect(instance2.bowie.decorator_val).to eq('ziggy2..')
211
+ end
212
+
213
+ it 'memoizes when the relevant option is set to true' do
214
+ allow(Random).to receive(:rand).and_return(1, 2, 3)
215
+
216
+ expect(instance2.random.decorator_val).to eq('1..')
217
+ expect(instance2.random.decorator_val).to eq('1..')
218
+ end
219
+
220
+ it 'cascades decorated values to contexts down the chain' do
221
+ cascaded_decorated = instance3.rolling
222
+ expect(cascaded_decorated).to be_a(TestDecorator)
223
+ expect(cascaded_decorated.decorator_val).to eq('rolling..stones')
224
+ end
225
+ end
226
+
227
+ describe '#context_class_chain' do
228
+ let(:instance) { TestContext.new(foo: 1) }
229
+ let(:instance2) { TestContext2.wrap(instance) }
230
+ let(:instance3) { TestContext3.wrap(instance2) }
231
+
232
+ it 'returns an array of all chained context class names in the order '\
233
+ 'they were wrapped' do
234
+ expect(instance.context_class_chain).to eq(['TestContext'])
235
+ expect(instance2.context_class_chain)
236
+ .to eq(['TestContext', 'TestContext2'])
237
+ expect(instance3.context_class_chain)
238
+ .to eq(['TestContext', 'TestContext2', 'TestContext3'])
239
+ end
240
+ end
241
+
242
+ describe '#has_view_helper?' do
243
+ let(:instance) { TestContext.new(foo: 1) }
244
+ let(:instance2) { TestContext2.wrap(instance) }
245
+ let(:instance3) { TestContext3.wrap(instance2) }
246
+
247
+ it 'is true for a declared view helper' do
248
+ expect(instance.has_view_helper?(:method1)).to eq(true)
249
+ expect(instance.has_view_helper?('method2')).to eq(true)
250
+ end
251
+
252
+ it 'is false for public methods not declared as view helpers' do
253
+ expect(instance.method3).to eq('method3')
254
+ expect(instance.has_view_helper?(:method3)).to eq(false)
255
+ end
256
+
257
+ it 'is true if a wrapped context has a certain declared view helper' do
258
+ expect(instance2.has_view_helper?(:method1)).to eq(true)
259
+ expect(instance2.has_view_helper?('method2')).to eq(true)
260
+ end
261
+
262
+ it 'is true if a grand-wrapped context has a declared view helper' do
263
+ expect(instance3.has_view_helper?(:method1)).to eq(true)
264
+ expect(instance3.has_view_helper?('method2')).to eq(true)
265
+ end
266
+ end
267
+
268
+ describe '#context_method_mapping' do
269
+ let(:instance) { TestContext.new }
270
+ let(:instance2) { TestContext2.wrap(instance) }
271
+ let(:instance3) { TestContext3.wrap(instance2) }
272
+
273
+ it 'returns a hash of public instance method names as keys and the '\
274
+ 'context name as values' do
275
+ expect(instance.context_method_mapping).to eq(
276
+ {
277
+ :bowie => 'TestContext',
278
+ :foo => 'TestContext',
279
+ :foo= => 'TestContext',
280
+ :method1 => 'TestContext',
281
+ :method2 => 'TestContext',
282
+ :method3 => 'TestContext',
283
+ :random => 'TestContext',
284
+ :rolling => 'TestContext',
285
+ }
286
+ )
287
+ end
288
+
289
+ it 'includes public instance methods from a wrapped context, with that '\
290
+ 'wrapped context class name as the associated value for those methods' do
291
+ expect(instance2.context_method_mapping).to eq(
292
+ {
293
+ :_unmemoized_random => 'TestContext2',
294
+ :blah => 'TestContext2',
295
+ :blah= => 'TestContext2',
296
+ :bowie => 'TestContext2',
297
+ :foo => 'TestContext',
298
+ :foo= => 'TestContext',
299
+ :method1 => 'TestContext',
300
+ :method2 => 'TestContext',
301
+ :method3 => 'TestContext',
302
+ :random => 'TestContext2',
303
+ :rolling => 'TestContext2'
304
+ }
305
+ )
306
+ end
307
+
308
+ it 'returns the expected values for multiple-wrapped contexts' do
309
+ expect(instance3.context_method_mapping).to eq(
310
+ {
311
+ :_unmemoized_random => 'TestContext2',
312
+ :alpha => 'TestContext3',
313
+ :blah => 'TestContext2',
314
+ :blah= => 'TestContext2',
315
+ :bowie => 'TestContext2',
316
+ :foo => 'TestContext',
317
+ :foo= => 'TestContext',
318
+ :method1 => 'TestContext',
319
+ :method2 => 'TestContext',
320
+ :method3 => 'TestContext',
321
+ :random => 'TestContext2',
322
+ :rolling => 'TestContext2'
323
+ }
324
+ )
325
+ end
326
+ end
327
+
328
+ describe '#whereis' do
329
+ let(:instance) { TestContext.new }
330
+ let(:instance2) { TestContext2.wrap(instance) }
331
+ let(:instance3) { TestContext3.wrap(instance2) }
332
+
333
+ it 'returns the name of the context class in the chain where a method is '\
334
+ 'defined' do
335
+ expect(instance3.whereis('foo=')).to eq('TestContext')
336
+ expect(instance3.whereis(:method2)).to eq('TestContext')
337
+ expect(instance3.whereis('blah')).to eq('TestContext2')
338
+ expect(instance3.whereis('alpha')).to eq('TestContext3')
339
+ end
340
+
341
+ it 'handles decorated methods, showing the class that most recently '\
342
+ 'did the decoration' do
343
+ expect(instance3.whereis(:bowie)).to eq('TestContext2')
344
+ end
345
+
346
+ it 'returns nil if the method is not a public method' do
347
+ expect(instance.instance_eval('protected_method'))
348
+ .to eq('protected_method')
349
+ expect(instance.whereis(:protected_method)).to eq(nil)
350
+
351
+ expect(instance.instance_eval('private_method')).to eq('private_method')
352
+ expect(instance.whereis(:private_method)).to eq(nil)
353
+ end
354
+
355
+ it 'returns nil if the method does not exist' do
356
+ expect(instance.whereis(:obladiblahda)).to eq(nil)
357
+ end
358
+ end
359
+
360
+ describe 'method_missing' do
361
+ let(:instance) { TestContext.new(foo: 1) }
362
+ let(:instance2) { TestContext2.wrap(instance) }
363
+ let(:instance3) { TestContext3.wrap(instance2) }
364
+
365
+ it 'responds to public methods from a wrapped context' do
366
+ expect(instance2.method3).to eq('method3')
367
+ end
368
+
369
+ it 'response to public methods from a grand-wrapped context' do
370
+ expect(instance3.method3).to eq('method3')
371
+ end
372
+
373
+ it 'does not respond to protected methods from a wrapped context' do
374
+ expect(instance.instance_eval('protected_method'))
375
+ .to eq('protected_method')
376
+
377
+ expect { instance2.instance_eval('protected_method') }
378
+ .to raise_error(NoMethodError)
379
+ expect { instance2.protected_method }.to raise_error(NoMethodError)
380
+ end
381
+
382
+ it 'does not respond to private methods from a wrapped context' do
383
+ expect(instance.instance_eval('private_method'))
384
+ .to eq('private_method')
385
+
386
+ expect { instance2.instance_eval('private_method') }
387
+ .to raise_error(NoMethodError)
388
+ expect { instance2.private_method }.to raise_error(NoMethodError)
389
+ end
390
+ end
391
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: context-pattern
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Barun Singh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: memoizer
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '10.4'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '10.4'
75
+ description: Start using the Context Pattern in your Rails app
76
+ email: bsingh@wegowise.com
77
+ executables: []
78
+ extensions: []
79
+ extra_rdoc_files:
80
+ - README.md
81
+ - LICENSE.txt
82
+ files:
83
+ - ".gitignore"
84
+ - Gemfile
85
+ - LICENSE.txt
86
+ - README.md
87
+ - Rakefile
88
+ - context-pattern.gemspec
89
+ - lib/context-pattern.rb
90
+ - lib/context/base_context.rb
91
+ - lib/context/controller.rb
92
+ - lib/context/railtie.rb
93
+ - lib/context/version.rb
94
+ - spec/base_context_spec.rb
95
+ homepage: http://github.com/barunio/context-pattern
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 1.3.6
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.6.14.1
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Start using the Context Pattern in your Rails app
119
+ test_files: []