meta_presenter 0.2.4 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", "6.0.0"
6
+ gem "actionmailer", "6.0.0"
7
+
8
+ group :development, :test do
9
+ gem "builder"
10
+ gem "byebug", platforms: [:mri, :mingw, :x64_mingw]
11
+ gem "rb-readline"
12
+ gem "rspec"
13
+ end
14
+
15
+ group :development do
16
+ gem "rubocop", "~> 1.57", require: false
17
+ end
18
+
19
+ gemspec path: "../"
@@ -0,0 +1,19 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", "7.0.1"
6
+ gem "actionmailer", "7.0.1"
7
+
8
+ group :development, :test do
9
+ gem "builder"
10
+ gem "byebug", platforms: [:mri, :mingw, :x64_mingw]
11
+ gem "rb-readline"
12
+ gem "rspec"
13
+ end
14
+
15
+ group :development do
16
+ gem "rubocop", "~> 1.57", require: false
17
+ end
18
+
19
+ gemspec path: "../"
@@ -1,10 +1,8 @@
1
1
  require 'active_support/core_ext/object/try'
2
2
 
3
3
  module MetaPresenter
4
-
5
4
  # Builds a presenter class for a controller and method
6
5
  class Builder
7
-
8
6
  # @return [ActionController::Base, ActionMailer::Base] Controller that this presenter will delegate methods to
9
7
  attr_reader :controller
10
8
 
@@ -20,7 +18,7 @@ module MetaPresenter
20
18
  @action_name = action_name
21
19
  end
22
20
 
23
- # Error for there's no presenter class defined but a file for it exists
21
+ # Error when there's no presenter class defined but a file for it exists
24
22
  class FileExistsButPresenterNotDefinedError < NameError
25
23
  # Create a new error
26
24
  #
@@ -40,90 +38,91 @@ module MetaPresenter
40
38
 
41
39
  # @return [Class] Class constant for the built MetaPresenter::Base presenter
42
40
  def presenter_class
43
- # Try to find the presenter class (Not guaranteed,
41
+ # Try to find the presenter class (Not guaranteed,
44
42
  # for example if the presenter class wasn't defined
45
43
  # or if the file wasn't found)
46
44
  klass = nil
47
45
  ancestors.each do |klass_name|
48
46
  klass = presenter_class_for(klass_name)
49
- break if !klass.nil?
47
+ break unless klass.nil?
50
48
  end
51
49
 
52
50
  klass
53
51
  end
54
52
 
55
53
  def presenter_base_dir
56
- File.join(Rails.root, "app", "presenters")
54
+ File.join(Rails.root, 'app', 'presenters')
57
55
  end
58
56
 
59
57
  private
60
- def all_ancestors
61
- controller.class.ancestors.select do |ancestor|
62
- if controller.class <= ActionController::Base
63
- ancestor <= ActionController::Base
64
- elsif controller.class <= ActionMailer::Base
65
- ancestor <= ActionMailer::Base
66
- else
67
- raise InvalidControllerError.new(controller)
68
- end
69
- end
70
- end
71
58
 
72
- def mailer_ancestors
73
- ancestors_until(ApplicationMailer) do |klass|
74
- "Mailers::#{klass.name.gsub('Mailer', '')}"
59
+ def all_ancestors
60
+ controller.class.ancestors.select do |ancestor|
61
+ if controller.class <= ActionController::Base
62
+ ancestor <= ActionController::Base
63
+ elsif controller.class <= ActionMailer::Base
64
+ ancestor <= ActionMailer::Base
65
+ else
66
+ raise InvalidControllerError, controller
75
67
  end
76
68
  end
69
+ end
77
70
 
78
- def controller_ancestors
79
- ancestors_until(ApplicationController) do |klass|
80
- klass.try(:name).try(:gsub, 'Controller', '')
81
- end
71
+ def mailer_ancestors
72
+ ancestors_until(ApplicationMailer) do |klass|
73
+ "Mailers::#{klass.name.gsub('Mailer', '')}"
82
74
  end
83
-
84
- def presenter_class_for(klass_name)
85
- presenter_class_name = "::#{klass_name}Presenter"
86
- begin
87
- return presenter_class_name.constantize
88
-
89
- # No corresponding presenter class was found
90
- rescue NameError => e
91
- filename = "#{presenter_class_name.underscore}.rb"
92
- presenter_file_path = File.join(presenter_base_dir, filename)
93
- if File.exists?(presenter_file_path)
94
- raise FileExistsButPresenterNotDefinedError.new(presenter_class_name, presenter_file_path)
95
- else
96
- return nil
97
- end
98
- end
75
+ end
76
+
77
+ def controller_ancestors
78
+ ancestors_until(ApplicationController) do |klass|
79
+ klass.try(:name).try(:gsub, 'Controller', '')
99
80
  end
81
+ end
100
82
 
101
- def ancestors
102
- # Different ancestors depending on whether
103
- # we're dealing with a mailer or a controller
104
- list = if all_ancestors.map(&:to_s).include?("ActionMailer::Base")
105
- mailer_ancestors
106
- else
107
- controller_ancestors
83
+ def presenter_class_for(klass_name)
84
+ presenter_class_name = "::#{klass_name}Presenter"
85
+ begin
86
+ presenter_class_name.constantize
87
+
88
+ # No corresponding presenter class was found
89
+ rescue NameError => e
90
+ filename = "#{presenter_class_name.underscore}.rb"
91
+ presenter_file_path = File.join(presenter_base_dir, filename)
92
+ if File.exist?(presenter_file_path)
93
+ raise FileExistsButPresenterNotDefinedError.new(presenter_class_name, presenter_file_path)
108
94
  end
109
95
 
110
- # add a presenter class for our current action
111
- # to the front of the list
112
- presenter_class_name_for_current_action = "#{list.first}::#{action_name.camelcase}"
113
- list.unshift(presenter_class_name_for_current_action)
96
+ nil
114
97
  end
98
+ end
115
99
 
116
- # The list of ancestors is very long.
117
- # Trim it down to just the length of the class we are looking for.
118
- #
119
- # Takes an optional block method to transform the result
120
- # with a map operation
121
- def ancestors_until(until_class)
122
- # trim down the list
123
- ancestors_list = all_ancestors[0..all_ancestors.index(until_class)]
124
-
125
- # map to the fully qualified class name
126
- ancestors_list.map { |klass| yield(klass) }
127
- end
100
+ def ancestors
101
+ # Different ancestors depending on whether
102
+ # we're dealing with a mailer or a controller
103
+ list = if all_ancestors.map(&:to_s).include?('ActionMailer::Base')
104
+ mailer_ancestors
105
+ else
106
+ controller_ancestors
107
+ end
108
+
109
+ # add a presenter class for our current action
110
+ # to the front of the list
111
+ presenter_class_name_for_current_action = "#{list.first}::#{action_name.camelcase}"
112
+ list.unshift(presenter_class_name_for_current_action)
113
+ end
114
+
115
+ # The list of ancestors is very long.
116
+ # Trim it down to just the length of the class we are looking for.
117
+ #
118
+ # Takes an optional block method to transform the result
119
+ # with a map operation
120
+ def ancestors_until(until_class, &block)
121
+ # trim down the list
122
+ ancestors_list = all_ancestors[0..all_ancestors.index(until_class)]
123
+
124
+ # map to the fully qualified class name
125
+ ancestors_list.map(&block)
126
+ end
128
127
  end
129
- end
128
+ end
@@ -1,5 +1,4 @@
1
1
  require 'meta_presenter/builder'
2
- require 'active_support/concern'
3
2
  require 'active_support/rescuable'
4
3
 
5
4
  module MetaPresenter
@@ -16,21 +15,23 @@ module MetaPresenter
16
15
  # end
17
16
  #
18
17
  module Helpers
19
- extend ActiveSupport::Concern
20
- included do
21
- # Sets up the `presenter.` method as helper within your views
22
- # If you want to customize this for yourself just alias_method it
23
- helper_method :presenter
18
+ def self.included(base)
19
+ base.instance_eval do
20
+ # Sets up the `presenter.` method as helper within your views
21
+ # If you want to customize this for yourself just alias_method it
22
+ helper_method :presenter
23
+ end
24
24
  end
25
25
 
26
26
  private
27
- # Initialize presenter with the current controller
28
- def presenter
29
- @presenter ||= begin
30
- controller = self
31
- klass = MetaPresenter::Builder.new(controller, action_name).presenter_class
32
- klass.new(controller)
33
- end
27
+
28
+ # Initialize presenter with the current controller
29
+ def presenter
30
+ @presenter ||= begin
31
+ controller = self
32
+ klass = MetaPresenter::Builder.new(controller, action_name).presenter_class
33
+ klass.new(controller)
34
34
  end
35
+ end
35
36
  end
36
- end
37
+ end
@@ -1,32 +1,30 @@
1
-
2
-
3
1
  Gem::Specification.new do |s|
4
2
  s.name = 'meta_presenter'
5
- s.version = '0.2.4'
3
+ s.version = '1.0.1'
6
4
  s.platform = Gem::Platform::RUBY
7
5
  s.authors = ['szTheory']
8
- s.description = %q{Write highly focused and testable view presenter classes for your Rails controllers and actions}
9
- s.summary = %q{MetaPresenter is a Ruby gem for writing highly focused and testable view Rails presenter classes. 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
+ s.description = 'Write highly focused and testable view presenter classes for your Rails controllers and actions'
7
+ s.summary = "MetaPresenter is a Ruby gem for writing highly focused and testable view Rails presenter classes. 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."
10
8
  s.homepage = 'https://github.com/szTheory/meta_presenter'
11
9
  s.license = 'MIT'
12
10
  s.metadata = {
13
- "source_code_uri" => "https://github.com/szTheory/meta_presenter",
11
+ 'source_code_uri' => 'https://github.com/szTheory/meta_presenter',
12
+ 'rubygems_mfa_required' => 'true'
14
13
  }
15
14
 
16
15
  s.files = `git ls-files`.split($/)
17
- s.test_files = s.files.grep(%r{^(test|spec)/})
18
16
  s.require_paths = ['lib']
19
17
 
20
- s.required_ruby_version = '>= 2.1.0'
18
+ s.required_ruby_version = '>= 2.7.5'
21
19
 
22
- s.add_dependency 'actionpack', '>= 3.0.12'
23
- s.add_dependency 'actionmailer', '>= 3.0.12'
20
+ s.add_dependency 'actionmailer', '>= 6', '>= 7.0.1'
21
+ s.add_dependency 'actionpack', '>= 6', '>= 7.0.1'
24
22
 
25
- s.add_development_dependency 'rspec'
23
+ s.add_development_dependency 'appraisal'
26
24
  s.add_development_dependency 'bundler'
25
+ s.add_development_dependency 'coveralls'
26
+ s.add_development_dependency 'pry'
27
27
  s.add_development_dependency 'rake'
28
28
  s.add_development_dependency 'rb-readline'
29
- s.add_development_dependency 'pry'
30
- s.add_development_dependency 'coveralls'
31
- s.add_development_dependency 'appraisal'
29
+ s.add_development_dependency 'rspec'
32
30
  end
@@ -24,27 +24,27 @@ describe MetaPresenter::Builder do
24
24
  expect(controller_ancestors.first).to eql(controller_class)
25
25
  end
26
26
 
27
- context "application controller" do
27
+ context 'application controller' do
28
28
  let(:controller_class) { ApplicationController }
29
29
 
30
30
  it { is_expected.to be ApplicationPresenter }
31
31
  end
32
32
 
33
- context "controller without a presenter" do
33
+ context 'controller without a presenter' do
34
34
  let(:controller_class) { WithoutPresenterController }
35
35
 
36
- let(:presenter_file_path) { File.join(object.presenter_base_dir, "without_presenter_presenter.rb") }
36
+ let(:presenter_file_path) { File.join(object.presenter_base_dir, 'without_presenter_presenter.rb') }
37
37
 
38
- context "but file exists" do
38
+ context 'but file exists' do
39
39
  before do
40
- expect(File).to be_exists(presenter_file_path)
40
+ expect(File).to be_exist(presenter_file_path)
41
41
  end
42
42
 
43
43
  it { expect { subject }.to raise_error(MetaPresenter::Builder::FileExistsButPresenterNotDefinedError) }
44
44
  end
45
45
  end
46
46
 
47
- context "neither a controller nor a mailer" do
47
+ context 'neither a controller nor a mailer' do
48
48
  let(:controller_class) { OpenStruct }
49
49
 
50
50
  before do
@@ -55,7 +55,7 @@ describe MetaPresenter::Builder do
55
55
  it { expect { subject }.to raise_error(MetaPresenter::Builder::InvalidControllerError) }
56
56
  end
57
57
 
58
- context "mailer" do
58
+ context 'mailer' do
59
59
  let(:controller_class) { ApplicationMailer }
60
60
 
61
61
  before do
@@ -65,40 +65,38 @@ describe MetaPresenter::Builder do
65
65
  it { is_expected.to be Mailers::ApplicationPresenter }
66
66
  end
67
67
 
68
- context "subclass of ApplicationController" do
68
+ context 'subclass of ApplicationController' do
69
69
  let(:controller_class) { PagesController }
70
70
 
71
71
  before do
72
72
  expect(controller_class.ancestors).to include(ApplicationController)
73
73
  end
74
74
 
75
- context "action with a presenter class defined" do
76
- let(:action_name) { "logs" }
75
+ context 'action with a presenter class defined' do
76
+ let(:action_name) { 'logs' }
77
77
  before { expect(Object).to_not be_const_defined('LogsPresenter') }
78
78
 
79
79
  it { is_expected.to be Pages::LogsPresenter }
80
80
  end
81
81
 
82
- context "action without a presenter class defined" do
83
- let(:action_name) { "fairy" }
82
+ context 'action without a presenter class defined' do
83
+ let(:action_name) { 'fairy' }
84
84
  before { expect(Object).to_not be_const_defined('FairyPresenter') }
85
85
 
86
- context "parent presenter defines the method" do
87
-
88
- it "defers to the parent presenter" do
86
+ context 'parent presenter defines the method' do
87
+ it 'defers to the parent presenter' do
89
88
  expect(subject).to be PagesPresenter
90
89
  end
91
90
  end
92
91
 
93
92
  context "parent presenter doesn't define the method" do
94
-
95
- it "defers to the parent presenter" do
93
+ it 'defers to the parent presenter' do
96
94
  expect(subject).to be PagesPresenter
97
95
  end
98
96
  end
99
97
 
100
- context "but the file exists" do
101
- let(:action_name) { "only_file_exists" }
98
+ context 'but the file exists' do
99
+ let(:action_name) { 'only_file_exists' }
102
100
 
103
101
  it do
104
102
  expect { subject }.to raise_error(MetaPresenter::Builder::FileExistsButPresenterNotDefinedError)
@@ -107,11 +105,11 @@ describe MetaPresenter::Builder do
107
105
  end
108
106
  end
109
107
 
110
- context "namespaced" do
108
+ context 'namespaced' do
111
109
  let(:controller_class) { Admin::DashboardController }
112
- let(:action_name) { "inbox" }
110
+ let(:action_name) { 'inbox' }
113
111
 
114
112
  it { is_expected.to be Admin::Dashboard::InboxPresenter }
115
113
  end
116
114
  end
117
- end
115
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,22 +1,18 @@
1
- # spec coverage
2
- require 'coveralls'
3
- Coveralls.wear!
4
-
5
1
  # debug tool
6
- require "pry"
2
+ require 'pry'
7
3
 
8
4
  # main lib module
9
- require "meta_presenter"
5
+ require 'meta_presenter'
10
6
 
11
7
  # support files
12
- Dir["#{__dir__}/support/*.rb"].each {|file| require file }
8
+ Dir["#{__dir__}/support/*.rb"].each { |file| require file }
13
9
 
14
10
  # Simulate the Rails env.
15
11
  # Instead of loading the Rails environment, we stub the bare amount
16
12
  # and load from spec/support/app as if it were a Rails app
17
13
  begin
18
14
  # mount app dir tree
19
- Dir["#{__dir__}/support/app/**/*.rb"].each {|file| require file }
15
+ Dir["#{__dir__}/support/app/**/*.rb"].each { |file| require file }
20
16
 
21
17
  # mock Rails
22
18
  module Rails
@@ -28,4 +24,4 @@ begin
28
24
  allow(Rails).to receive(:root).and_return(File.join(__dir__, 'support'))
29
25
  end
30
26
  end
31
- end
27
+ end
@@ -1,2 +1,6 @@
1
- class Admin::DashboardController < ApplicationController
2
- end
1
+ require_relative '../application_controller'
2
+
3
+ class Admin
4
+ class DashboardController < ::ApplicationController
5
+ end
6
+ end
@@ -1,8 +1,8 @@
1
1
  require_relative '../dashboard_presenter'
2
2
 
3
- module Admin
4
- module Dashboard
3
+ class Admin
4
+ class Dashboard
5
5
  class InboxPresenter < Admin::DashboardPresenter
6
6
  end
7
7
  end
8
- end
8
+ end
@@ -1,4 +1,5 @@
1
- module Admin
2
- class DashboardPresenter < ApplicationPresenter
1
+ require_relative '../../presenters/application_presenter'
2
+ class Admin
3
+ class DashboardPresenter < ::ApplicationPresenter
3
4
  end
4
5
  end
@@ -1,4 +1,6 @@
1
- module Pages
2
- class LogsPresenter < PagesPresenter
1
+ require_relative '../pages_presenter'
2
+
3
+ class Pages
4
+ class LogsPresenter < ::PagesPresenter
3
5
  end
4
- end
6
+ end