makeover 1.0.0.rc1
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 +7 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/LICENSE.md +20 -0
- data/README.md +187 -0
- data/Rakefile +22 -0
- data/lib/generators/makeover/install/USAGE +13 -0
- data/lib/generators/makeover/install/install_generator.rb +32 -0
- data/lib/generators/makeover/install/templates/application_presenter.rb +3 -0
- data/lib/generators/makeover/install/templates/collection_presenter.rb +3 -0
- data/lib/generators/presenter/USAGE +9 -0
- data/lib/generators/presenter/presenter_generator.rb +36 -0
- data/lib/generators/presenter/templates/collection_presenter.rb.erb +2 -0
- data/lib/generators/presenter/templates/presenter.rb.erb +2 -0
- data/lib/generators/presenter/templates/spec.rb.erb +4 -0
- data/lib/generators/presenter/templates/test.rb.erb +4 -0
- data/lib/makeover/collection_presenter.rb +30 -0
- data/lib/makeover/engine.rb +8 -0
- data/lib/makeover/helpers.rb +17 -0
- data/lib/makeover/presentable.rb +91 -0
- data/lib/makeover/presenter.rb +27 -0
- data/lib/makeover/version.rb +4 -0
- data/lib/makeover.rb +13 -0
- data/lib/tasks/presenters_tasks.rake +5 -0
- metadata +221 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bc00466b91b8719cfb7e1373f7f37671f807a964
|
4
|
+
data.tar.gz: 0ebc94022e9c2e1146d4e15a515f1d0f7b1343c4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 331489eeaf921f18402795ecccaab6d34a19413b77a15b0eb4fa2cd8252f08ff49f9f45f477243249dcd1fff869599c24c75647179daf031f686caa28109f86d
|
7
|
+
data.tar.gz: 272d5eb00ba6faa63fa2143383a04fb2ed12ab491fa29bb941337d1f0ded69daf5ec1e969ddf9314b7ba828ade962cdaf64fa6d912ea67050077b7430400d11c
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at tscott@weblinc.com. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/LICENSE.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2016 Tom Scott
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
# Makeover
|
2
|
+
|
3
|
+
[](https://travis-ci.org/tubbo/presenters)
|
4
|
+
[](https://codeclimate.com/github/tubbo/presenters)
|
5
|
+
[](https://codeclimate.com/github/tubbo/presenters)
|
6
|
+
[](https://codeclimate.com/github/tubbo/presenters/coverage)
|
7
|
+
|
8
|
+
A [decorator][] library for [Rails][] applications, inspired by
|
9
|
+
[Draper][], but with an emphasis on architectural simplicity. Makeover
|
10
|
+
uses the given [ActiveSupport][] and [Ruby standard library][stdlib]
|
11
|
+
objects that can help in building an object-presentation layer for your
|
12
|
+
models.
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
After installing, run the following command to get things set up:
|
17
|
+
|
18
|
+
```bash
|
19
|
+
$ bin/rails makeover:install
|
20
|
+
```
|
21
|
+
|
22
|
+
This will mix in the `Makeover::Presentable` module into your
|
23
|
+
`ApplicationRecord` model code, enabling models to be presented by
|
24
|
+
calling `model.present`. This module is also mixed into your
|
25
|
+
`ApplicationController`, because the `present` method can be called with
|
26
|
+
an optional first argument that dictates the model being presented. In
|
27
|
+
addition to mixing itself in (visibly) to your controller and model
|
28
|
+
layer, this generator also creates an `ApplicationPresenter` and
|
29
|
+
`CollectionPresenter` base class for presenting models and collections,
|
30
|
+
respectively. All makeover will be derived from one of these base
|
31
|
+
classes.
|
32
|
+
|
33
|
+
In your application code, presentation would look like the following:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
class PostsController < ApplicationController
|
37
|
+
def index
|
38
|
+
@posts = present Post.search(params[:q])
|
39
|
+
end
|
40
|
+
|
41
|
+
def show
|
42
|
+
@post = Post.find(params[:id]).present
|
43
|
+
end
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
It is recommended to choose one syntax and make that standard across
|
48
|
+
your app, however both syntaxes are provided in case one or the other
|
49
|
+
works out better for you. Conventionally, presenter classes are found
|
50
|
+
by taking the model name and adding "Presenter" to the end, or in the
|
51
|
+
case of collections, pluralizing the model name and then suffixing with
|
52
|
+
"Presenter". You can customize this by passing the `with:` option into
|
53
|
+
the `#present` method:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
@post.present with: SearchResultPresenter
|
57
|
+
```
|
58
|
+
|
59
|
+
You can also use this options hash to apply context into the presenter.
|
60
|
+
A call to `#present` like this:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
@post.present with: SearchResultPresenter, search: @search
|
64
|
+
```
|
65
|
+
|
66
|
+
Will result in the following instantiation:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
SearchResultPresenter.new(@post, search: @search)
|
70
|
+
```
|
71
|
+
|
72
|
+
### The Presenter Class
|
73
|
+
|
74
|
+
Makeover are subclasses of `Makeover::Presenter`, which itself
|
75
|
+
subclasses (and implements [Delegator][]. The Delegator API was designed
|
76
|
+
specifically for implementing decorator objects such as this, and it's
|
77
|
+
utilized here to delegate all method calls not implemented on the
|
78
|
+
presenter itself to its underlying model. In addition, the Presenter
|
79
|
+
class contains an instance of a `Makeover::Helpers` object, which
|
80
|
+
mixes in `ActionView::Helpers` as well as any modules you define in
|
81
|
+
`Rails.application.config.makeover.helpers`.
|
82
|
+
|
83
|
+
This library is also capable of presenting entire collections of
|
84
|
+
objects. You can opt to present the collection object itself (like
|
85
|
+
in cases of pagination), or the objects within it. Collection makeover
|
86
|
+
derive from `Makeover::CollectionPresenter`, and in your application
|
87
|
+
the base collection presenter is called `CollectionPresenter`.
|
88
|
+
These types of objects can be generated using the `--collection` flag on
|
89
|
+
the presenter generator (as described below), but they're also generated
|
90
|
+
automatically when you pass a plural name into the presenter generator.
|
91
|
+
Collection makeover are [Enumerable][] objects, and when iterating
|
92
|
+
over their `model`, all records inside the collection are decorated
|
93
|
+
prior to returning to the caller.
|
94
|
+
|
95
|
+
### Generating Makeover
|
96
|
+
|
97
|
+
To generate a presenter, run the following command:
|
98
|
+
|
99
|
+
```bash
|
100
|
+
$ bin/rails generate presenter post
|
101
|
+
```
|
102
|
+
|
103
|
+
This will generate **app/makeover/post_presenter.rb** as a subclass fo
|
104
|
+
`ApplicationPresenter`. It will also generate a test file in
|
105
|
+
**test/makeover/post_presenter_test.rb** or
|
106
|
+
**spec/makeover/post_presenter_spec.rb**.
|
107
|
+
|
108
|
+
A typical presenter might look like this:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
class PostPresenter < ApplicationPresenter
|
112
|
+
def title
|
113
|
+
model.name.titleize
|
114
|
+
end
|
115
|
+
|
116
|
+
def cover_image
|
117
|
+
h.image_tag model.cover_image_url
|
118
|
+
end
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
You can also generate collection makeover using this generator. This
|
123
|
+
can be done in one of two ways, either by passing a plural name into the
|
124
|
+
generator:
|
125
|
+
|
126
|
+
```bash
|
127
|
+
$ bin/rails generate presenter posts
|
128
|
+
```
|
129
|
+
|
130
|
+
Or, by passing the `--collection` option in the generator arguments:
|
131
|
+
|
132
|
+
```bash
|
133
|
+
$ bin/rails generate presenter query --collection
|
134
|
+
```
|
135
|
+
|
136
|
+
This will generate a presenter class that is subclassed from
|
137
|
+
`CollectionPresenter`, rather than `ApplicationPresenter`.
|
138
|
+
|
139
|
+
### Configuring Makeover
|
140
|
+
|
141
|
+
To mix helper modules into your makeover, add the following to your
|
142
|
+
**config/application.rb**:
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
config.makeover.helpers << Refile::AttachmentHelper # or whatever module you want
|
146
|
+
```
|
147
|
+
|
148
|
+
## Installation
|
149
|
+
|
150
|
+
Add this line to your application's Gemfile:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
gem 'makeover'
|
154
|
+
```
|
155
|
+
|
156
|
+
And then execute:
|
157
|
+
```bash
|
158
|
+
$ bundle
|
159
|
+
```
|
160
|
+
|
161
|
+
Or install it yourself as:
|
162
|
+
```bash
|
163
|
+
$ gem install makeover
|
164
|
+
```
|
165
|
+
|
166
|
+
## Contributing
|
167
|
+
|
168
|
+
All contributions to this library must follow the [Code of Conduct][].
|
169
|
+
Please follow the instructions laid out in the issue and pull request
|
170
|
+
template for proper description formatting. We use [GitHub Issues][] as
|
171
|
+
a bug tracker, and only accept code contributions in the form of GitHub
|
172
|
+
Pull Requests.
|
173
|
+
|
174
|
+
## License
|
175
|
+
|
176
|
+
The gem is available as open source under the terms of the [MIT License][].
|
177
|
+
|
178
|
+
[decorator]: https://en.wikipedia.org/wiki/Decorator_pattern
|
179
|
+
[Rails]: http://rubyonrails.org
|
180
|
+
[Draper]: http://github.com/drapergem/draper
|
181
|
+
[ActiveSupport]: https://github.com/rails/rails/tree/master/activesupport
|
182
|
+
[stdlib]: http://ruby-doc.org
|
183
|
+
[Delegator]: http://ruby-doc.org/stdlib-2.2.1/libdoc/delegate/rdoc/Delegator.html
|
184
|
+
[Enumerable]: http://ruby-doc.org/core-2.2.1/Enumerable.html
|
185
|
+
[Code of Conduct]: https://github.com/tubbo/makeover/master/CODE_OF_CONDUCT.md
|
186
|
+
[GitHub Issues]: https://github.com/tubbo/makeover/issues
|
187
|
+
[MIT License]: http://opensource.org/licenses/MIT
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
require 'rubocop/rake_task'
|
5
|
+
require 'yard'
|
6
|
+
require 'bundler/gem_tasks'
|
7
|
+
require 'travis/release/task'
|
8
|
+
|
9
|
+
APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
|
10
|
+
|
11
|
+
load 'rails/tasks/engine.rake'
|
12
|
+
load 'rails/tasks/statistics.rake'
|
13
|
+
|
14
|
+
RSpec::Core::RakeTask.new :test
|
15
|
+
|
16
|
+
RuboCop::RakeTask.new :lint
|
17
|
+
|
18
|
+
Travis::Release::Task.new
|
19
|
+
|
20
|
+
YARD::Rake::YardocTask.new :doc
|
21
|
+
|
22
|
+
task default: [:test, :build]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Description:
|
2
|
+
Install the Makeover library into your Rails application.
|
3
|
+
|
4
|
+
Example:
|
5
|
+
rails generate makeover:install
|
6
|
+
|
7
|
+
This will create:
|
8
|
+
app/makeover/application_presenter.rb
|
9
|
+
app/makeover/collection_presenter.rb
|
10
|
+
|
11
|
+
This will also edit the following files:
|
12
|
+
app/controllers/application_controller.rb
|
13
|
+
app/models/application_record.rb
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Makeover
|
3
|
+
# Install the makeover library.
|
4
|
+
# More info: +rails g makeover:install --help+
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
7
|
+
|
8
|
+
MIXIN = "\n\s\sinclude Makeover::Presentable\n"
|
9
|
+
|
10
|
+
def copy_makeover
|
11
|
+
%w(application collection).each do |type|
|
12
|
+
filename = "app/presenters/#{type}_presenter.rb"
|
13
|
+
if File.exist? Rails.root.join(filename).to_s
|
14
|
+
copy_file "#{type}_presenter.rb", filename
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def inject_mixin
|
20
|
+
insert_into_file(
|
21
|
+
'app/models/application_record.rb',
|
22
|
+
MIXIN,
|
23
|
+
after: "self.abstract_class = true\n"
|
24
|
+
)
|
25
|
+
insert_into_file(
|
26
|
+
'app/controllers/application_controller.rb',
|
27
|
+
MIXIN,
|
28
|
+
after: "class ApplicationController < ActionController::Base\n"
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Generates a presenter. More info: +rails g presenter --help+.
|
4
|
+
class PresenterGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
class_option :collection, type: :boolean, default: false
|
7
|
+
|
8
|
+
def copy_presenter
|
9
|
+
template "#{presenter}.rb.erb", "app/presenters/#{file_name}_presenter.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
def copy_test
|
13
|
+
template(
|
14
|
+
"#{test}.rb.erb",
|
15
|
+
"#{test}/presenters/#{file_name}_presenter_#{test}.rb"
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def collection?
|
22
|
+
options[:collection] || plural?
|
23
|
+
end
|
24
|
+
|
25
|
+
def plural?
|
26
|
+
file_name == file_name.pluralize
|
27
|
+
end
|
28
|
+
|
29
|
+
def presenter
|
30
|
+
collection? ? 'collection_presenter' : 'presenter'
|
31
|
+
end
|
32
|
+
|
33
|
+
def test
|
34
|
+
Dir.exist?(Rails.root.join('spec').to_s) ? 'spec' : 'test'
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Makeover
|
3
|
+
# Presents +ActiveRecord::Relation+ objects as collections of
|
4
|
+
# presented models.
|
5
|
+
class CollectionPresenter < Presenter
|
6
|
+
prepend Enumerable
|
7
|
+
|
8
|
+
class_attribute :presenter_name
|
9
|
+
|
10
|
+
# Whenever model data is needed, records are first presented with
|
11
|
+
# the configured object.
|
12
|
+
def each
|
13
|
+
model.each { |record| yield record.present(with: presenter) }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def presenter
|
19
|
+
configured_presenter_name.constantize
|
20
|
+
end
|
21
|
+
|
22
|
+
def configured_presenter_name
|
23
|
+
presenter_name || "#{model_class_name}Presenter"
|
24
|
+
end
|
25
|
+
|
26
|
+
def model_class_name
|
27
|
+
self.class.name.demodulize.gsub(/Presenter/, '').classify
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Makeover
|
3
|
+
# Access view and route helpers from within the makeover.
|
4
|
+
class Helpers
|
5
|
+
include ActionView::Helpers
|
6
|
+
|
7
|
+
# Cache instances of +Rails.application.routes.url_helpers+ and
|
8
|
+
# +Rails.application.helpers+ when instantiated.
|
9
|
+
def initialize
|
10
|
+
self.class.send :include, Rails.application.routes.url_helpers
|
11
|
+
self.class.send :include, Rails.application.helpers
|
12
|
+
Rails.configuration.makeover.helpers.each do |helper|
|
13
|
+
self.class.send :include, helper
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Makeover
|
3
|
+
# Controller and model mixin for presenting objects.
|
4
|
+
module Presentable
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :presenter_class
|
9
|
+
class_attribute :collection_presenter_class
|
10
|
+
class_attribute :presentable_class_name
|
11
|
+
|
12
|
+
alias_method :decorate, :present
|
13
|
+
helper_method :present if respond_to? :helper_method
|
14
|
+
|
15
|
+
# @return [Class] Object used to present records.
|
16
|
+
def presenter_class
|
17
|
+
self.class.presenter_class || default_presenter_class
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Class] Object used to present collections.
|
21
|
+
def collection_presenter_class
|
22
|
+
self.class.collection_presenter_class || default_collection_presenter_class
|
23
|
+
end
|
24
|
+
|
25
|
+
# Find the class name we use to derive presenter constants.
|
26
|
+
#
|
27
|
+
# @return [String] Class name for presenter lookup.
|
28
|
+
def presentable_class_name
|
29
|
+
self.class.presentable_class_name || controller_class_name || self.class.name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class_methods do
|
34
|
+
# Configure the class used to present records by default
|
35
|
+
# within this object.
|
36
|
+
#
|
37
|
+
# @param [Class] custom_presenter_class
|
38
|
+
def presented_by(custom_presenter_class)
|
39
|
+
self.presenter_class = custom_presenter_class
|
40
|
+
end
|
41
|
+
|
42
|
+
# Configure the class used to present collections by default
|
43
|
+
# within this object.
|
44
|
+
#
|
45
|
+
# @param [Class] custom_presenter_class
|
46
|
+
def collection_presented_by(custom_presenter_class)
|
47
|
+
self.collection_presenter_class = custom_presenter_class
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Presents the given model or the current object with the current
|
52
|
+
# object's configured presenter or the given class in +with:+.
|
53
|
+
#
|
54
|
+
# @param [Object] model - Model class to present. (optional)
|
55
|
+
# @option [Class] :with - Presenter object that wraps the model.
|
56
|
+
# @option [Hash] **context - Additional context for the presenter in
|
57
|
+
# key/value pairs.
|
58
|
+
def present(model = nil, with: nil, **context)
|
59
|
+
model ||= self
|
60
|
+
with ||= model.try(:presenter_class) || presenter_class
|
61
|
+
|
62
|
+
if model.respond_to?(:each) && with != collection_presenter_class
|
63
|
+
return present model, with: collection_presenter_class, **context
|
64
|
+
else
|
65
|
+
with.new model, **context
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# @private
|
72
|
+
# @return [Class] Default singular presenter class name.
|
73
|
+
def default_presenter_class
|
74
|
+
"#{presentable_class_name}Presenter".constantize
|
75
|
+
end
|
76
|
+
|
77
|
+
# @private
|
78
|
+
# @return [Class] Default collection presenter class name.
|
79
|
+
def default_collection_presenter_class
|
80
|
+
"#{presentable_class_name.pluralize}Presenter".constantize
|
81
|
+
end
|
82
|
+
|
83
|
+
# Return the classified +controller_name+ if this object responds to
|
84
|
+
# a method like that (e.g., we're in a controller)
|
85
|
+
#
|
86
|
+
# @return [String] or +nil+ if not in a controller.
|
87
|
+
def controller_class_name
|
88
|
+
controller_name.classify if respond_to? :controller_name
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Makeover
|
3
|
+
# Base Presenter class for all decorator objects.
|
4
|
+
class Presenter < Delegator
|
5
|
+
attr_reader :model
|
6
|
+
|
7
|
+
def initialize(model, **context)
|
8
|
+
@model = model
|
9
|
+
context.each do |option, value|
|
10
|
+
instance_variable_set "@#{option}", value
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.delegate(*methods, to: :model, **options)
|
15
|
+
super(*methods, to: to, **options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def __getobj__
|
19
|
+
@model
|
20
|
+
end
|
21
|
+
|
22
|
+
def helpers
|
23
|
+
@helpers ||= Helpers.new
|
24
|
+
end
|
25
|
+
alias h helpers
|
26
|
+
end
|
27
|
+
end
|
data/lib/makeover.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'makeover/engine'
|
3
|
+
require 'makeover/version'
|
4
|
+
|
5
|
+
# A simple view model library for Rails applications.
|
6
|
+
module Makeover
|
7
|
+
extend ActiveSupport::Autoload
|
8
|
+
|
9
|
+
autoload :Helpers
|
10
|
+
autoload :Presenter
|
11
|
+
autoload :CollectionPresenter
|
12
|
+
autoload :Presentable
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,221 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: makeover
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.rc1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tom Scott
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-07-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pg
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: capybara
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: poltergeist
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: generator_spec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: travis-release
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: codeclimate-test-reporter
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: pry-byebug
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
description: View model library for Rails applications. Extracted from brother.ly.
|
168
|
+
email:
|
169
|
+
- tscott@weblinc.com
|
170
|
+
executables: []
|
171
|
+
extensions: []
|
172
|
+
extra_rdoc_files: []
|
173
|
+
files:
|
174
|
+
- CODE_OF_CONDUCT.md
|
175
|
+
- LICENSE.md
|
176
|
+
- README.md
|
177
|
+
- Rakefile
|
178
|
+
- lib/generators/makeover/install/USAGE
|
179
|
+
- lib/generators/makeover/install/install_generator.rb
|
180
|
+
- lib/generators/makeover/install/templates/application_presenter.rb
|
181
|
+
- lib/generators/makeover/install/templates/collection_presenter.rb
|
182
|
+
- lib/generators/presenter/USAGE
|
183
|
+
- lib/generators/presenter/presenter_generator.rb
|
184
|
+
- lib/generators/presenter/templates/collection_presenter.rb.erb
|
185
|
+
- lib/generators/presenter/templates/presenter.rb.erb
|
186
|
+
- lib/generators/presenter/templates/spec.rb.erb
|
187
|
+
- lib/generators/presenter/templates/test.rb.erb
|
188
|
+
- lib/makeover.rb
|
189
|
+
- lib/makeover/collection_presenter.rb
|
190
|
+
- lib/makeover/engine.rb
|
191
|
+
- lib/makeover/helpers.rb
|
192
|
+
- lib/makeover/presentable.rb
|
193
|
+
- lib/makeover/presenter.rb
|
194
|
+
- lib/makeover/version.rb
|
195
|
+
- lib/tasks/presenters_tasks.rake
|
196
|
+
homepage: http://github.com/tubbo/makeover
|
197
|
+
licenses:
|
198
|
+
- MIT
|
199
|
+
metadata: {}
|
200
|
+
post_install_message:
|
201
|
+
rdoc_options: []
|
202
|
+
require_paths:
|
203
|
+
- lib
|
204
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
210
|
+
requirements:
|
211
|
+
- - ">"
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: 1.3.1
|
214
|
+
requirements: []
|
215
|
+
rubyforge_project:
|
216
|
+
rubygems_version: 2.5.1
|
217
|
+
signing_key:
|
218
|
+
specification_version: 4
|
219
|
+
summary: View model library for Rails applications.
|
220
|
+
test_files: []
|
221
|
+
has_rdoc:
|