simple_exposure 0.0.2 → 0.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +71 -7
- data/lib/simple_exposure/core.rb +33 -9
- data/lib/simple_exposure/version.rb +1 -1
- data/simple_exposure.gemspec +0 -1
- data/spec/controllers/application_controller_spec.rb +71 -0
- data/spec/dummy/app/controllers/application_controller.rb +27 -3
- data/spec/dummy/app/views/application/index.html.erb +0 -7
- data/spec/spec_helper.rb +0 -6
- metadata +5 -20
- data/spec/integration/simple_exposure_spec.rb +0 -21
- data/spec/simple_exposure/core_spec.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4ac6213c3f38471d413641334b633e9f930c36a
|
4
|
+
data.tar.gz: cffbf6e5672dbf1ec8feebb49ecd3f0e5396441b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 28f0a6fbac384b2adc6ed468e9c82ae0835c86ab8c3107093364166c93d43811c5329d6489aa2c752bd5da224ccd85d5afc8be6a36a98a91b44a34f6af5b54ad
|
7
|
+
data.tar.gz: 73217785155e4003aa33ebe131b90d1807341d320624dec4ef9efc1c612a5a5f74f9ab1f625196b53062bfce3f398d05f0016f6969d0af4e3cd2b50dcf46cad5
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
## v0.1.0
|
2
|
+
|
3
|
+
+ Added extension shortcuts (e.g. `paginate :users`)
|
4
|
+
+ Moved UnknownExtension exception directly to SimpleExposure namespace (SimpleExposure::UnknownExtension)
|
5
|
+
|
6
|
+
## v0.0.2
|
7
|
+
|
8
|
+
+ Don't apply extensions when no value is provided
|
9
|
+
|
10
|
+
## v0.0.1
|
11
|
+
|
12
|
+
+ Initial impementation
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# SimpleExposure
|
2
2
|
|
3
|
-

|
3
|
+

|
4
4
|

|
5
5
|

|
6
6
|

|
@@ -22,6 +22,8 @@ end
|
|
22
22
|
p = project.title
|
23
23
|
```
|
24
24
|
|
25
|
+
Wait, there's more!
|
26
|
+
|
25
27
|
## Installation
|
26
28
|
|
27
29
|
Add this line to your application's Gemfile:
|
@@ -43,11 +45,15 @@ Or install it yourself as:
|
|
43
45
|
```ruby
|
44
46
|
# controllers/projects_controller.rb
|
45
47
|
class ProjectsController < ApplicationController
|
46
|
-
expose :projects
|
48
|
+
expose :projects, :project
|
47
49
|
|
48
50
|
def index
|
49
51
|
self.projects = Project.all
|
50
52
|
end
|
53
|
+
|
54
|
+
def show
|
55
|
+
self.project = Project.find(1)
|
56
|
+
end
|
51
57
|
end
|
52
58
|
|
53
59
|
# views/projects/index.html.slim
|
@@ -55,6 +61,21 @@ end
|
|
55
61
|
p = project.title
|
56
62
|
```
|
57
63
|
|
64
|
+
Expose controller methods to the views:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
# controllers/projects_controller.rb
|
68
|
+
class ProjectsController < ApplicationController
|
69
|
+
expose :project
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def project
|
74
|
+
@project ||= Project.find(1)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
58
79
|
### Provide default values
|
59
80
|
|
60
81
|
```ruby
|
@@ -73,12 +94,23 @@ class ProjectsController < ApplicationController
|
|
73
94
|
def index
|
74
95
|
@projects = Project.page(params[:page])
|
75
96
|
end
|
76
|
-
|
77
97
|
end
|
78
98
|
```
|
79
99
|
|
80
100
|
After:
|
81
101
|
|
102
|
+
```ruby
|
103
|
+
class ProjectsController < ApplicationController
|
104
|
+
paginate :projects
|
105
|
+
|
106
|
+
def index
|
107
|
+
self.projects = Project.all
|
108
|
+
end
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
Which is the same as:
|
113
|
+
|
82
114
|
```ruby
|
83
115
|
class ProjectsController < ApplicationController
|
84
116
|
expose :projects, extend: :paginate
|
@@ -91,6 +123,31 @@ end
|
|
91
123
|
|
92
124
|
### Combine multiple extensions
|
93
125
|
|
126
|
+
Before:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
class ProjectsController < ApplicationController
|
130
|
+
|
131
|
+
def index
|
132
|
+
@projects = Project.page(params[:page]).decorate
|
133
|
+
end
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
After:
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
class ProjectsController < ApplicationController
|
141
|
+
paginate :projects, extend: :decorate
|
142
|
+
|
143
|
+
def index
|
144
|
+
self.projects = Project.all
|
145
|
+
end
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
Which is the same as:
|
150
|
+
|
94
151
|
```ruby
|
95
152
|
class ProjectsController < ApplicationController
|
96
153
|
expose :projects, extend: %i(paginate decorate)
|
@@ -121,15 +178,13 @@ After:
|
|
121
178
|
|
122
179
|
```ruby
|
123
180
|
class ProjectsController < ApplicationController
|
124
|
-
|
181
|
+
decorate :current_user
|
125
182
|
|
126
183
|
expose :projects do
|
127
184
|
current_user.projects.ordered
|
128
185
|
end
|
129
186
|
|
130
|
-
|
131
|
-
projects.completed
|
132
|
-
end
|
187
|
+
paginate(:completed_projects) { projects.completed }
|
133
188
|
end
|
134
189
|
```
|
135
190
|
|
@@ -158,10 +213,19 @@ module SimpleExposure
|
|
158
213
|
end
|
159
214
|
|
160
215
|
class ProjectsController < ApplicationController
|
216
|
+
my_extension :projects
|
217
|
+
# or
|
161
218
|
expose :projects, extend: :my_extension
|
162
219
|
end
|
163
220
|
```
|
164
221
|
|
222
|
+
Note that extensions are applied at the time of `render`, not immediately when the value is assigned.
|
223
|
+
|
224
|
+
## Similar projects
|
225
|
+
|
226
|
+
+ [view_accessor](https://github.com/invisiblefunnel/view_accessor)
|
227
|
+
+ [obviews](https://github.com/elia/obviews)
|
228
|
+
+ [decent_exposure](https://github.com/voxdolo/decent_exposure)
|
165
229
|
|
166
230
|
## Contributing
|
167
231
|
|
data/lib/simple_exposure/core.rb
CHANGED
@@ -2,20 +2,21 @@ require 'simple_exposure/extensions/paginate'
|
|
2
2
|
require 'simple_exposure/extensions/decorate'
|
3
3
|
|
4
4
|
module SimpleExposure
|
5
|
+
UnknownExtension = Class.new(NameError)
|
6
|
+
|
5
7
|
module Core
|
6
8
|
extend ActiveSupport::Concern
|
7
9
|
|
8
|
-
UnknownExtension = Class.new(NameError)
|
9
|
-
|
10
10
|
included do
|
11
11
|
delegate :_exposure_extensions, to: :class
|
12
|
+
delegate :_exposure_extension_class, to: :class
|
12
13
|
before_render :_apply_exposure_extensions
|
13
14
|
end
|
14
15
|
|
15
16
|
def _apply_exposure_extensions
|
16
17
|
_exposure_extensions.each do |attribute, extensions|
|
17
18
|
extensions.each do |extension|
|
18
|
-
_apply_exposure_extension(attribute, extension)
|
19
|
+
_apply_exposure_extension(attribute, extension.to_s)
|
19
20
|
end
|
20
21
|
end
|
21
22
|
end
|
@@ -29,12 +30,6 @@ module SimpleExposure
|
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
|
-
def _exposure_extension_class(extension)
|
33
|
-
Extensions.const_get(extension.camelize)
|
34
|
-
rescue NameError
|
35
|
-
raise UnknownExtension, "Unknown extension: #{extension}"
|
36
|
-
end
|
37
|
-
|
38
33
|
module ClassMethods
|
39
34
|
|
40
35
|
def expose(*attributes, &block)
|
@@ -51,6 +46,12 @@ module SimpleExposure
|
|
51
46
|
@_exposure_extensions ||= HashWithIndifferentAccess.new([])
|
52
47
|
end
|
53
48
|
|
49
|
+
def _exposure_extension_class(extension)
|
50
|
+
Extensions.const_get(extension.camelize)
|
51
|
+
rescue NameError
|
52
|
+
raise UnknownExtension, "Unknown extension: #{extension}"
|
53
|
+
end
|
54
|
+
|
54
55
|
private
|
55
56
|
|
56
57
|
def _define_exposure_accessors(attributes, &block)
|
@@ -92,6 +93,29 @@ module SimpleExposure
|
|
92
93
|
_exposure_extensions[attribute] += extensions
|
93
94
|
end
|
94
95
|
end
|
96
|
+
|
97
|
+
def method_missing(extension, *attributes, &block)
|
98
|
+
extension_class = _exposure_extension_class(extension.to_s)
|
99
|
+
if extension_class
|
100
|
+
options = attributes.extract_options!
|
101
|
+
|
102
|
+
extensions = options.fetch(:extend, nil)
|
103
|
+
extensions = Array(extensions)
|
104
|
+
extensions = extensions.prepend(extension)
|
105
|
+
|
106
|
+
options = options.merge(extend: extensions)
|
107
|
+
|
108
|
+
expose(*attributes, options, &block)
|
109
|
+
end
|
110
|
+
rescue UnknownExtension
|
111
|
+
super
|
112
|
+
end
|
113
|
+
|
114
|
+
def respond_to_missing?(extension, include_private = false)
|
115
|
+
_exposure_extension_class(extension.to_s)
|
116
|
+
rescue UnknownExtension
|
117
|
+
false
|
118
|
+
end
|
95
119
|
end
|
96
120
|
end
|
97
121
|
end
|
data/simple_exposure.gemspec
CHANGED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ApplicationController, type: :controller do
|
4
|
+
let(:view) { controller.view_context }
|
5
|
+
|
6
|
+
it 'loads the modules' do
|
7
|
+
expect(described_class.ancestors).to include(SimpleExposure::Core)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'responds to #expose' do
|
11
|
+
expect(described_class).to respond_to(:expose)
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
get :index
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'Inline definition of multiple exposed attributes' do
|
19
|
+
it 'exposes multiple attributes defined inline' do
|
20
|
+
expect(view.my_name).to eq 'Jane Doe'
|
21
|
+
expect(view.your_name).to eq 'Jane Doe'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'Default values' do
|
26
|
+
it 'assigns default value' do
|
27
|
+
expect(view.message).to eq 'Hello!'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'does not override provided values with default one' do
|
31
|
+
expect(view.other_message).to eq 'Other message'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'Exposing controllers instance variables' do
|
36
|
+
it 'exposes the value in ivar' do
|
37
|
+
expect(view.ivar_message).to eq 'Hello!'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'Exposing private methods' do
|
42
|
+
it 'exposes controllers private methods' do
|
43
|
+
expect(view.current_user).to eq 'mikekreeki'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'Extensions' do
|
48
|
+
it 'applies extension when value provided' do
|
49
|
+
expect(view.decoratable_message).to eq 'Hello!'
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'does not apply extension when value not provided' do
|
53
|
+
expect(view.nil_value).to be_nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'Extension shortcuts' do
|
58
|
+
it 'quacks like a shortcut' do
|
59
|
+
expect(described_class).to respond_to :decorate
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'applies the extension when specified using a shortcut' do
|
63
|
+
expect(view.second_user).to eq 'Andrew Bennett'
|
64
|
+
expect(view.third_user).to eq 'Andrew Bennett'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'takes additional extensions' do
|
68
|
+
expect(view.combined_extension).to eq 'HELLO'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,18 +1,42 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
1
3
|
class ApplicationController < ActionController::Base
|
2
4
|
# Prevent CSRF attacks by raising an exception.
|
3
5
|
# For APIs, you may want to use :null_session instead.
|
4
6
|
protect_from_forgery with: :exception
|
5
7
|
|
6
|
-
expose(:
|
8
|
+
expose(:my_name, :your_name) { 'Jane Doe' }
|
9
|
+
|
10
|
+
expose(:message) { 'Hello!' }
|
11
|
+
expose(:other_message) { 'Hello!' }
|
12
|
+
expose(:ivar_message)
|
7
13
|
|
8
14
|
expose(:current_user)
|
9
15
|
|
10
|
-
expose(:
|
16
|
+
expose(:decoratable_message, extend: :decorate) do
|
17
|
+
OpenStruct.new(decorate: 'Hello!')
|
18
|
+
end
|
11
19
|
|
12
20
|
expose(:nil_value, extend: :decorate)
|
13
21
|
|
22
|
+
decorate(:second_user, :third_user) { OpenStruct.new(decorate: 'Andrew Bennett') }
|
23
|
+
|
24
|
+
paginate :combined_extension, extend: :decorate do
|
25
|
+
Class.new do
|
26
|
+
def page(*)
|
27
|
+
@name = 'Hello'
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def decorate
|
32
|
+
@name.upcase
|
33
|
+
end
|
34
|
+
end.new
|
35
|
+
end
|
36
|
+
|
14
37
|
def index
|
15
|
-
|
38
|
+
self.other_message = 'Other message'
|
39
|
+
@ivar_message = 'Hello!'
|
16
40
|
end
|
17
41
|
|
18
42
|
private
|
data/spec/spec_helper.rb
CHANGED
@@ -2,12 +2,6 @@ ENV['RAILS_ENV'] ||= 'test'
|
|
2
2
|
require File.expand_path('../dummy/config/environment', __FILE__)
|
3
3
|
|
4
4
|
require 'rspec/rails'
|
5
|
-
require 'capybara/rspec'
|
6
|
-
|
7
|
-
# Requires supporting ruby files with custom matchers and macros, etc,
|
8
|
-
# in spec/support/ and its subdirectories.
|
9
|
-
Dir[Rails.root.join('spec/support/**/*.rb')].each {|f| require f}
|
10
5
|
|
11
6
|
RSpec.configure do |config|
|
12
|
-
config.include Capybara::DSL, type: :integration
|
13
7
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_exposure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michal Krejčí
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -44,20 +44,6 @@ dependencies:
|
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: 3.0.0
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: capybara
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ">="
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - ">="
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: '0'
|
61
47
|
description: Cleanup your Rails controllers
|
62
48
|
email:
|
63
49
|
- work@mikekreeki.com
|
@@ -69,6 +55,7 @@ files:
|
|
69
55
|
- ".ruby-gemset"
|
70
56
|
- ".ruby-version"
|
71
57
|
- ".travis.yml"
|
58
|
+
- CHANGELOG.md
|
72
59
|
- Gemfile
|
73
60
|
- LICENSE.txt
|
74
61
|
- README.md
|
@@ -80,6 +67,7 @@ files:
|
|
80
67
|
- lib/simple_exposure/extensions/paginate.rb
|
81
68
|
- lib/simple_exposure/version.rb
|
82
69
|
- simple_exposure.gemspec
|
70
|
+
- spec/controllers/application_controller_spec.rb
|
83
71
|
- spec/dummy/.gitignore
|
84
72
|
- spec/dummy/Gemfile
|
85
73
|
- spec/dummy/README.rdoc
|
@@ -134,8 +122,6 @@ files:
|
|
134
122
|
- spec/dummy/test/test_helper.rb
|
135
123
|
- spec/dummy/vendor/assets/javascripts/.keep
|
136
124
|
- spec/dummy/vendor/assets/stylesheets/.keep
|
137
|
-
- spec/integration/simple_exposure_spec.rb
|
138
|
-
- spec/simple_exposure/core_spec.rb
|
139
125
|
- spec/spec_helper.rb
|
140
126
|
homepage: https://github.com/mikekreeki/simple_exposure
|
141
127
|
licenses:
|
@@ -162,6 +148,7 @@ signing_key:
|
|
162
148
|
specification_version: 4
|
163
149
|
summary: Cleanup your Rails controllers
|
164
150
|
test_files:
|
151
|
+
- spec/controllers/application_controller_spec.rb
|
165
152
|
- spec/dummy/.gitignore
|
166
153
|
- spec/dummy/Gemfile
|
167
154
|
- spec/dummy/README.rdoc
|
@@ -216,6 +203,4 @@ test_files:
|
|
216
203
|
- spec/dummy/test/test_helper.rb
|
217
204
|
- spec/dummy/vendor/assets/javascripts/.keep
|
218
205
|
- spec/dummy/vendor/assets/stylesheets/.keep
|
219
|
-
- spec/integration/simple_exposure_spec.rb
|
220
|
-
- spec/simple_exposure/core_spec.rb
|
221
206
|
- spec/spec_helper.rb
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe SimpleExposure, type: :integration do
|
4
|
-
it 'loads the modules' do
|
5
|
-
expect(ActionController::Base.ancestors).to include(SimpleExposure::Core)
|
6
|
-
end
|
7
|
-
|
8
|
-
let(:controller) { ApplicationController.new }
|
9
|
-
|
10
|
-
it 'can see the content' do
|
11
|
-
visit '/'
|
12
|
-
|
13
|
-
controller.index
|
14
|
-
|
15
|
-
expect(page).to have_content controller.send(:message)
|
16
|
-
expect(page).to have_content controller.send(:current_user)
|
17
|
-
expect(page).to have_content controller.send(:posts_count)
|
18
|
-
end
|
19
|
-
|
20
|
-
|
21
|
-
end
|