meta_presenter 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f337e9c7d7719689f5bf9f34215265b34eb197dd1dde628c1d227812db8461bc
4
- data.tar.gz: a0c2c339a4b9afa58085b50d815054aa935a4369a5477fbb7eaaf0fbc1028310
3
+ metadata.gz: 85ad2a5319203c66fddcad35088e1fafbed032ba0268d47dc7a5450935c5f7f9
4
+ data.tar.gz: fe1f7357f559f3246b972214e02c2084f3ab943c0ecc0db60ffdc34d1c882bb0
5
5
  SHA512:
6
- metadata.gz: ec286fb53acbae17137ca1cb6b84f7d9a64faab49b4e2b355ba19a8df41400fe1fb90b0bbb681038adedba4aca01a8033ecfd9af4376abedba6ca0521abc58dd
7
- data.tar.gz: 11f1d08524cde6ed6c5cbfaf336f5d54bb99786e0cdb28263fc372d539faf84ee57a23bdc3252347fa3d71d82a4c63122adc2297295a03948aee31d20f17d365
6
+ metadata.gz: 9365877877a78521bd8540624d6eb75e19375854cc4b295c1555c5d0c95504022242a1eb58dd9b6ce257c36660a83d89b70116c978cff3606763e4da8f0ebc00
7
+ data.tar.gz: 18382a4cfb689d8d605fec617528f3e5b11dca72ad42cf27f8fc29d047ec43614207a90350c440a0d8795006ece10d418b4e27f0acc201437b071065cae12367
data/.travis.yml CHANGED
@@ -19,4 +19,6 @@ matrix:
19
19
  gemfile: gemfiles/actionpack5.gemfile
20
20
  - rvm: 2.2.0
21
21
  gemfile: gemfiles/actionpack5.gemfile
22
- script: bundle exec rspec
22
+ script: bundle exec rspec
23
+ before_install:
24
+ - gem install bundler -v '< 2'
data/Appraisals CHANGED
@@ -9,4 +9,9 @@ end
9
9
 
10
10
  appraise "actionpack5" do
11
11
  gem "actionpack", "5.0.0"
12
- end
12
+ end
13
+
14
+ # TODO: uncomment this once Rails 6 is released on April 30, 2019
15
+ # appraise "actionpack6" do
16
+ # gem "actionpack", "6.0.0"
17
+ # end
data/Gemfile CHANGED
@@ -2,11 +2,10 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'pry'
6
-
7
5
  # Hinting at development dependencies
8
6
  # Prevents bundler from taking a long-time to resolve
9
7
  group :development, :test do
8
+ gem 'pry'
10
9
  gem 'rspec'
11
10
  gem 'builder'
12
11
  gem 'rb-readline'
data/Gemfile.lock CHANGED
@@ -1,26 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- meta_presenter (0.1.4)
4
+ meta_presenter (0.1.5)
5
5
  actionpack (>= 3.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- actionpack (5.2.1)
11
- actionview (= 5.2.1)
12
- activesupport (= 5.2.1)
10
+ actionpack (5.2.2)
11
+ actionview (= 5.2.2)
12
+ activesupport (= 5.2.2)
13
13
  rack (~> 2.0)
14
14
  rack-test (>= 0.6.3)
15
15
  rails-dom-testing (~> 2.0)
16
16
  rails-html-sanitizer (~> 1.0, >= 1.0.2)
17
- actionview (5.2.1)
18
- activesupport (= 5.2.1)
17
+ actionview (5.2.2)
18
+ activesupport (= 5.2.2)
19
19
  builder (~> 3.1)
20
20
  erubi (~> 1.4)
21
21
  rails-dom-testing (~> 2.0)
22
22
  rails-html-sanitizer (~> 1.0, >= 1.0.3)
23
- activesupport (5.2.1)
23
+ activesupport (5.2.2)
24
24
  concurrent-ruby (~> 1.0, >= 1.0.2)
25
25
  i18n (>= 0.7, < 2)
26
26
  minitest (~> 5.1)
@@ -31,7 +31,7 @@ GEM
31
31
  thor (>= 0.14.0)
32
32
  builder (3.2.3)
33
33
  coderay (1.1.2)
34
- concurrent-ruby (1.1.3)
34
+ concurrent-ruby (1.1.4)
35
35
  coveralls (0.8.22)
36
36
  json (>= 1.8, < 3)
37
37
  simplecov (~> 0.16.1)
@@ -41,18 +41,18 @@ GEM
41
41
  crass (1.0.4)
42
42
  diff-lcs (1.3)
43
43
  docile (1.3.1)
44
- erubi (1.7.1)
45
- i18n (1.1.1)
44
+ erubi (1.8.0)
45
+ i18n (1.5.2)
46
46
  concurrent-ruby (~> 1.0)
47
47
  json (2.1.0)
48
48
  loofah (2.2.3)
49
49
  crass (~> 1.0.2)
50
50
  nokogiri (>= 1.5.9)
51
51
  method_source (0.9.2)
52
- mini_portile2 (2.3.0)
52
+ mini_portile2 (2.4.0)
53
53
  minitest (5.11.3)
54
- nokogiri (1.8.5)
55
- mini_portile2 (~> 2.3.0)
54
+ nokogiri (1.10.1)
55
+ mini_portile2 (~> 2.4.0)
56
56
  pry (0.12.2)
57
57
  coderay (~> 1.1.0)
58
58
  method_source (~> 0.9.0)
data/README.md CHANGED
@@ -1,159 +1,217 @@
1
- [![Gem Version](https://badge.fury.io/rb/meta_presenter.svg)](https://badge.fury.io/rb/meta_presenter) [![Build Status](https://travis-ci.org/szTheory/meta_presenter.svg?branch=master)](https://travis-ci.org/szTheory/meta_presenter) [![Coverage Status](https://coveralls.io/repos/github/szTheory/meta_presenter/badge.svg?branch=master)](https://coveralls.io/github/szTheory/meta_presenter?branch=master) [![Inline docs](http://inch-ci.org/github/szTheory/meta_presenter.svg?branch=master)](http://inch-ci.org/github/szTheory/meta_presenter) [![Maintainability](https://api.codeclimate.com/v1/badges/8698d68a87ec1a9bfacd/maintainability)](https://codeclimate.com/github/szTheory/meta_presenter/maintainability) [![MIT License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/szTheory/meta_presenter/blob/master/LICENSE.txt) [![Gem](https://img.shields.io/gem/dt/meta_presenter.svg)](https://rubygems.org/gems/meta_presenter) [![GitHub stars](https://img.shields.io/github/stars/szTheory/meta_presenter.svg?label=Stars&style=social)](https://github.com/szTheory/meta_presenter)
1
+ [![Gem Version](https://badge.fury.io/rb/meta_presenter.svg)](https://badge.fury.io/rb/meta_presenter) [![Build Status](https://travis-ci.org/szTheory/meta_presenter.svg?branch=master)](https://travis-ci.org/szTheory/meta_presenter) [![Coverage Status](https://coveralls.io/repos/github/szTheory/meta_presenter/badge.svg?branch=master)](https://coveralls.io/github/szTheory/meta_presenter?branch=master) [![Inline docs](https://inch-ci.org/github/szTheory/meta_presenter.svg?branch=master)](https://inch-ci.org/github/szTheory/meta_presenter) [![Maintainability](https://api.codeclimate.com/v1/badges/8698d68a87ec1a9bfacd/maintainability)](https://codeclimate.com/github/szTheory/meta_presenter/maintainability) [![MIT License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/szTheory/meta_presenter/blob/master/LICENSE.txt) [![Gem](https://img.shields.io/gem/dt/meta_presenter.svg)](https://rubygems.org/gems/meta_presenter) [![GitHub stars](https://img.shields.io/github/stars/szTheory/meta_presenter.svg?label=Stars&style=social)](https://github.com/szTheory/meta_presenter)
2
2
 
3
- # MetaPresenter
3
+ [![logo](https://user-images.githubusercontent.com/28652/50427588-2289cf80-087a-11e9-82e1-ae212adf0d07.png)](https://metapresenter.com)
4
4
 
5
5
  MetaPresenter is a Ruby gem that gives you access to the powerful presenter pattern in your Rails controllers. For each controller/action pair you get a presenter class in `app/presenters` that you can use in your views with with `presenter.method_name`. This helps you decompose your helper logic into tight, easily testable classes. There's even a DSL for method delegation on objects to reduce boilerplate.
6
6
 
7
- [Github Project Page](https://github.com/szTheory/meta_presenter)
7
+ ![overlay-shape-clean-sm](https://user-images.githubusercontent.com/28652/50854229-828c7580-1352-11e9-824b-a78c9a2404fb.png)
8
8
 
9
9
  ## Installation
10
10
 
11
- Add this line to your application's Gemfile:
11
+ 1. Add this line to your application's Gemfile:
12
12
 
13
- gem 'meta_presenter'
13
+ ```ruby
14
+ gem 'meta_presenter'
15
+ ```
14
16
 
15
- And then execute:
17
+ 2. Bundle from the command line:
16
18
 
17
- $ bundle
19
+ ```sh
20
+ $ bundle
21
+ ```
18
22
 
19
- Or install it yourself as:
23
+ 3. Include MetaPresenter::Helpers in your controller or mailer:
20
24
 
21
- $ gem install meta_presenter
25
+ ```ruby
26
+ class ApplicationController < ActionController::Base
27
+ include MetaPresenter::Helpers
28
+ end
29
+ ```
22
30
 
23
- Include MetaPresenter::Helpers in your controller or mailer:
24
-
25
- class ApplicationController < ActionController::Base
26
- include MetaPresenter::Base
27
- end
28
-
29
- class ApplicationMailer < ActionMailer::Base
30
- include MetaPresenter::Base
31
- end
32
-
33
- ## Requirements
34
-
35
- MetaPresenter supports Ruby >= 2.1 and ActionPack >= 4.0. If you'd like to help adding support for older versions please submit a pull request with passing specs.
31
+ ```ruby
32
+ class ApplicationMailer < ActionMailer::Base
33
+ include MetaPresenter::Helpers
34
+ end
35
+ ```
36
36
 
37
37
  ## Example
38
38
 
39
39
  Say you have a PagesController with an action for home and logs. Underneath `app/presenters` you can add a class for each action. In this example we'll also create an application and base presenter we'll inherit from to re-use code in the per-action presenters.
40
40
 
41
- app/
42
- controllers/
43
- application_controller.rb
44
- pages_controller.rb
45
- presenters/
46
- application_presenter.rb
47
- pages/
48
- base_presenter.rb
49
- home_presenter.rb
50
- logs_presenter.rb
41
+ ```
42
+ app/
43
+ controllers/
44
+ application_controller.rb
45
+ pages_controller.rb
46
+ presenters/
47
+ application_presenter.rb
48
+ pages_presenter.rb
49
+ pages/
50
+ home_presenter.rb
51
+ logs_presenter.rb
52
+ views
53
+ pages
54
+ home.html.erb
55
+ logs.html.erb
56
+ spec/ (or test/)
57
+ presenters/
58
+ application_presenter_spec.rb
59
+ pages_presenter_spec.rb
60
+ pages/
61
+ home_presenter_spec.rb
62
+ logs_presenter_spec.rb
63
+ ```
51
64
 
52
65
  app/controllers/page_controller.rb
53
66
 
54
- class ApplicationController < ActionController::Base
55
- # Controller methods automatically become available in views and other presenters.
56
- # So this gives you presenter.current_user in views, and you can call `current_user`
57
- # within your presenters as well
58
- def current_user
59
- User.first
60
- end
61
- end
67
+ ```ruby
68
+ class ApplicationController < ActionController::Base
69
+ include MetaPresenter::Helpers
70
+
71
+ # Controller methods automatically become available in views and other presenters.
72
+ # So this gives you presenter.current_user in views, and you can call `current_user`
73
+ # within your presenters as well
74
+ def current_user
75
+ User.first
76
+ end
77
+ end
78
+ ```
62
79
 
63
80
  app/controllers/dashboard_controller.rb
64
81
 
65
- class ApplicationController < ActionController::Base
66
- def home
67
- end
82
+ ```ruby
83
+ class ApplicationController < ActionController::Base
84
+ def home
85
+ end
68
86
 
69
- def logs
70
- end
87
+ def logs
88
+ end
71
89
 
72
- private
73
- # presenter.logs in views
74
- def logs
75
- Log.all
76
- end
90
+ private
91
+ # presenter.logs in views
92
+ def logs
93
+ Log.all
77
94
  end
95
+ end
96
+ ```
78
97
 
79
98
  app/presenters/application_presenter.rb
80
99
 
81
- class ApplicationPresenter < MetaPresenter::BasePresenter
82
- # Makes presenter.page_title available in all of your app's views
83
- def page_title
84
- "My App"
85
- end
86
-
87
- # presenter.last_login_at in views
88
- def last_login_at
89
- # controller methods from within the same scope
90
- # as the presenter are directly available
91
- current_user.last_login_at
92
- end
93
- end
94
-
95
- app/presenters/pages/base_presenter.rb:
96
-
97
- class Pages::BasePresenter < ApplicationPresenter
98
- # Makes presenter.nav_items available for
99
- # all actions on PagesController
100
- def nav_items
101
- [
102
- {name: "Home", path: home_path},
103
- {name: "Logs", path: logs_path}
104
- ]
105
- end
106
- end
100
+ ```ruby
101
+ class ApplicationPresenter < MetaPresenter::BasePresenter
102
+ # Makes presenter.page_title available in all of your app's views
103
+ def page_title
104
+ "My App"
105
+ end
106
+
107
+ # presenter.last_login_at in views
108
+ def last_login_at
109
+ # controller methods from within the same scope
110
+ # as the presenter are directly available
111
+ current_user.last_login_at
112
+ end
113
+ end
114
+ ```
115
+
116
+ app/presenters/pages_presenter.rb:
117
+
118
+ ```ruby
119
+ class PagesPresenter < ApplicationPresenter
120
+ # Makes presenter.nav_items available for
121
+ # all actions on PagesController
122
+ def nav_items
123
+ [
124
+ {name: "Home", path: home_path},
125
+ {name: "Logs", path: logs_path}
126
+ ]
127
+ end
128
+ end
129
+ ```
107
130
 
108
131
  app/presenters/pages/home_presenter.rb
109
132
 
110
- class Pages::HomePresenter << Pages::BasePresenter
111
- # presenter.email, presenter.id or any other
112
- # method not already defined will delegate to
113
- # the current_user
114
- delegate_all_to :current_user
133
+ ```ruby
134
+ class Pages::HomePresenter < PagesPresenter
135
+ # presenter.email, presenter.id or any other
136
+ # method not already defined will delegate to
137
+ # the current_user
138
+ delegate_all_to :current_user
115
139
 
116
- # presenter.greeting in views
117
- def greeting
118
- "Hello, #{current_user.name}"
119
- end
120
- end
140
+ # presenter.greeting in views
141
+ def greeting
142
+ "Hello, #{current_user.name}"
143
+ end
144
+ end
145
+ ```
146
+
147
+ app/views/pages/home.html.haml
148
+
149
+ ```Haml
150
+ %h1 Home
151
+ %p #{greeting}
152
+ %p Last login #{distance_of_time_in_words_to_now(last_login_at)}
153
+ ```
121
154
 
122
155
  app/presenters/pages/logs_presenter.rb
123
156
 
124
- class Pages::LogsPresenter << Pages::BasePresenter
125
- # presenter.size and presenter.last will delegate to
126
- # the controller's private `#logs`
127
- delegate :size, :last, to: :logs
128
-
129
- # presenter.log_text(log) in view
130
- # for example in a haml view:
131
- #
132
- # - presenter.logs.each do |log|
133
- # = presenter.log_text(log)
134
- #
135
- def log_text(log)
136
- log.description
137
- end
138
- end
157
+ ```ruby
158
+ class Pages::LogsPresenter < PagesPresenter
159
+ # presenter.size and presenter.last will delegate to
160
+ # the controller's private `#logs`
161
+ delegate :size, :last, to: :logs
162
+
163
+ # presenter.log_text(log) in view
164
+ def log_text(log)
165
+ log.description
166
+ end
167
+ end
168
+ ```
169
+
170
+ app/views/pages/logs.html.haml
171
+
172
+ ```Haml
173
+ %h1 Logs
174
+ %p Num logs: #{presenter.size}
175
+ %p Last log: #{presenter.log_text(presenter.last)}
176
+ %ul
177
+ - presenter.logs.each do |log|
178
+ %li= presenter.log_text(log)
179
+ ```
139
180
 
140
181
  ## Aliasing the presenter methods
141
182
 
142
183
  If you want to customize the `presenter` method you can specify a shorthand by adding an alias_method to your controller or mailer:
143
184
 
144
- class ApplicationController < ActionController::Base
145
- including MetaPresenter
185
+ ```ruby
186
+ class ApplicationController < ActionController::Base
187
+ including MetaPresenter
146
188
 
147
- # So convenient!
148
- alias_method :presenter, :pr
149
- end
189
+ # So convenient!
190
+ alias_method :presenter, :pr
191
+ end
192
+ ```
150
193
 
151
- ## TODO
194
+ ## Requirements
152
195
 
153
- * add support for actionsupport3, will require enabling it in the Appraisal file and then fixing any bugs in the build
196
+ MetaPresenter supports Ruby >= 2.1 and ActionPack >= 4.0. If you'd like to help adding support for older versions please submit a pull request with passing specs.
197
+
198
+ ## Links
199
+
200
+ * [Project website](https://metapresenter.com)
201
+ * [RDocs for the master branch](https://www.rubydoc.info/github/szTheory/meta-presenter/master)
202
+
203
+ ## Specs
204
+ To run the specs for the currently running Ruby version, run `bundle install` and then `bundle exec rspec`. To run specs for every supported version of ActionPack, run `bundle exec appraisal install` and then `bundle exec appraisal rspec`.
205
+
206
+ ## TODO
154
207
  * tests for ActionMailer support
155
- * add an optional task that generates the scaffolding for you. Or, you can manually create the files you want
156
- * add support for layouts
208
+ * optional `rake meta_presenter:install` that generates the scaffolding for you. Or, you can manually create the files you want.
209
+ * add support for layout-level presenters
210
+ * add Rails 6 support once it comes out (hopefully just have to add a gemfiles/actionpack6.gemfile and it will run with the Appraisal suite)
211
+
212
+ ## TODO (lower priority)
213
+ * add backwards compatibility for actionsupport3, will require enabling it in the Appraisal file and then fixing any bugs in the build
214
+ * add Middleman support (?)
157
215
 
158
216
  ## Contributing
159
217
 
@@ -2,10 +2,10 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "pry"
6
5
  gem "actionpack", "4.0.0"
7
6
 
8
7
  group :development, :test do
8
+ gem "pry"
9
9
  gem "rspec"
10
10
  gem "builder"
11
11
  gem "rb-readline"
@@ -2,10 +2,10 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "pry"
6
5
  gem "actionpack", "5.0.0"
7
6
 
8
7
  group :development, :test do
8
+ gem "pry"
9
9
  gem "rspec"
10
10
  gem "builder"
11
11
  gem "rb-readline"
@@ -11,7 +11,7 @@ module MetaPresenter
11
11
 
12
12
  extend ActiveSupport::Concern
13
13
  included do
14
- # Controller that this presenter will delegate methods to
14
+ # @return [ActionController::Base, ActionMailer::Base] Controller that this presenter will delegate methods to
15
15
  attr_reader :controller
16
16
 
17
17
  include InstanceMethods
@@ -22,6 +22,7 @@ module MetaPresenter
22
22
  # Creates a new presenter
23
23
  #
24
24
  # @param [ActionController::Base, ActionMailer::Base] controller Controller that this presenter will delegate methods to
25
+ # @return [MetaPresenter::Base] a base presenter
25
26
  def initialize(controller)
26
27
  @controller = controller
27
28
  end
@@ -6,12 +6,14 @@ module MetaPresenter
6
6
  # Base presenter class. Inherit from this it in order
7
7
  # to get a presenter you can use in your views
8
8
  #
9
- # # app/presenters/application_presenter.rb
10
- # class ApplicationPresenter < MetaPresenter::Base
11
- # def message
12
- # "Hello"
9
+ # @example
10
+ #
11
+ # # app/presenters/application_presenter.rb
12
+ # class ApplicationPresenter < MetaPresenter::Base
13
+ # def message
14
+ # "Hello"
15
+ # end
13
16
  # end
14
- # end
15
17
  class Base
16
18
  include DelegateToController
17
19
  # Comes last so `delegate_all_to` takes priority
@@ -19,6 +21,8 @@ module MetaPresenter
19
21
  include DelegateAllTo
20
22
 
21
23
  # Displayed in errors involving the presenter
24
+ #
25
+ # @return [String] Brief description of this presenter as its class name
22
26
  def inspect
23
27
  # Concise to not dump too much information on the dev
24
28
  "#<#{self.class.name}>"
@@ -5,10 +5,10 @@ module MetaPresenter
5
5
  # Builds a presenter class for a controller and method
6
6
  class Builder
7
7
 
8
- # Controller that this presenter will delegate methods to
8
+ # @return [ActionController::Base, ActionMailer::Base] Controller that this presenter will delegate methods to
9
9
  attr_reader :controller
10
10
 
11
- # Name of the controller's action to hook the presenter up to
11
+ # @return [String] Name of the controller's action to hook the presenter up to
12
12
  attr_reader :action_name
13
13
 
14
14
  # Creates a new Builder
@@ -31,20 +31,40 @@ module MetaPresenter
31
31
  end
32
32
  end
33
33
 
34
- # @return [Class] the presenter class for our controller and action combination
34
+ class NoPresenterClassDefinedError < NameError
35
+ # Create a new error
36
+ def initialize(controller, action_name)
37
+ super("No presenter defined for #{controller.class.to_s}##{action_name}")
38
+ end
39
+ end
40
+
41
+ # @return [Class] Class constant for the built MetaPresenter::Base presenter
35
42
  def presenter_class
36
- # Try to find the class (it's not guaranteed)
37
- klass_name = ancestors.find do |klass_name|
38
- presenter_class_for(klass_name)
43
+ # Try to find the presenter class (Not guaranteed,
44
+ # for example if the presenter class wasn't defined
45
+ # or if the file wasn't found)
46
+ klass = nil
47
+ ancestors.each do |klass_name|
48
+ klass = presenter_class_for(klass_name)
49
+ break if !klass.nil?
39
50
  end
40
51
 
41
- # Return the actual class
42
- presenter_class_for(klass_name)
52
+ if klass.nil?
53
+ raise NoPresenterClassDefinedError.new(controller, action_name)
54
+ end
55
+
56
+ klass
57
+ end
58
+
59
+ def presenter_base_dir
60
+ File.join(Rails.root, "app", "presenters")
43
61
  end
44
62
 
45
63
  private
46
64
  def all_ancestors
47
- controller.class.ancestors
65
+ controller.class.ancestors.select do |ancestor|
66
+ ancestor <= ActionController::Base
67
+ end
48
68
  end
49
69
 
50
70
  def mailer_ancestors
@@ -62,16 +82,16 @@ module MetaPresenter
62
82
  def presenter_class_for(klass_name)
63
83
  presenter_class_name = "::#{klass_name}Presenter"
64
84
  begin
65
- presenter_class_name.constantize
85
+ return presenter_class_name.constantize
66
86
 
67
87
  # No corresponding presenter class was found
68
88
  rescue NameError => e
69
89
  filename = "#{presenter_class_name.underscore}.rb"
70
- presenter_file_path = File.join(Rails.root, "app", "presenters", filename)
90
+ presenter_file_path = File.join(presenter_base_dir, filename)
71
91
  if File.exists?(presenter_file_path)
72
92
  raise FileExistsButPresenterNotDefinedError.new(presenter_class_name, presenter_file_path)
73
93
  else
74
- false
94
+ return nil
75
95
  end
76
96
  end
77
97
  end
@@ -2,7 +2,6 @@ require 'meta_presenter/builder'
2
2
  require 'active_support/concern'
3
3
 
4
4
  module MetaPresenter
5
-
6
5
  # Including this module in your controller will give
7
6
  # your views access to a `presenter` method that
8
7
  # delegates to controller methods
@@ -23,12 +22,19 @@ module MetaPresenter
23
22
  helper_method :presenter
24
23
  end
25
24
 
25
+ class PresenterClassNotFoundError < NameError
26
+ def initialize(controller, action_name)
27
+ super("No presenter class and method found for #{controller.class.name}##{action_name} (Are you rendering another action's template? If so then move your presenter method to a base presenter class for the controller that both action presenters inherit from)")
28
+ end
29
+ end
30
+
26
31
  private
27
32
  # Initialize presenter with the current controller
28
33
  def presenter
29
34
  @presenter ||= begin
30
35
  controller = self
31
36
  klass = MetaPresenter::Builder.new(controller, action_name).presenter_class
37
+ raise PresenterClassNotFoundError.new(controller, action_name) if klass == :undefined_presenter_class
32
38
  klass.new(controller)
33
39
  end
34
40
  end
data/logo.png ADDED
Binary file
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'meta_presenter'
5
- s.version = '0.1.4'
5
+ s.version = '0.1.5'
6
6
  s.platform = Gem::Platform::RUBY
7
7
  s.authors = ['szTheory']
8
8
  s.description = %q{Presenter pattern in your Rails controllers and actions}
@@ -30,9 +30,27 @@ describe MetaPresenter::Builder do
30
30
  it { is_expected.to be ApplicationPresenter }
31
31
  end
32
32
 
33
+ context "controller without a presenter" do
34
+ let(:controller_class) { WithoutPresenterController }
35
+
36
+ let(:presenter_file_path) { File.join(object.presenter_base_dir, "without_presenter_presenter.rb") }
37
+
38
+ context "but file exists" do
39
+ before do
40
+ expect(File).to be_exists(presenter_file_path)
41
+ end
42
+
43
+ it { expect { subject }.to raise_error(MetaPresenter::Builder::FileExistsButPresenterNotDefinedError) }
44
+ end
45
+ end
46
+
33
47
  context "subclass of ApplicationController" do
34
48
  let(:controller_class) { PagesController }
35
49
 
50
+ before do
51
+ expect(controller_class.ancestors).to include(ApplicationController)
52
+ end
53
+
36
54
  context "action with a presenter class defined" do
37
55
  let(:action_name) { "logs" }
38
56
  before { expect(Object).to_not be_const_defined('LogsPresenter') }
@@ -44,8 +62,18 @@ describe MetaPresenter::Builder do
44
62
  let(:action_name) { "fairy" }
45
63
  before { expect(Object).to_not be_const_defined('FairyPresenter') }
46
64
 
47
- it "defers to the parent presenter" do
48
- expect(subject).to be PagesPresenter
65
+ context "parent presenter defines the method" do
66
+
67
+ it "defers to the parent presenter" do
68
+ expect(subject).to be PagesPresenter
69
+ end
70
+ end
71
+
72
+ context "parent presenter doesn't define the method" do
73
+
74
+ it "defers to the parent presenter" do
75
+ expect(subject).to be PagesPresenter
76
+ end
49
77
  end
50
78
 
51
79
  context "but the file exists" do
@@ -0,0 +1,2 @@
1
+ class WithoutPresenterController < ApplicationController
2
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meta_presenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - szTheory
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-24 00:00:00.000000000 Z
11
+ date: 2019-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -145,6 +145,7 @@ files:
145
145
  - lib/meta_presenter/base/delegate_to_controller.rb
146
146
  - lib/meta_presenter/builder.rb
147
147
  - lib/meta_presenter/helpers.rb
148
+ - logo.png
148
149
  - meta_presenter.gemspec
149
150
  - spec/meta_presenter/builder_spec.rb
150
151
  - spec/meta_presenter/helpers_spec.rb
@@ -152,12 +153,14 @@ files:
152
153
  - spec/support/app/controllers/admin/dashboard_controller.rb
153
154
  - spec/support/app/controllers/application_controller.rb
154
155
  - spec/support/app/controllers/pages_controller.rb
156
+ - spec/support/app/controllers/without_presenter_controller.rb
155
157
  - spec/support/app/presenters/admin/dashboard/inbox_presenter.rb
156
158
  - spec/support/app/presenters/admin/dashboard_presenter.rb
157
159
  - spec/support/app/presenters/application_presenter.rb
158
160
  - spec/support/app/presenters/pages/logs_presenter.rb
159
161
  - spec/support/app/presenters/pages/only_file_exists_presenter.rb
160
162
  - spec/support/app/presenters/pages_presenter.rb
163
+ - spec/support/app/presenters/without_presenter_presenter.rb
161
164
  homepage: https://github.com/szTheory/meta_presenter
162
165
  licenses:
163
166
  - MIT
@@ -194,9 +197,11 @@ test_files:
194
197
  - spec/support/app/controllers/admin/dashboard_controller.rb
195
198
  - spec/support/app/controllers/application_controller.rb
196
199
  - spec/support/app/controllers/pages_controller.rb
200
+ - spec/support/app/controllers/without_presenter_controller.rb
197
201
  - spec/support/app/presenters/admin/dashboard/inbox_presenter.rb
198
202
  - spec/support/app/presenters/admin/dashboard_presenter.rb
199
203
  - spec/support/app/presenters/application_presenter.rb
200
204
  - spec/support/app/presenters/pages/logs_presenter.rb
201
205
  - spec/support/app/presenters/pages/only_file_exists_presenter.rb
202
206
  - spec/support/app/presenters/pages_presenter.rb
207
+ - spec/support/app/presenters/without_presenter_presenter.rb