context-pattern 1.0.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.
@@ -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: []