pres 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 679fb7c90be5b08c135e46d8da2e64f94c3be04d
4
+ data.tar.gz: 005d0c7bd07a446107f2dd09c235f05eb6d3aa56
5
+ SHA512:
6
+ metadata.gz: 2bd353785c1572705fcd30ab41c6a240b80549de720e3a2d6444a9ef4f19fda8714d0d3b5180fce3318f55e30be09d7a68e9e71c395645199a5b84f71871d203
7
+ data.tar.gz: 41634e73d39c0836589804163e0e19c1eedaf869931c19dcdcfdfdd9aeca70737d98c770a6634b8f3ddc8752cb325d2720442a543bf068a50ae71cce34125cce
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+
3
+ if ENV["TRAVIS"]
4
+ gem "coveralls", require: false
5
+ end
6
+
7
+ if ENV["BYEBUG"]
8
+ gem "byebug"
9
+ end
10
+
11
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Neighborland, Inc.
2
+
3
+ MIT License
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.
data/README.md ADDED
@@ -0,0 +1,230 @@
1
+ # Pres: A Simple Rails Presenter
2
+
3
+ ## What?
4
+
5
+ A Presenter is a rendering class that wraps a model. Presenters are an
6
+ alternative to an unorganized mass of helper methods in your Rails application.
7
+
8
+ The `pres` gem is a lightweight presenter solution.
9
+
10
+ ## How and Why?
11
+
12
+ Decorators add methods to a model. `pres` does not do that. `pres` encourages you
13
+ to whitelist model methods (via delegation).
14
+
15
+ Other presenter libraries mix in all the methods from the Rails ViewContext to
16
+ make it easy to call those methods in the Presenter class. This causes method
17
+ bloat. `pres` instead injects the ViewContext as a dependency into the
18
+ Presenter class, and uses `method_missing` to delegate to those methods.
19
+
20
+ ## Install
21
+
22
+ Add it to your Gemfile:
23
+
24
+ ```ruby
25
+ gem "pres"
26
+ ```
27
+
28
+ Include the `Presents` module:
29
+
30
+ ```ruby
31
+ class ApplicationController
32
+ include Presents
33
+ end
34
+ ```
35
+
36
+ Add `app/presenters` to your application's autoload paths in `application.rb`:
37
+
38
+ ```ruby
39
+ config.autoload_paths += %W( #{ config.root }/app/presenters )
40
+ ```
41
+
42
+ #### Example Usage
43
+
44
+ Create a presenter class in `app/presenters`:
45
+
46
+ ```ruby
47
+ class DogePresenter < Presenter
48
+ # explicitly delegate methods to the model
49
+ delegate :name, to: :object
50
+
51
+ def know_your_meme_link
52
+ # Rails helpers are available via the view context
53
+ link_to "Know your meme", "http://knowyourmeme.com/memes/doge"
54
+ end
55
+
56
+ def name_header
57
+ # object is the Doge
58
+ content_tag(:h1, objec†.name)
59
+ end
60
+
61
+ def signed_in_status
62
+ # controller methods are accessible via the view context
63
+ if signed_in?
64
+ "Signed in"
65
+ else
66
+ "Signed out"
67
+ end
68
+ end
69
+ end
70
+ ```
71
+
72
+ Wrap your model object in your controller with `present`:
73
+
74
+ ```ruby
75
+ class DogesController
76
+ def show
77
+ end
78
+
79
+ private
80
+
81
+ def doge
82
+ @doge ||= present(Doge.find(params[:id]))
83
+ end
84
+ end
85
+ ```
86
+
87
+ Use the presenter object in `doges/show.haml.html`
88
+
89
+ ```haml
90
+ = doge.name_header
91
+ .status
92
+ You are #{ doge.signed_in_status }
93
+ .links
94
+ .meme-link= doge.know_your_meme_link
95
+ ```
96
+
97
+ #### Collection Example
98
+
99
+ Create a presenter class in `app/presenters`:
100
+
101
+ ```ruby
102
+ class DogePresenter < Presenter
103
+ # same as above
104
+ end
105
+ ```
106
+
107
+ Wrap your model object in your controller with `present`:
108
+
109
+ ```ruby
110
+ class DogesController
111
+ def index
112
+ end
113
+
114
+ private
115
+
116
+ def doges
117
+ @doges ||= present(Doge.all)
118
+ end
119
+ end
120
+ ```
121
+
122
+ Use the presenter objects in `doges/index.haml.html`
123
+
124
+ ```haml
125
+ This renders "doges/_doge.html.haml" for each item, as usual:
126
+ = render @doges
127
+
128
+ Or use each:
129
+ - doges.each do |doge|
130
+ = doge.name_header
131
+ ```
132
+
133
+ #### Present with options
134
+
135
+ Use keyword arguements (or an options hash) to pass additional options to a
136
+ Presenter:
137
+
138
+ ```ruby
139
+ class UserPresenter
140
+ def initialize(object, view_context, cool: false)
141
+ super
142
+ @cool = cool
143
+ end
144
+ end
145
+
146
+ user = User.new
147
+ present(user, cool: true)
148
+ => #<UserPresenter object: #<User> ...>
149
+ ```
150
+
151
+ #### Render a custom Presenter
152
+
153
+ By default, a presenter class corresponding to the model class name is
154
+ constructed. To specify a different class, pass the `presenter:` key, followed
155
+ by any additional arguments:
156
+
157
+ ```ruby
158
+ user = User.new
159
+ present(user, presenter: NiceUserPresenter, cool: true)
160
+ => #<NiceUserPresenter object: #<User> ...>
161
+ ```
162
+
163
+ #### Render a collection
164
+
165
+ ```ruby
166
+ present(User.first(5))
167
+ => [#<UserPresenter object: #<User> ...>]
168
+ ```
169
+
170
+ #### Creating presenters in views
171
+
172
+ You should create presenters in your controllers. If you would like to create
173
+ a presenter in your view code, make the `presents` method visible to your views:
174
+
175
+ ```ruby
176
+ class ApplicationController
177
+ include Presents
178
+ helper_method :present
179
+ end
180
+ ```
181
+
182
+ ## More Goodness
183
+
184
+ #### Presenters are objects
185
+
186
+ You can mix in common methods. Move everything in `application_helper.rb` to
187
+ `app/presenters/shared`:
188
+
189
+ ```ruby
190
+ module Shared
191
+ def logout_link
192
+ # whatever
193
+ end
194
+ end
195
+
196
+ class DogePresenter < Presenter
197
+ include Shared
198
+ end
199
+ ```
200
+
201
+ You can override methods without resorting to convoluted method names:
202
+
203
+ ```ruby
204
+ class DogePresenter < Presenter
205
+ include Shared
206
+
207
+ def logout_link
208
+ # whoa this one is different!
209
+ end
210
+ end
211
+ ```
212
+
213
+ #### Presenters can create other presenters
214
+
215
+ ```ruby
216
+ class DogePresenter < Presenter
217
+ def cats
218
+ present(object.cats)
219
+ end
220
+ end
221
+ ```
222
+
223
+ ```haml
224
+ = render doge.cats
225
+ ```
226
+
227
+ ## References
228
+
229
+ * http://nithinbekal.com/posts/rails-presenters/
230
+ * https://github.com/drapergem/draper
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ task default: [:test]
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.test_files = %w(test/**/*.rb)
9
+ t.verbose = false
10
+ end
@@ -0,0 +1,14 @@
1
+ # Base Presenter class
2
+ # Construct with object, view_context, and optional options
3
+ class Presenter < Struct.new(:object, :view_context, :options)
4
+ delegate :id, :to_partial_path, to: :object
5
+
6
+ # Send missing symbols to view_context
7
+ def method_missing(symbol, *args, &block)
8
+ view_context.send(symbol, *args, &block)
9
+ end
10
+
11
+ def respond_to?(symbol, _ = false)
12
+ super || view_context.respond_to?(symbol, true)
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ module Presents
2
+ private
3
+
4
+ # Wrap an object or collection of objects with a presenter class.
5
+ #
6
+ # object - a ruby class
7
+ # presenter - a Presenter class (optional)
8
+ #
9
+ # Examples
10
+ #
11
+ # user = User.new
12
+ # present(user, cool: true)
13
+ # => #<UserPresenter object: #<User> ...>
14
+ #
15
+ # user = User.new
16
+ # present(user, presenter: NiceUserPresenter, cool: true)
17
+ # => #<NiceUserPresenter object: #<User> ...>
18
+ #
19
+ # present([user])
20
+ # => [#<UserPresenter object: #<User> ...>]
21
+ #
22
+ # Returns a new Presenter object or array of new Presenter objects
23
+ def present(object, presenter: nil, **args)
24
+ if object.respond_to?(:to_ary)
25
+ object.map { |item| present(item, presenter: presenter, **args) }
26
+ else
27
+ presenter ||= Object.const_get("#{ object.class.name }Presenter")
28
+ presenter.new(object, view_context, **args)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Pres
2
+ VERSION = "0.0.1"
3
+ end
data/lib/pres.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "active_support/core_ext/module/delegation"
2
+ require "pres/version"
3
+ require "pres/presenter.rb"
4
+ require "pres/presents.rb"
@@ -0,0 +1,22 @@
1
+ require "test_helper"
2
+
3
+ describe Presenter do
4
+ it "delegates to view_context" do
5
+ view_context = FakeViewContext.new
6
+ presenter = Presenter.new(nil, view_context)
7
+ assert presenter.respond_to?(:current_user)
8
+ assert presenter.respond_to?(:link_to)
9
+ view_context.expects(:link_to)
10
+ presenter.link_to "something"
11
+ end
12
+
13
+ it "is constructed without options" do
14
+ assert Presenter.new(nil, nil)
15
+ end
16
+
17
+ it "is constructed with options" do
18
+ presenter = Presenter.new(nil, nil, something: 42, secrets: "none")
19
+ assert_equal 42, presenter.options[:something]
20
+ assert_equal "none", presenter.options[:secrets]
21
+ end
22
+ end
@@ -0,0 +1,54 @@
1
+ require "test_helper"
2
+
3
+ describe Presents do
4
+ class Doge
5
+ end
6
+
7
+ class DogePresenter < Presenter
8
+ end
9
+
10
+ class VeryDogePresenter < Presenter
11
+ end
12
+
13
+ class FakeController
14
+ include Presents
15
+
16
+ def wrap(object)
17
+ present(object)
18
+ end
19
+
20
+ def very_wrap(object)
21
+ present(object, presenter: VeryDogePresenter)
22
+ end
23
+
24
+ def view_context
25
+ FakeViewContext.new
26
+ end
27
+ end
28
+
29
+ let(:controller) { FakeController.new }
30
+
31
+ it "creates the default presenter" do
32
+ presenter = controller.wrap(Doge.new)
33
+ assert presenter.is_a?(DogePresenter)
34
+ end
35
+
36
+ it "creates the specified presenter" do
37
+ presenter = controller.very_wrap(Doge.new)
38
+ assert presenter.is_a?(VeryDogePresenter)
39
+ end
40
+
41
+ it "creates an array of default presenters" do
42
+ presenters = controller.wrap([Doge.new, Doge.new])
43
+ assert presenters.is_a?(Array)
44
+ assert_equal 2, presenters.size
45
+ assert presenters[0].is_a?(DogePresenter)
46
+ end
47
+
48
+ it "creates an array of specified presenters" do
49
+ presenters = controller.very_wrap([Doge.new, Doge.new])
50
+ assert presenters.is_a?(Array)
51
+ assert_equal 2, presenters.size
52
+ assert presenters[0].is_a?(VeryDogePresenter)
53
+ end
54
+ end
@@ -0,0 +1,23 @@
1
+ if ENV["TRAVIS"]
2
+ require "coveralls"
3
+ Coveralls.wear!
4
+ end
5
+
6
+ require "minitest/autorun"
7
+ require "mocha/mini_test"
8
+ require "byebug" if ENV["BYEBUG"]
9
+ require "pres"
10
+
11
+ class FakeViewContext
12
+ # An example of a method mixed into the view_context
13
+ def current_user
14
+ nil
15
+ end
16
+
17
+ private
18
+
19
+ # An example of a private method provided by the view_context
20
+ def link_to(*_)
21
+ nil
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pres
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tee Parham
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.4'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.4'
83
+ description: A Simple Rails Presenter base class and controller helper
84
+ email:
85
+ - tee@neighborland.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - Gemfile
91
+ - LICENSE.txt
92
+ - README.md
93
+ - Rakefile
94
+ - lib/pres.rb
95
+ - lib/pres/presenter.rb
96
+ - lib/pres/presents.rb
97
+ - lib/pres/version.rb
98
+ - test/presenter_test.rb
99
+ - test/presents_test.rb
100
+ - test/test_helper.rb
101
+ homepage: https://github.com/neighborland/pres
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: 2.0.0
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.4.5
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: A Simple Rails Presenter
125
+ test_files:
126
+ - Gemfile
127
+ - Rakefile
128
+ - test/presenter_test.rb
129
+ - test/presents_test.rb
130
+ - test/test_helper.rb
131
+ has_rdoc: