decent_exposure 2.0.0 → 2.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.
data/README.md
CHANGED
@@ -284,7 +284,7 @@ This block is evaluated and the memoized result is returned whenever you call
|
|
284
284
|
|
285
285
|
For the times when custom behavior is needed for resource finding,
|
286
286
|
`decent_exposure` provides a base class for extending. For example, if
|
287
|
-
scoping a resource from `current_user` is not
|
287
|
+
scoping a resource from `current_user` is not an option, but you'd like
|
288
288
|
to verify a resource's relationship to the `current_user`, you can use a
|
289
289
|
custom strategy like the following:
|
290
290
|
|
@@ -353,4 +353,52 @@ And opt into it like so:
|
|
353
353
|
expose(:article, config: :sluggable)
|
354
354
|
```
|
355
355
|
|
356
|
-
|
356
|
+
## Testing
|
357
|
+
|
358
|
+
Controller testing remains trivially easy. The shift is that you now set expectations on methods rather than instance variables. With RSpec, this mostly means avoiding `assign` and `assigns`.
|
359
|
+
|
360
|
+
```ruby
|
361
|
+
describe CompaniesController do
|
362
|
+
describe "GET index" do
|
363
|
+
|
364
|
+
# this...
|
365
|
+
it "assigns @companies" do
|
366
|
+
company = Company.create
|
367
|
+
get :index
|
368
|
+
assigns(:companies).should eq([company])
|
369
|
+
end
|
370
|
+
|
371
|
+
# becomes this
|
372
|
+
it "exposes companies" do
|
373
|
+
company = Company.create
|
374
|
+
get :index
|
375
|
+
controller.companies.should eq([company])
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
```
|
380
|
+
|
381
|
+
View specs follow a similar pattern:
|
382
|
+
|
383
|
+
```ruby
|
384
|
+
describe "people/index.html.erb" do
|
385
|
+
|
386
|
+
# this...
|
387
|
+
it "lists people" do
|
388
|
+
assign(:people, [ mock_model(Person, name: 'John Doe') ])
|
389
|
+
render
|
390
|
+
rendered.should have_content('John Doe')
|
391
|
+
end
|
392
|
+
|
393
|
+
# becomes this
|
394
|
+
it "lists people" do
|
395
|
+
view.stub(people: [ mock_model(Person, name: 'John Doe') ])
|
396
|
+
render
|
397
|
+
rendered.should have_content('John Doe')
|
398
|
+
end
|
399
|
+
|
400
|
+
end
|
401
|
+
```
|
402
|
+
|
403
|
+
|
404
|
+
[1]: http://blog.voxdolo.me/a-diatribe-on-maintaining-state.html
|
@@ -2,19 +2,20 @@ require 'decent_exposure/active_record_strategy'
|
|
2
2
|
|
3
3
|
module DecentExposure
|
4
4
|
class ActiveRecordWithEagerAttributesStrategy < ActiveRecordStrategy
|
5
|
-
delegate :get?,
|
5
|
+
delegate :get?, :to => :request
|
6
|
+
delegate :delete?, :to => :request
|
6
7
|
|
7
8
|
def singular?
|
8
9
|
!plural?
|
9
10
|
end
|
10
11
|
|
11
12
|
def attributes
|
12
|
-
params[inflector.singular]
|
13
|
+
params[inflector.singular] || {}
|
13
14
|
end
|
14
15
|
|
15
16
|
def assign_attributes?
|
16
17
|
return false unless attributes && singular?
|
17
|
-
!get? || new_record?
|
18
|
+
(!get? && !delete?) || new_record?
|
18
19
|
end
|
19
20
|
|
20
21
|
def new_record?
|
@@ -7,7 +7,7 @@ module DecentExposure
|
|
7
7
|
def initialize(name, strategy, options)
|
8
8
|
self.strategy = strategy
|
9
9
|
self.options = options
|
10
|
-
self.inflector = DecentExposure::Inflector.new(name)
|
10
|
+
self.inflector = DecentExposure::Inflector.new(name, options[:model])
|
11
11
|
end
|
12
12
|
|
13
13
|
def call(controller)
|
@@ -1,22 +1,23 @@
|
|
1
1
|
require 'active_support/inflector'
|
2
|
-
require 'active_support/core_ext/string
|
2
|
+
require 'active_support/core_ext/string'
|
3
3
|
|
4
4
|
module DecentExposure
|
5
5
|
class Inflector
|
6
|
-
attr_reader :string, :original
|
6
|
+
attr_reader :string, :original, :model
|
7
7
|
alias name string
|
8
8
|
|
9
|
-
def initialize(name)
|
10
|
-
@original = name
|
11
|
-
@
|
9
|
+
def initialize(name, model=nil)
|
10
|
+
@original = name.to_s
|
11
|
+
@model = model
|
12
|
+
@string = (model || name).to_s.demodulize
|
12
13
|
end
|
13
14
|
|
14
15
|
def constant(context=Object)
|
15
|
-
case
|
16
|
+
case model
|
16
17
|
when Module, Class
|
17
|
-
|
18
|
+
model
|
18
19
|
else
|
19
|
-
context
|
20
|
+
ConstantResolver.new(context, string.classify).constant
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
@@ -25,7 +26,7 @@ module DecentExposure
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def singular
|
28
|
-
string.parameterize
|
29
|
+
@singular ||= string.singularize.parameterize
|
29
30
|
end
|
30
31
|
|
31
32
|
def plural
|
@@ -34,7 +35,37 @@ module DecentExposure
|
|
34
35
|
alias collection plural
|
35
36
|
|
36
37
|
def plural?
|
37
|
-
|
38
|
+
original.pluralize == original && !uncountable?
|
39
|
+
end
|
40
|
+
|
41
|
+
def uncountable?
|
42
|
+
original.pluralize == original.singularize
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
ConstantResolver = Struct.new :context, :constant_name do
|
48
|
+
|
49
|
+
def constant
|
50
|
+
immediate_child || namespace_qualified
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def immediate_child
|
56
|
+
context.constants.map do |c|
|
57
|
+
context.const_get(c) if c.to_s == constant_name
|
58
|
+
end.compact.first
|
59
|
+
end
|
60
|
+
|
61
|
+
def namespace_qualified
|
62
|
+
namespace.const_get(constant_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def namespace
|
66
|
+
path = context.to_s
|
67
|
+
path[0...(path.rindex('::') || 0)].constantize
|
68
|
+
end
|
38
69
|
end
|
39
70
|
end
|
40
71
|
end
|
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: decent_exposure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0
|
5
4
|
prerelease:
|
5
|
+
version: 2.0.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Stephen Caudill
|
@@ -11,72 +11,72 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-
|
14
|
+
date: 2012-12-14 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
|
-
|
18
|
-
requirement: !ruby/object:Gem::Requirement
|
19
|
-
none: false
|
17
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
18
|
requirements:
|
21
19
|
- - ~>
|
22
20
|
- !ruby/object:Gem::Version
|
23
21
|
version: '2.7'
|
22
|
+
none: false
|
23
|
+
name: rspec
|
24
24
|
type: :development
|
25
25
|
prerelease: false
|
26
|
-
|
27
|
-
none: false
|
26
|
+
requirement: !ruby/object:Gem::Requirement
|
28
27
|
requirements:
|
29
28
|
- - ~>
|
30
29
|
- !ruby/object:Gem::Version
|
31
30
|
version: '2.7'
|
32
|
-
- !ruby/object:Gem::Dependency
|
33
|
-
name: rspec-rails
|
34
|
-
requirement: !ruby/object:Gem::Requirement
|
35
31
|
none: false
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
34
|
requirements:
|
37
35
|
- - ~>
|
38
36
|
- !ruby/object:Gem::Version
|
39
37
|
version: '2.7'
|
38
|
+
none: false
|
39
|
+
name: rspec-rails
|
40
40
|
type: :development
|
41
41
|
prerelease: false
|
42
|
-
|
43
|
-
none: false
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
44
43
|
requirements:
|
45
44
|
- - ~>
|
46
45
|
- !ruby/object:Gem::Version
|
47
46
|
version: '2.7'
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: actionpack
|
50
|
-
requirement: !ruby/object:Gem::Requirement
|
51
47
|
none: false
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
50
|
requirements:
|
53
51
|
- - ~>
|
54
52
|
- !ruby/object:Gem::Version
|
55
53
|
version: '3.1'
|
54
|
+
none: false
|
55
|
+
name: actionpack
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
|
59
|
-
none: false
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
60
59
|
requirements:
|
61
60
|
- - ~>
|
62
61
|
- !ruby/object:Gem::Version
|
63
62
|
version: '3.1'
|
64
|
-
- !ruby/object:Gem::Dependency
|
65
|
-
name: activesupport
|
66
|
-
requirement: !ruby/object:Gem::Requirement
|
67
63
|
none: false
|
64
|
+
- !ruby/object:Gem::Dependency
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
66
|
requirements:
|
69
67
|
- - ~>
|
70
68
|
- !ruby/object:Gem::Version
|
71
69
|
version: '3.1'
|
70
|
+
none: false
|
71
|
+
name: activesupport
|
72
72
|
type: :development
|
73
73
|
prerelease: false
|
74
|
-
|
75
|
-
none: false
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
76
75
|
requirements:
|
77
76
|
- - ~>
|
78
77
|
- !ruby/object:Gem::Version
|
79
78
|
version: '3.1'
|
79
|
+
none: false
|
80
80
|
description: ! "\n DecentExposure helps you program to an interface, rather than
|
81
81
|
an\n implementation in your Rails controllers. The fact of the matter is that\n
|
82
82
|
\ sharing state via instance variables in controllers promotes close coupling\n
|
@@ -107,17 +107,17 @@ rdoc_options:
|
|
107
107
|
require_paths:
|
108
108
|
- lib
|
109
109
|
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
-
none: false
|
111
110
|
requirements:
|
112
111
|
- - ! '>='
|
113
112
|
- !ruby/object:Gem::Version
|
114
113
|
version: '0'
|
115
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
114
|
none: false
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
116
|
requirements:
|
118
117
|
- - ! '>='
|
119
118
|
- !ruby/object:Gem::Version
|
120
119
|
version: 1.3.6
|
120
|
+
none: false
|
121
121
|
requirements: []
|
122
122
|
rubyforge_project:
|
123
123
|
rubygems_version: 1.8.24
|