request_store_rails 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +265 -0
- data/lib/request_locals.rb +87 -0
- data/lib/request_store_rails/middleware.rb +29 -0
- data/lib/request_store_rails/railtie.rb +14 -0
- data/lib/request_store_rails/version.rb +5 -0
- data/lib/request_store_rails.rb +5 -0
- metadata +114 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: b4179f342e1c92035d2daf543887e02c5b2e5620
|
|
4
|
+
data.tar.gz: ae71e457d209160ae4ccc736f93cb252769640ff
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 480eee450b8cc4f6d9fb105ceaf9ef1520123cb8b9298466b53a22b7ebd8fadcb459349c3700668407787fcee6e6497a5037b5ccf0d5b0876e9b2aaf0ead3c09
|
|
7
|
+
data.tar.gz: e8cfc0b07cd322fd4dffa9209f9743a88ac1021a9506e913e7be7e4c3c4305a49c6992ffe3455a79745052249cb8eca154c237a8618fa49d6598da3bf5f9d866
|
data/README.md
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
Queryable
|
|
2
|
+
=====================
|
|
3
|
+
[](http://badge.fury.io/rb/queryable)
|
|
4
|
+
[](https://travis-ci.org/ElMassimo/queryable)
|
|
5
|
+
[](https://codeclimate.com/github/ElMassimo/queryable)
|
|
6
|
+
[](https://codeclimate.com/github/ElMassimo/queryable)
|
|
7
|
+
[](http://inch-ci.org/github/ElMassimo/queryable)
|
|
8
|
+
[](https://github.com/ElMassimo/queryable/blob/master/LICENSE.txt)
|
|
9
|
+
<!-- [](https://coveralls.io/r/ElMassimo/queryable) -->
|
|
10
|
+
|
|
11
|
+
Queryable is a mixin that allows you to easily define query objects with chainable scopes.
|
|
12
|
+
|
|
13
|
+
### Scopes
|
|
14
|
+
|
|
15
|
+
Scopes serve to encapsulate reusable business rules, a method is defined with
|
|
16
|
+
the selected name and block (or proc)
|
|
17
|
+
```ruby
|
|
18
|
+
class CustomersQuery
|
|
19
|
+
include Queryable
|
|
20
|
+
|
|
21
|
+
scope(:recent) { desc(:logged_in_at) }
|
|
22
|
+
|
|
23
|
+
scope :active, ->{ where(status: 'active') }
|
|
24
|
+
|
|
25
|
+
scope :favourite_brand do |product, brand|
|
|
26
|
+
where("favourites.#{product}": brand)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def current
|
|
30
|
+
recent.active
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def miller_fans
|
|
34
|
+
favourite_brand(:beer, :Miller)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
CustomerQuery.new(shop.customers).miller_fans
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Delegation
|
|
43
|
+
|
|
44
|
+
By default most Array methods are delegated to the internal query. It's possible
|
|
45
|
+
to delegate extra methods to the query by calling `delegate`.
|
|
46
|
+
```ruby
|
|
47
|
+
class CustomersQuery
|
|
48
|
+
include Queryable
|
|
49
|
+
|
|
50
|
+
delegate :update_all, :destroy_all, :exists?
|
|
51
|
+
end
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Delegate and Chain
|
|
55
|
+
|
|
56
|
+
Sometimes you want to delegate a method to the internal query, but continue
|
|
57
|
+
working with the query object like if you were calling scopes.
|
|
58
|
+
|
|
59
|
+
You can achieve that using `delegate_and_chain`, which will delegate the method
|
|
60
|
+
call, assign the return value as the internal query, and return the query object.
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
class CustomersQuery
|
|
64
|
+
include Queryable
|
|
65
|
+
|
|
66
|
+
delegate_and_chain :where, :order_by
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Advantages
|
|
71
|
+
|
|
72
|
+
* Query objects are easy to understand.
|
|
73
|
+
* You can inherit, mixin, and chain queries in a very natural way.
|
|
74
|
+
* Increased testability, pretty close to being ORM/ODM agnostic.
|
|
75
|
+
|
|
76
|
+
## Basic Usage
|
|
77
|
+
|
|
78
|
+
If you are using Mongoid or ActiveRecord, you might want to try the
|
|
79
|
+
`Queryable::Mongoid` and `Queryable::ActiveRecord` modules that already take
|
|
80
|
+
care of delegating and chaining most of the methods in the underlying queries.
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
class CustomersQuery
|
|
84
|
+
include Queryable::Mongoid
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
CustomersQuery.new.where(:amount_purchased.gt => 2).active.asc(:logged_in_at)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This modules also include all the optional modules. If you would like to opt-out
|
|
91
|
+
of the other modules you can follow the approach in the [Notes](https://github.com/ElMassimo/queryable#notes) section.
|
|
92
|
+
|
|
93
|
+
## Advanced Usage
|
|
94
|
+
There are three opt-in modules that can help you when creating query objects.
|
|
95
|
+
These modules would need to be manually required during app initialization or
|
|
96
|
+
wherever necessary (in Rails, config/initializers).
|
|
97
|
+
|
|
98
|
+
### DefaultQuery
|
|
99
|
+
Provides default initialization for query objects, by attempting to infer the
|
|
100
|
+
class name of the default collection for the query, and it also provides a
|
|
101
|
+
`queryable` method to specify it.
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
require 'queryable/default_query'
|
|
105
|
+
|
|
106
|
+
def CustomersQuery
|
|
107
|
+
include Queryable
|
|
108
|
+
include Queryable::DefaultQuery
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def OldCustomersQuery < CustomersQuery
|
|
112
|
+
queryable ArchivedCustomers
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
CustomersQuery.new.queryable == Customer.all
|
|
116
|
+
OldCustomersQuery.new.queryable == ArchivedCustomers.all
|
|
117
|
+
```
|
|
118
|
+
If you want to use common base objects for your queries, you may want want to
|
|
119
|
+
delay the automatic inference:
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
class BaseQuery
|
|
123
|
+
include Queryable
|
|
124
|
+
include Queryable::DefaultQuery
|
|
125
|
+
|
|
126
|
+
queryable false
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
class CustomersQuery < BaseQuery
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
CustomersQuery.new.queryable == Customer.all
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### DefaultScope
|
|
136
|
+
Allows to define default scopes in query objects, and inherit them in query
|
|
137
|
+
object subclasses.
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
require 'queryable/default_scope'
|
|
141
|
+
|
|
142
|
+
def CustomersQuery
|
|
143
|
+
include Queryable
|
|
144
|
+
include Queryable::DefaultScope
|
|
145
|
+
include Queryable::DefaultQuery
|
|
146
|
+
|
|
147
|
+
default_scope :active
|
|
148
|
+
scope :active, -> { where(:last_purchase.gt => 7.days.ago) }
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def BigCustomersQuery < CustomersQuery
|
|
152
|
+
default_scope :big_spender
|
|
153
|
+
scope :big_spender, -> { where(:total_expense.gt => 9999999) }
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
CustomersQuery.new.queryable == Customer.where(:last_purchase.gt => 7.days.ago)
|
|
157
|
+
|
|
158
|
+
BigCustomersQuery.new.queryable ==
|
|
159
|
+
Customer.where(:last_purchase.gt => 7.days.ago, :total_expense.gt => 9999999)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Chainable
|
|
163
|
+
|
|
164
|
+
While scopes are great because of their terseness, they can be limiting because
|
|
165
|
+
the block executes in the context of the internal query, so methods, constants,
|
|
166
|
+
and variables of the Queryable are not accessible.
|
|
167
|
+
|
|
168
|
+
For those cases, you can use a normal method, and then `chain` it. Chainable
|
|
169
|
+
will take care of setting the return value of the method as the internal query,
|
|
170
|
+
and return `self` at the end to make the method chainable.
|
|
171
|
+
|
|
172
|
+
```ruby
|
|
173
|
+
class CustomersQuery
|
|
174
|
+
include Queryable
|
|
175
|
+
include Queryable::Chainable
|
|
176
|
+
|
|
177
|
+
chain :active, :recent
|
|
178
|
+
|
|
179
|
+
def active
|
|
180
|
+
where(status: 'active')
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def recent
|
|
184
|
+
queryable.desc(:logged_in_at)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
chain def search(field_values)
|
|
188
|
+
field_values.inject(queryable) { |query, (field, value)|
|
|
189
|
+
query.where(field => /#{value}/i)
|
|
190
|
+
}
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def search_in_active(field_values)
|
|
194
|
+
search(field_values).active
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
CustomerQuery.new(shop.customers).miller_fans.search_in_current(last_name: 'M')
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Notes
|
|
203
|
+
To avoid repetition, it's a good idea to create a `BaseQuery` object
|
|
204
|
+
to contain both the modules inclusion, and common scopes you may reuse.
|
|
205
|
+
|
|
206
|
+
```ruby
|
|
207
|
+
require 'queryable/chainable'
|
|
208
|
+
require 'queryable/default_scope'
|
|
209
|
+
require 'queryable/default_query'
|
|
210
|
+
|
|
211
|
+
def BaseQuery
|
|
212
|
+
include Queryable
|
|
213
|
+
include Queryable::Chainable
|
|
214
|
+
include Queryable::DefaultScope
|
|
215
|
+
include Queryable::DefaultQuery
|
|
216
|
+
|
|
217
|
+
# If you want to be concise:
|
|
218
|
+
include Queryable::DefaultQuery, Queryable::DefaultScope, Queryable::Chainable, Queryable
|
|
219
|
+
|
|
220
|
+
queryable false
|
|
221
|
+
|
|
222
|
+
scope :recent, ->{ where(:created_at.gt => 1.week.ago) }
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def CustomersQuery < BaseQuery
|
|
226
|
+
...
|
|
227
|
+
end
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Testing
|
|
231
|
+
|
|
232
|
+
You can check the [specs](https://github.com/ElMassimo/queryable/tree/master/spec) of the project
|
|
233
|
+
to check how to test query objects without even having to require the ORM/ODM, or
|
|
234
|
+
you can test by requiring your ORM/ODM and executing queries as usual.
|
|
235
|
+
|
|
236
|
+
## RDocs
|
|
237
|
+
|
|
238
|
+
You can view the **Queryable** documentation in RDoc format here:
|
|
239
|
+
|
|
240
|
+
http://rubydoc.info/github/ElMassimo/queryable/master/frames
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
License
|
|
244
|
+
--------
|
|
245
|
+
|
|
246
|
+
Copyright (c) 2014 Máximo Mussini
|
|
247
|
+
|
|
248
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
249
|
+
a copy of this software and associated documentation files (the
|
|
250
|
+
"Software"), to deal in the Software without restriction, including
|
|
251
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
252
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
253
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
254
|
+
the following conditions:
|
|
255
|
+
|
|
256
|
+
The above copyright notice and this permission notice shall be
|
|
257
|
+
included in all copies or substantial portions of the Software.
|
|
258
|
+
|
|
259
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
260
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
261
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
262
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
263
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
264
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
265
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require 'singleton'
|
|
2
|
+
require 'thread_safe'
|
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
|
4
|
+
|
|
5
|
+
# Public: Provides per-request global storage, by offering an interface that is
|
|
6
|
+
# very similar to Rails.cache, or Hash.
|
|
7
|
+
#
|
|
8
|
+
# The store may be shared between threads, as long as the :request_id
|
|
9
|
+
# thread-local variable is set.
|
|
10
|
+
#
|
|
11
|
+
# Intended to work in collaboration with the RequestStoreRails middleware, that
|
|
12
|
+
# will clear the request local variables after each request.
|
|
13
|
+
class RequestLocals
|
|
14
|
+
include Singleton
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
|
|
18
|
+
# Public: Public methods of RequestLocals, they are delegated to the Singleton instance.
|
|
19
|
+
delegate :clear!, :clear_all!, :[], :[]=, :fetch, :delete, :exist?, :empty?, to: :instance
|
|
20
|
+
|
|
21
|
+
# Public: There is no accounting for taste, RequestLocals[:foo] vs RequestLocals.store[:foo]
|
|
22
|
+
alias_method :store, :instance
|
|
23
|
+
|
|
24
|
+
# Internal: We don't want to expose the Singleton implementation details.
|
|
25
|
+
private :instance
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Internal: Methods of the RequestLocals instance, delegated to the request-local structure.
|
|
29
|
+
delegate :[], :[]=, :delete, :empty?, to: :store
|
|
30
|
+
|
|
31
|
+
def initialize
|
|
32
|
+
@cache = ThreadSafe::Cache.new
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Public: Removes all the request-local variables.
|
|
36
|
+
#
|
|
37
|
+
# Returns nothing.
|
|
38
|
+
def clear!
|
|
39
|
+
@cache.delete(current_request_id)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Public: Clears all the request-local variable stores.
|
|
43
|
+
#
|
|
44
|
+
# Returns nothing.
|
|
45
|
+
def clear_all!
|
|
46
|
+
@cache = ThreadSafe::Cache.new
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Public: Checks if a value was stored for the given key.
|
|
50
|
+
#
|
|
51
|
+
# Returns true if there is a value stored for the key.
|
|
52
|
+
def exist?(key)
|
|
53
|
+
store.key?(key)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Public: Implements fetch in a consistent way with Rails.cache, persisting
|
|
57
|
+
# the value yielded by the block if the key was not found.
|
|
58
|
+
#
|
|
59
|
+
# Returns an existing value for the key is found, otherwise it returns the
|
|
60
|
+
# value yielded by the block.
|
|
61
|
+
def fetch(key, &block)
|
|
62
|
+
store.fetch_or_store(key, &block)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
protected
|
|
66
|
+
|
|
67
|
+
# Internal: Returns the structure that holds the request-local variables for
|
|
68
|
+
# the current request.
|
|
69
|
+
#
|
|
70
|
+
# Returns a ThreadSafe::Cache.
|
|
71
|
+
def store
|
|
72
|
+
@cache.fetch_or_store(current_request_id) { new_store }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Internal: The current request is inferred from the current thread. It's very
|
|
76
|
+
# important to pass on the :request_id thread local variable when spawning new
|
|
77
|
+
# threads within a single request.
|
|
78
|
+
def current_request_id
|
|
79
|
+
Thread.current[:request_id]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Internal: Returns a new empty structure where the request-local variables
|
|
83
|
+
# will be stored.
|
|
84
|
+
def new_store
|
|
85
|
+
ThreadSafe::Cache.new
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
|
|
3
|
+
# Public: Middleware that takes care of setting the thread-local variable
|
|
4
|
+
# :request_id, which enables RequestLocals to associate threads and requests.
|
|
5
|
+
module RequestStoreRails
|
|
6
|
+
class Middleware
|
|
7
|
+
|
|
8
|
+
def initialize(app)
|
|
9
|
+
@app = app
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Internal: Assigns the :request_id thread-local variable, and cleans up all
|
|
13
|
+
# the request-local variables after the request.
|
|
14
|
+
def call(env)
|
|
15
|
+
Thread.current[:request_id] = extract_request_id(env)
|
|
16
|
+
@app.call(env)
|
|
17
|
+
ensure
|
|
18
|
+
RequestLocals.clear!
|
|
19
|
+
Thread.current[:request_id] = nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
protected
|
|
23
|
+
|
|
24
|
+
# Internal: Extracts the request id from the environment, or generates one.
|
|
25
|
+
def extract_request_id(env)
|
|
26
|
+
env['action_dispatch.request_id'] || env['HTTP_X_REQUEST_ID'] || SecureRandom.hex(16)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Internal: Inserts the middleware to manage request_ids and cleaning up after
|
|
2
|
+
# the request is complete.
|
|
3
|
+
module RequestStoreRails
|
|
4
|
+
class Railtie < ::Rails::Railtie
|
|
5
|
+
|
|
6
|
+
initializer 'request_store_rails.insert_middleware' do |app|
|
|
7
|
+
app.config.middleware.insert_after ActionDispatch::RequestId, RequestStoreRails::Middleware
|
|
8
|
+
|
|
9
|
+
ActionDispatch::Reloader.to_cleanup do
|
|
10
|
+
RequestLocals.clear_all!
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: request_store_rails
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Máximo Mussini
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-04-11 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rake
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: minitest
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '5.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '5.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: thread_safe
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.3'
|
|
48
|
+
- - ">="
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: 0.3.5
|
|
51
|
+
type: :runtime
|
|
52
|
+
prerelease: false
|
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
54
|
+
requirements:
|
|
55
|
+
- - "~>"
|
|
56
|
+
- !ruby/object:Gem::Version
|
|
57
|
+
version: '0.3'
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: 0.3.5
|
|
61
|
+
- !ruby/object:Gem::Dependency
|
|
62
|
+
name: rails
|
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.2'
|
|
68
|
+
type: :runtime
|
|
69
|
+
prerelease: false
|
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '3.2'
|
|
75
|
+
description: RequestLocals gives you per-request global storage in Rails
|
|
76
|
+
email:
|
|
77
|
+
- maximomussini@gmail.com
|
|
78
|
+
executables: []
|
|
79
|
+
extensions: []
|
|
80
|
+
extra_rdoc_files:
|
|
81
|
+
- README.md
|
|
82
|
+
files:
|
|
83
|
+
- README.md
|
|
84
|
+
- lib/request_locals.rb
|
|
85
|
+
- lib/request_store_rails.rb
|
|
86
|
+
- lib/request_store_rails/middleware.rb
|
|
87
|
+
- lib/request_store_rails/railtie.rb
|
|
88
|
+
- lib/request_store_rails/version.rb
|
|
89
|
+
homepage: https://github.com/ElMassimo/request_store_rails
|
|
90
|
+
licenses:
|
|
91
|
+
- MIT
|
|
92
|
+
metadata: {}
|
|
93
|
+
post_install_message:
|
|
94
|
+
rdoc_options:
|
|
95
|
+
- "--charset=UTF-8"
|
|
96
|
+
require_paths:
|
|
97
|
+
- lib
|
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: 1.9.3
|
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
|
+
requirements:
|
|
105
|
+
- - ">="
|
|
106
|
+
- !ruby/object:Gem::Version
|
|
107
|
+
version: '0'
|
|
108
|
+
requirements: []
|
|
109
|
+
rubyforge_project:
|
|
110
|
+
rubygems_version: 2.4.3
|
|
111
|
+
signing_key:
|
|
112
|
+
specification_version: 4
|
|
113
|
+
summary: Per-request global storage for Rails
|
|
114
|
+
test_files: []
|