meta_presenter 0.1.4 → 0.1.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 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