adequate_exposure 0.0.4 → 0.0.5
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 +4 -4
- data/.travis.yml +4 -0
- data/README.md +136 -33
- data/adequate_exposure.gemspec +2 -4
- data/lib/adequate_exposure/attribute.rb +4 -2
- data/lib/adequate_exposure/exposure.rb +3 -1
- data/lib/adequate_exposure/flow.rb +4 -4
- data/lib/adequate_exposure/version.rb +1 -1
- data/spec/controller_spec.rb +2 -2
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 331663a8f718896cab6be3800c0af9fc98379e8b
|
4
|
+
data.tar.gz: e942a3866cdd940adf9dd9e08e979b68b8456446
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ce222e1500bce49ee95bc6eec47bc7f4956591070fba3b9acf5e5a3e3585296da02c79bb82c6532e65acf7049e39833709e8efe8032a8de58b18a6da26eaf59
|
7
|
+
data.tar.gz: 9e292f24fbf0242ee15b8bb41483a2aa73def2316373612645d94c99592430c31ba41bfc3be9d243326e29f5ee62084ec7e408b3da4b12a5201dd07dcf7645d2
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,22 +1,23 @@
|
|
1
1
|
# Adequate Exposure
|
2
|
-
|
3
|
-
|
2
|
+
[](https://rubygems.org/gems/adequate_exposure)
|
3
|
+
[](http://travis-ci.org/rwz/adequate_exposure)
|
4
|
+
[](https://codeclimate.com/github/rwz/adequate_exposure)
|
4
5
|
|
5
6
|
Exposing things, adequately.
|
6
7
|
|
7
8
|
Adequate exposure is a lightweight alternative to [Decent
|
8
|
-
Exposure](https://github.com/voxdolo/decent_exposure). With
|
9
|
+
Exposure](https://github.com/voxdolo/decent_exposure). With its narrowly
|
9
10
|
focused api you can get exactly what you need without all the extra dressing.
|
10
11
|
|
11
12
|
*Note: It is not the intent of the author to imply that Decent Exposure is
|
12
|
-
inadequate
|
13
|
+
inadequate.*
|
13
14
|
|
14
15
|
Installation is as simple as: `$ gem install adequate_exposure`. Once you have
|
15
16
|
that down we can start talking about the API.
|
16
17
|
|
17
18
|
## API
|
18
19
|
|
19
|
-
The whole API consists of
|
20
|
+
The whole API consists of two methods so far: `expose` and `expose!`.
|
20
21
|
|
21
22
|
In the simplest scenario you'll just use it to expose a model in the
|
22
23
|
controller:
|
@@ -28,28 +29,29 @@ end
|
|
28
29
|
```
|
29
30
|
|
30
31
|
Now every time you call `thing` in your controller or view, it'll look for an
|
31
|
-
|
32
|
-
|
32
|
+
ID and try to perform `Thing.find(id)`. If the ID isn't found, it'll call
|
33
|
+
`Thing.new(things_params)`. The result will be memoized in an `@exposed_thing`
|
34
|
+
instance variable.
|
33
35
|
|
34
36
|
The default resolving workflow if pretty powerful and customizable. It could be
|
35
37
|
expressed with the following pseudocode:
|
36
38
|
|
37
39
|
```ruby
|
38
40
|
def fetch(scope, id)
|
39
|
-
instance = id ? find(id, scope) : build(scope)
|
41
|
+
instance = id ? find(id, scope) : build(build_params, scope)
|
40
42
|
decorate(instance)
|
41
43
|
end
|
42
44
|
|
43
45
|
def id
|
44
|
-
params[:
|
46
|
+
params[:thing_id] || params[:id]
|
45
47
|
end
|
46
48
|
|
47
49
|
def find(id, scope)
|
48
|
-
scope.find(id)
|
50
|
+
scope.find(id)
|
49
51
|
end
|
50
52
|
|
51
|
-
def build(scope)
|
52
|
-
scope.new(
|
53
|
+
def build(params, scope)
|
54
|
+
scope.new(params) # Thing.new(params)
|
53
55
|
end
|
54
56
|
|
55
57
|
def scope
|
@@ -73,75 +75,176 @@ def decorate(thing)
|
|
73
75
|
end
|
74
76
|
```
|
75
77
|
|
78
|
+
The exposure is also lazy, which means that it won't do anything until you call
|
79
|
+
the method. To eliminate this lazyness you can use `expose!` macro instead,
|
80
|
+
which will try to resolve the exposure in a before filter.
|
81
|
+
|
76
82
|
Each step could be overrided with options. The acceptable options to the
|
77
83
|
`expose` macro are:
|
78
84
|
|
79
|
-
|
85
|
+
### `fetch`
|
80
86
|
|
81
|
-
This is the entry point.
|
82
|
-
first place.
|
87
|
+
This is the entry point. The `fetch` proc defines how to resolve your exposure
|
88
|
+
in the first place.
|
83
89
|
|
84
90
|
```ruby
|
85
91
|
expose :thing, fetch: ->{ get_thing_some_way_or_another }
|
86
92
|
```
|
87
93
|
|
88
|
-
|
94
|
+
Because the above behavior overrides the normal workflow, all other options
|
95
|
+
would be ignored. However, Adequate Exposure is decent enough to actually blow
|
96
|
+
up with an error so you don't accidentally do this.
|
89
97
|
|
90
|
-
|
91
|
-
|
98
|
+
There are other less verbose ways to pass the `fetch` block, since you'll
|
99
|
+
probably be using it often:
|
92
100
|
|
93
101
|
```ruby
|
94
|
-
expose
|
102
|
+
expose(:thing){ get_thing_some_way_or_another }
|
95
103
|
```
|
96
104
|
|
97
|
-
|
105
|
+
Or if you (like me) absolutely hate parens in side-effect methods:
|
98
106
|
|
99
|
-
|
107
|
+
```ruby
|
108
|
+
expose :thing, ->{ get_thing_some_way_or_another }
|
109
|
+
```
|
110
|
+
|
111
|
+
There is another shortcut that allows you to redefine entire fetch block with
|
112
|
+
less code:
|
100
113
|
|
101
114
|
```ruby
|
102
|
-
expose :
|
115
|
+
expose :comments, from: :post
|
116
|
+
# equivalent to
|
117
|
+
expose :comments, ->{ post.comments }
|
103
118
|
```
|
104
119
|
|
105
|
-
|
120
|
+
### `id`
|
121
|
+
|
122
|
+
The default fetch logic relies on the presence of an ID. And of course Adequate
|
123
|
+
Exposure allows to to specify how exactly you want the ID to be extracted.
|
106
124
|
|
107
|
-
|
125
|
+
Default behavior could be expressed using following code:
|
108
126
|
|
109
127
|
```ruby
|
110
|
-
# default
|
111
128
|
expose :thing, id: ->{ params[:thing_id] || params[:id] }
|
129
|
+
```
|
112
130
|
|
113
|
-
|
131
|
+
But nothing is stopping you from throwing in any arbitrary code:
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
# id is always gonna be the answer to ultimate question of life, the universe,
|
135
|
+
# and everyting
|
114
136
|
expose :thing, id: ->{ 42 }
|
137
|
+
```
|
115
138
|
|
139
|
+
Passing lambdas might not always be fun, so here are couple shortcuts that could
|
140
|
+
help making life easier.
|
141
|
+
|
142
|
+
```ruby
|
116
143
|
# equivalent to id: ->{ params[:custom_thing_id] }
|
117
144
|
expose :thing, id: :custom_thing_id
|
118
145
|
|
119
146
|
# equivalent to id: ->{ params[:try_this_id] || params[:or_maybe_that_id] }
|
120
|
-
expose :thing, id:
|
147
|
+
expose :thing, id: [:try_this_id, :or_maybe_that_id]
|
148
|
+
```
|
149
|
+
|
150
|
+
### `find`
|
151
|
+
|
152
|
+
If an ID was provided, Adequate Exposure will try to find the model using it.
|
153
|
+
Default behavior could be expressed with this configuration:
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
expose :thing, find: ->(id, scope){ scope.find(id) }
|
157
|
+
```
|
158
|
+
|
159
|
+
Where `scope` is a model scope, like `Thing` or `User.active` or
|
160
|
+
`Post.published`.
|
161
|
+
|
162
|
+
Now, if you're using FriendlyId or Stringex or something similar, you'd have to
|
163
|
+
customize your finding logic. You code might look somewhat like this:
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
expose :thing, find: ->(id, scope){ scope.find_by!(slug: id) }
|
167
|
+
```
|
168
|
+
|
169
|
+
Again, because this is likely to happen a lot, Adequate Exposure gives you a
|
170
|
+
decent shortcut so you can get more done by typing less.
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
expose :thing, find_by: :slug
|
121
174
|
```
|
122
175
|
|
123
|
-
|
176
|
+
### `build`
|
177
|
+
|
178
|
+
When an ID is not present, Adequate Exposure tries to build an object for you. By
|
179
|
+
default, it behaves like this:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
expose :thing, build: ->(thing_params, scope){ scope.new(thing_params) }
|
183
|
+
```
|
184
|
+
|
185
|
+
### `build_params`
|
186
|
+
|
187
|
+
This options is responsible for calulating params before passing it to the
|
188
|
+
build step. The default behavior was modeled with Strong Parameters in mind and
|
189
|
+
is somewhat smart: it calls `thing_params` controller method if it's available
|
190
|
+
and request method it not `GET`. In all other cases it produces an empty hash.
|
191
|
+
|
192
|
+
You can easily specify which controller method you want it to call instead of
|
193
|
+
`thing_params`, or just provide your own logic:
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
expose :thing, build_params: :custom_thing_params
|
197
|
+
expose :other_thing, build_params: ->{ { foo: "bar" } }
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def custom_thing_params
|
202
|
+
# strong parameters stuff goes here
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
206
|
+
### `scope`
|
124
207
|
|
125
208
|
Defines the scope that's used in `find` and `build` steps.
|
126
209
|
|
127
210
|
```ruby
|
128
211
|
expose :thing, scope: ->{ current_user.things }
|
212
|
+
expose :user, scope: ->{ User.active }
|
213
|
+
expose :post, scope: ->{ Post.published }
|
214
|
+
```
|
215
|
+
|
216
|
+
Like before, shortcuts are there to make you happier:
|
217
|
+
|
218
|
+
```ruby
|
219
|
+
expose :post, scope: :published
|
220
|
+
# fully equivalent to
|
221
|
+
expose :post, scope: ->{ Post.published }
|
222
|
+
```
|
223
|
+
|
224
|
+
and
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
expose :thing, parent: :current_user
|
228
|
+
# fully equivalent to:
|
229
|
+
expose :thing, scope: ->{ current_user.things }
|
129
230
|
```
|
130
231
|
|
131
|
-
|
232
|
+
### `model`
|
132
233
|
|
133
|
-
|
234
|
+
Allows to specify the model class to use. Pretty straightforward.
|
134
235
|
|
135
236
|
```ruby
|
136
237
|
expose :thing, model: ->{ AnotherThing }
|
137
238
|
expose :thing, model: AnotherThing
|
239
|
+
expose :thing, model: "AnotherThing"
|
138
240
|
expose :thing, model: :another_thing
|
139
241
|
```
|
140
242
|
|
243
|
+
### `decorate`
|
141
244
|
|
142
|
-
|
143
|
-
|
144
|
-
|
245
|
+
Before returning the thing, Adequate Exposure will run it through the
|
246
|
+
decoration process. Initially, this does nothing, but you can obviously change
|
247
|
+
that:
|
145
248
|
|
146
249
|
```ruby
|
147
250
|
expose :thing, decorate: ->(thing){ ThingDecorator.new(thing) }
|
data/adequate_exposure.gemspec
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
4
2
|
require "adequate_exposure/version"
|
5
3
|
|
6
4
|
Gem::Specification.new do |spec|
|
@@ -15,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
15
13
|
spec.test_files = spec.files.grep(/\Aspec\//)
|
16
14
|
spec.require_path = "lib"
|
17
15
|
|
18
|
-
spec.required_ruby_version = "
|
16
|
+
spec.required_ruby_version = ">= 1.9.3"
|
19
17
|
|
20
18
|
spec.add_dependency "railties", "~> 4.0"
|
21
19
|
spec.add_dependency "activesupport", "~> 4.0"
|
@@ -2,8 +2,10 @@ module AdequateExposure
|
|
2
2
|
class Attribute
|
3
3
|
attr_reader :name, :fetch, :ivar_name
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@name
|
5
|
+
def initialize(options)
|
6
|
+
@name = options.fetch(:name)
|
7
|
+
@fetch = options.fetch(:fetch)
|
8
|
+
@ivar_name = options.fetch(:ivar_name)
|
7
9
|
end
|
8
10
|
|
9
11
|
def getter_method_name
|
@@ -6,8 +6,10 @@ module AdequateExposure
|
|
6
6
|
new(*args, &block).expose!
|
7
7
|
end
|
8
8
|
|
9
|
-
def initialize(controller, name,
|
9
|
+
def initialize(controller, name, *args, &block)
|
10
10
|
@controller = controller
|
11
|
+
options = args.extract_options!
|
12
|
+
fetch_block = args.pop
|
11
13
|
@options = options.with_indifferent_access.merge(name: name)
|
12
14
|
|
13
15
|
merge_lambda_option :fetch, fetch_block if fetch_block
|
@@ -11,7 +11,7 @@ module AdequateExposure
|
|
11
11
|
options.fetch(:name)
|
12
12
|
end
|
13
13
|
|
14
|
-
%
|
14
|
+
%w[fetch find build build_params scope model id decorate].each do |method_name|
|
15
15
|
define_method method_name do |*args|
|
16
16
|
ivar_name = "@#{method_name}"
|
17
17
|
return instance_variable_get(ivar_name) if instance_variable_defined?(ivar_name)
|
@@ -23,7 +23,7 @@ module AdequateExposure
|
|
23
23
|
|
24
24
|
def default_fetch
|
25
25
|
computed_scope = scope(model)
|
26
|
-
instance = id ? find(id, computed_scope) : build(computed_scope)
|
26
|
+
instance = id ? find(id, computed_scope) : build(build_params, computed_scope)
|
27
27
|
decorate(instance)
|
28
28
|
end
|
29
29
|
|
@@ -43,8 +43,8 @@ module AdequateExposure
|
|
43
43
|
scope.find(id)
|
44
44
|
end
|
45
45
|
|
46
|
-
def default_build(scope)
|
47
|
-
scope.new(
|
46
|
+
def default_build(params, scope)
|
47
|
+
scope.new(params)
|
48
48
|
end
|
49
49
|
|
50
50
|
def default_decorate(instance)
|
data/spec/controller_spec.rb
CHANGED
@@ -22,7 +22,7 @@ describe AdequateExposure::Controller do
|
|
22
22
|
let(:controller){ controller_klass.new }
|
23
23
|
before{ allow(controller).to receive(:request){ request } }
|
24
24
|
|
25
|
-
%
|
25
|
+
%w[expose expose!].each do |method_name|
|
26
26
|
define_method method_name do |*args, &block|
|
27
27
|
controller_klass.send method_name, *args, &block
|
28
28
|
end
|
@@ -274,7 +274,7 @@ describe AdequateExposure::Controller do
|
|
274
274
|
end
|
275
275
|
|
276
276
|
it "allows overriding id with an array of symbols" do
|
277
|
-
expose :thing, id: %
|
277
|
+
expose :thing, id: %w[non-existent-id lolwut another_id_param]
|
278
278
|
controller.params.merge! another_id_param: 42
|
279
279
|
end
|
280
280
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adequate_exposure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pavel Pravosud
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -46,6 +46,7 @@ extensions: []
|
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
48
|
- ".gitignore"
|
49
|
+
- ".travis.yml"
|
49
50
|
- Gemfile
|
50
51
|
- LICENSE.txt
|
51
52
|
- README.md
|
@@ -72,9 +73,9 @@ require_paths:
|
|
72
73
|
- lib
|
73
74
|
required_ruby_version: !ruby/object:Gem::Requirement
|
74
75
|
requirements:
|
75
|
-
- - "
|
76
|
+
- - ">="
|
76
77
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
78
|
+
version: 1.9.3
|
78
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
80
|
requirements:
|
80
81
|
- - ">="
|