prospecto 0.1.3 → 0.2.0
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.
- data/README.md +141 -1
- data/lib/generators/prospecto/install/USAGE +12 -0
- data/lib/generators/prospecto/install/install_generator.rb +13 -0
- data/lib/generators/prospecto/install/templates/application_presenter.rb +6 -0
- data/lib/generators/prospecto/install/templates/application_presenter_spec.rb +4 -0
- data/lib/generators/{presenter → prospecto/presenter}/USAGE +1 -1
- data/lib/generators/prospecto/presenter/presenter_generator.rb +35 -0
- data/lib/generators/prospecto/presenter/templates/presenter.rb +13 -0
- data/lib/generators/{presenter → prospecto/presenter}/templates/presenter_spec.rb +0 -0
- data/lib/prospecto/presenter_view.rb +22 -1
- data/lib/prospecto/version.rb +1 -1
- metadata +22 -84
- data/lib/generators/presenter/presenter_generator.rb +0 -25
- data/lib/generators/presenter/templates/presenter.rb +0 -8
- data/test/dummy/README.rdoc +0 -261
- data/test/dummy/Rakefile +0 -7
- data/test/dummy/app/assets/javascripts/application.js +0 -15
- data/test/dummy/app/assets/stylesheets/application.css +0 -13
- data/test/dummy/app/controllers/application_controller.rb +0 -3
- data/test/dummy/app/helpers/application_helper.rb +0 -2
- data/test/dummy/app/views/layouts/application.html.erb +0 -14
- data/test/dummy/config/application.rb +0 -56
- data/test/dummy/config/boot.rb +0 -10
- data/test/dummy/config/database.yml +0 -25
- data/test/dummy/config/environment.rb +0 -5
- data/test/dummy/config/environments/development.rb +0 -37
- data/test/dummy/config/environments/production.rb +0 -67
- data/test/dummy/config/environments/test.rb +0 -37
- data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/test/dummy/config/initializers/inflections.rb +0 -15
- data/test/dummy/config/initializers/mime_types.rb +0 -5
- data/test/dummy/config/initializers/secret_token.rb +0 -7
- data/test/dummy/config/initializers/session_store.rb +0 -8
- data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/test/dummy/config/locales/en.yml +0 -5
- data/test/dummy/config/routes.rb +0 -58
- data/test/dummy/config.ru +0 -4
- data/test/dummy/log/development.log +0 -0
- data/test/dummy/log/test.log +0 -42
- data/test/dummy/public/404.html +0 -26
- data/test/dummy/public/422.html +0 -26
- data/test/dummy/public/500.html +0 -25
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +0 -6
- data/test/prospecto_test.rb +0 -4
- data/test/test_helper.rb +0 -17
- data/test/view_test.rb +0 -17
data/README.md
CHANGED
@@ -1,3 +1,143 @@
|
|
1
1
|
# Prospecto
|
2
2
|
|
3
|
-
*Simple rails presenter
|
3
|
+
*Simple rails presenter with an emphasis on just using ruby.*
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'prospecto'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install prospecto
|
18
|
+
|
19
|
+
## Overview
|
20
|
+
|
21
|
+
There are 2 problems that prospecto was created to solve.
|
22
|
+
|
23
|
+
1. Views are hard and ineffective to test.
|
24
|
+
2. Code is often common between the output formats.
|
25
|
+
|
26
|
+
We feel that (our interpretation of) the presenter pattern is the answer to these problems. To be clear, you
|
27
|
+
do not need a library to implement the presenter pattern. The purpose of prospecto is to provide some syntactic
|
28
|
+
sugar and structure.
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
### ApplicationPresenter
|
33
|
+
|
34
|
+
To start it is recommended (but not required) that you generate an `ApplicationPresenter`. This will act
|
35
|
+
as a base class for all other presenters much like an `ApplicationController`. Just use the built in
|
36
|
+
generator:
|
37
|
+
|
38
|
+
$ rails generate prospecto:install
|
39
|
+
|
40
|
+
### Presenter
|
41
|
+
|
42
|
+
You are now ready to start creating presenters. In prospecto a presenter does not necessarily correlate with
|
43
|
+
a model (though this often ends up as the case), instead a presenter represents a view or family of views
|
44
|
+
depending on the situation. This is up to you to decide.
|
45
|
+
|
46
|
+
To create a simple presenter use the included generator:
|
47
|
+
|
48
|
+
$rails generate prospecto:presenter User
|
49
|
+
|
50
|
+
### Prospecto::PresenterView
|
51
|
+
|
52
|
+
By default all presenters inherit from the `Prospecto::PresenterView` class. This class is optional and exists
|
53
|
+
solely to provide some sugar for creating constructors for objects.
|
54
|
+
|
55
|
+
#### accepts
|
56
|
+
|
57
|
+
The `accepts` method is the most encouraged. It creates a private accessor for
|
58
|
+
the provided value.
|
59
|
+
|
60
|
+
``` ruby
|
61
|
+
class UserPresenter < Prospecto::PresenterView
|
62
|
+
accepts :user
|
63
|
+
|
64
|
+
def name
|
65
|
+
"#{user.first} #{user.last}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
view = UserPresenter.new(user: @user)
|
70
|
+
puts user.name
|
71
|
+
```
|
72
|
+
|
73
|
+
#### decorates
|
74
|
+
|
75
|
+
The `decorates` method allows the provided value to be accessed directly on the
|
76
|
+
presenter. This is simalar to how something like [draper](https://github.com/jcasimir/draper)
|
77
|
+
works.
|
78
|
+
|
79
|
+
``` ruby
|
80
|
+
class UserPresenter < Prospecto::PresenterView
|
81
|
+
decorates :user
|
82
|
+
end
|
83
|
+
|
84
|
+
view = UserPresenter.new(user: @user)
|
85
|
+
puts "#{view.first} #{view.last}"
|
86
|
+
```
|
87
|
+
|
88
|
+
#### proxies
|
89
|
+
|
90
|
+
The `proxies` method creates named methods on the presenter for the provided value.
|
91
|
+
|
92
|
+
``` ruby
|
93
|
+
class UserPresenter < Prospecto::PresenterView
|
94
|
+
proxies :user
|
95
|
+
end
|
96
|
+
|
97
|
+
view = UserPresenter.new(user: @user)
|
98
|
+
puts "#{view.user_first} #{view.user_last}"
|
99
|
+
```
|
100
|
+
|
101
|
+
#### presents
|
102
|
+
|
103
|
+
The `presents` method is creates a public accessor for the provided value. Use
|
104
|
+
of this is discouraged.
|
105
|
+
|
106
|
+
``` ruby
|
107
|
+
class UserPresenter < Prospecto::PresenterView
|
108
|
+
presents :user_public
|
109
|
+
end
|
110
|
+
|
111
|
+
view = UserPresenter.new(user_public: @user)
|
112
|
+
puts "#{view.user_public.first} #{view.user_public.last}"
|
113
|
+
```
|
114
|
+
|
115
|
+
### Rails Views and Controllers
|
116
|
+
|
117
|
+
How you use the presenters is very loose. Since you are just dealing with pretty vanilla
|
118
|
+
ruby objects you can instantiate where it makes the most sense for your project. Usually
|
119
|
+
basic usage looks something like this.
|
120
|
+
|
121
|
+
``` ruby
|
122
|
+
class UserController < ApplicationController
|
123
|
+
def index
|
124
|
+
users = User.where(active: true)
|
125
|
+
@view = UserPresenter.new(users: users)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
```
|
129
|
+
|
130
|
+
You then use the `@view` object like normal in the view.
|
131
|
+
|
132
|
+
## Contributing
|
133
|
+
|
134
|
+
1. Fork it
|
135
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
136
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
137
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
138
|
+
5. Create new Pull Request
|
139
|
+
|
140
|
+
## Sponsor
|
141
|
+
|
142
|
+
Development for prospecto is sponsored mainly by my employer [Voonami](http://www.voonami.com)
|
143
|
+
since we use it heavily in house.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Description:
|
2
|
+
Generate a base ApplicationPresenter class.
|
3
|
+
|
4
|
+
This is completely optional. If an ApplicationPresenter is not found then
|
5
|
+
not base class will be set on new presenters.
|
6
|
+
|
7
|
+
Example:
|
8
|
+
rails generate prospecto:install
|
9
|
+
|
10
|
+
This will create:
|
11
|
+
app/presenters/application_presenter.rb
|
12
|
+
spec/presenters/application_presenter_spec.rb
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Prospecto
|
2
|
+
class InstallGenerator < Rails::Generators::Base
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
4
|
+
|
5
|
+
def write_application_presenter
|
6
|
+
template 'application_presenter.rb', "app/presenters/application_presenter.rb"
|
7
|
+
end
|
8
|
+
|
9
|
+
def write_application_presenter_spec
|
10
|
+
template 'application_presenter_spec.rb', "spec/presenters/application_presenter_spec.rb"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Prospecto
|
2
|
+
class PresenterGenerator < Rails::Generators::NamedBase
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
4
|
+
|
5
|
+
def write_presenter
|
6
|
+
template 'presenter.rb', "app/presenters/#{file_name_root}_presenter.rb"
|
7
|
+
end
|
8
|
+
|
9
|
+
def write_presenter_spec
|
10
|
+
template 'presenter_spec.rb', "spec/presenters/#{file_name_root}_presenter_spec.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def file_name_root
|
16
|
+
name.underscore
|
17
|
+
end
|
18
|
+
|
19
|
+
def class_name
|
20
|
+
name.camelize
|
21
|
+
end
|
22
|
+
|
23
|
+
def single_name
|
24
|
+
name.underscore.singularize
|
25
|
+
end
|
26
|
+
|
27
|
+
def base_class
|
28
|
+
if File.exists?(Rails.root.join("app/presenters/application_presenter.rb"))
|
29
|
+
"ApplicationPresenter"
|
30
|
+
else
|
31
|
+
"Prospecto::PresenterView"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class <%= class_name %>Presenter < <%= base_class %>
|
2
|
+
# Use of the Prospecto::PresenterView is completely optional and just gives a
|
3
|
+
# little initialization sugar. Ala:
|
4
|
+
#
|
5
|
+
# Create a private accessor:
|
6
|
+
# accepts :<%= single_name %>
|
7
|
+
#
|
8
|
+
# Create a public accessor:
|
9
|
+
# presents :<%= single_name %>_public
|
10
|
+
#
|
11
|
+
# Create named proxy methods:
|
12
|
+
# proxies :<%= single_name %>
|
13
|
+
end
|
File without changes
|
@@ -1,9 +1,13 @@
|
|
1
|
+
require "set"
|
2
|
+
|
1
3
|
module Prospecto
|
2
4
|
class PresenterView
|
3
5
|
def initialize(args={})
|
4
6
|
args.each do |name, value|
|
5
7
|
if respond_to? name
|
6
8
|
instance_variable_set("@#{name}", value)
|
9
|
+
elsif self.class.__delegates.include?(name)
|
10
|
+
__delegates << value
|
7
11
|
else
|
8
12
|
# Stop everything there is a design problem.
|
9
13
|
raise ArgumentError.new("Unknown property '#{name}' for class '#{self.class.name}'.")
|
@@ -15,18 +19,28 @@ module Prospecto
|
|
15
19
|
if property_name = self.class.__properties.find{|m| name.to_s.start_with? "#{m}_"}
|
16
20
|
field_name = name.to_s.sub("#{property_name}_", "")
|
17
21
|
self.send(property_name).send(field_name)
|
22
|
+
elsif delegate_obj = __delegates.find{|d| d.respond_to? name}
|
23
|
+
delegate_obj.send(name)
|
18
24
|
else
|
19
25
|
super
|
20
26
|
end
|
21
27
|
end
|
22
28
|
|
29
|
+
def __delegates
|
30
|
+
@__delegates ||= Set.new
|
31
|
+
end
|
32
|
+
|
23
33
|
class << self
|
24
34
|
# "Presents" means a member will be reflected out to the view. Use of presents should be
|
25
35
|
# limited to very special cases.
|
26
36
|
alias :presents :attr_reader
|
27
37
|
|
28
38
|
def __properties
|
29
|
-
@__properties ||=
|
39
|
+
@__properties ||= Set.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def __delegates
|
43
|
+
@__delegates ||= Set.new
|
30
44
|
end
|
31
45
|
|
32
46
|
# Accepts means the view uses the member internally, but it is not available
|
@@ -48,6 +62,13 @@ module Prospecto
|
|
48
62
|
end
|
49
63
|
accepts(*args)
|
50
64
|
end
|
65
|
+
|
66
|
+
# Decorates means that properties of the object will be available directly on the presenter.
|
67
|
+
def decorates(*args)
|
68
|
+
args.each do |name|
|
69
|
+
__delegates << name
|
70
|
+
end
|
71
|
+
end
|
51
72
|
end
|
52
73
|
end
|
53
74
|
end
|
data/lib/prospecto/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prospecto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &70296683085180 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.1.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70296683085180
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement: &
|
26
|
+
name: rspec
|
27
|
+
requirement: &70296683083860 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70296683083860
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement: &
|
37
|
+
name: pry
|
38
|
+
requirement: &70296683082860 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70296683082860
|
47
47
|
description: ''
|
48
48
|
email:
|
49
49
|
- bigjasonwebb@gmail.com
|
@@ -51,10 +51,14 @@ executables: []
|
|
51
51
|
extensions: []
|
52
52
|
extra_rdoc_files: []
|
53
53
|
files:
|
54
|
-
- lib/generators/
|
55
|
-
- lib/generators/
|
56
|
-
- lib/generators/
|
57
|
-
- lib/generators/
|
54
|
+
- lib/generators/prospecto/install/install_generator.rb
|
55
|
+
- lib/generators/prospecto/install/templates/application_presenter.rb
|
56
|
+
- lib/generators/prospecto/install/templates/application_presenter_spec.rb
|
57
|
+
- lib/generators/prospecto/install/USAGE
|
58
|
+
- lib/generators/prospecto/presenter/presenter_generator.rb
|
59
|
+
- lib/generators/prospecto/presenter/templates/presenter.rb
|
60
|
+
- lib/generators/prospecto/presenter/templates/presenter_spec.rb
|
61
|
+
- lib/generators/prospecto/presenter/USAGE
|
58
62
|
- lib/prospecto/presenter_view.rb
|
59
63
|
- lib/prospecto/railtie.rb
|
60
64
|
- lib/prospecto/version.rb
|
@@ -63,39 +67,6 @@ files:
|
|
63
67
|
- MIT-LICENSE
|
64
68
|
- Rakefile
|
65
69
|
- README.md
|
66
|
-
- test/dummy/app/assets/javascripts/application.js
|
67
|
-
- test/dummy/app/assets/stylesheets/application.css
|
68
|
-
- test/dummy/app/controllers/application_controller.rb
|
69
|
-
- test/dummy/app/helpers/application_helper.rb
|
70
|
-
- test/dummy/app/views/layouts/application.html.erb
|
71
|
-
- test/dummy/config/application.rb
|
72
|
-
- test/dummy/config/boot.rb
|
73
|
-
- test/dummy/config/database.yml
|
74
|
-
- test/dummy/config/environment.rb
|
75
|
-
- test/dummy/config/environments/development.rb
|
76
|
-
- test/dummy/config/environments/production.rb
|
77
|
-
- test/dummy/config/environments/test.rb
|
78
|
-
- test/dummy/config/initializers/backtrace_silencers.rb
|
79
|
-
- test/dummy/config/initializers/inflections.rb
|
80
|
-
- test/dummy/config/initializers/mime_types.rb
|
81
|
-
- test/dummy/config/initializers/secret_token.rb
|
82
|
-
- test/dummy/config/initializers/session_store.rb
|
83
|
-
- test/dummy/config/initializers/wrap_parameters.rb
|
84
|
-
- test/dummy/config/locales/en.yml
|
85
|
-
- test/dummy/config/routes.rb
|
86
|
-
- test/dummy/config.ru
|
87
|
-
- test/dummy/log/development.log
|
88
|
-
- test/dummy/log/test.log
|
89
|
-
- test/dummy/public/404.html
|
90
|
-
- test/dummy/public/422.html
|
91
|
-
- test/dummy/public/500.html
|
92
|
-
- test/dummy/public/favicon.ico
|
93
|
-
- test/dummy/Rakefile
|
94
|
-
- test/dummy/README.rdoc
|
95
|
-
- test/dummy/script/rails
|
96
|
-
- test/prospecto_test.rb
|
97
|
-
- test/test_helper.rb
|
98
|
-
- test/view_test.rb
|
99
70
|
homepage: http://github.com/bigjason/prospecto
|
100
71
|
licenses: []
|
101
72
|
post_install_message:
|
@@ -110,7 +81,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
110
81
|
version: '0'
|
111
82
|
segments:
|
112
83
|
- 0
|
113
|
-
hash: -
|
84
|
+
hash: -977387351276312960
|
114
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
86
|
none: false
|
116
87
|
requirements:
|
@@ -119,44 +90,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
90
|
version: '0'
|
120
91
|
segments:
|
121
92
|
- 0
|
122
|
-
hash: -
|
93
|
+
hash: -977387351276312960
|
123
94
|
requirements: []
|
124
95
|
rubyforge_project:
|
125
96
|
rubygems_version: 1.8.10
|
126
97
|
signing_key:
|
127
98
|
specification_version: 3
|
128
|
-
summary:
|
129
|
-
test_files:
|
130
|
-
- test/dummy/app/assets/javascripts/application.js
|
131
|
-
- test/dummy/app/assets/stylesheets/application.css
|
132
|
-
- test/dummy/app/controllers/application_controller.rb
|
133
|
-
- test/dummy/app/helpers/application_helper.rb
|
134
|
-
- test/dummy/app/views/layouts/application.html.erb
|
135
|
-
- test/dummy/config/application.rb
|
136
|
-
- test/dummy/config/boot.rb
|
137
|
-
- test/dummy/config/database.yml
|
138
|
-
- test/dummy/config/environment.rb
|
139
|
-
- test/dummy/config/environments/development.rb
|
140
|
-
- test/dummy/config/environments/production.rb
|
141
|
-
- test/dummy/config/environments/test.rb
|
142
|
-
- test/dummy/config/initializers/backtrace_silencers.rb
|
143
|
-
- test/dummy/config/initializers/inflections.rb
|
144
|
-
- test/dummy/config/initializers/mime_types.rb
|
145
|
-
- test/dummy/config/initializers/secret_token.rb
|
146
|
-
- test/dummy/config/initializers/session_store.rb
|
147
|
-
- test/dummy/config/initializers/wrap_parameters.rb
|
148
|
-
- test/dummy/config/locales/en.yml
|
149
|
-
- test/dummy/config/routes.rb
|
150
|
-
- test/dummy/config.ru
|
151
|
-
- test/dummy/log/development.log
|
152
|
-
- test/dummy/log/test.log
|
153
|
-
- test/dummy/public/404.html
|
154
|
-
- test/dummy/public/422.html
|
155
|
-
- test/dummy/public/500.html
|
156
|
-
- test/dummy/public/favicon.ico
|
157
|
-
- test/dummy/Rakefile
|
158
|
-
- test/dummy/README.rdoc
|
159
|
-
- test/dummy/script/rails
|
160
|
-
- test/prospecto_test.rb
|
161
|
-
- test/test_helper.rb
|
162
|
-
- test/view_test.rb
|
99
|
+
summary: Simple rails presenter with an emphasis on just using ruby.
|
100
|
+
test_files: []
|
@@ -1,25 +0,0 @@
|
|
1
|
-
class PresenterGenerator < Rails::Generators::NamedBase
|
2
|
-
source_root File.expand_path('../templates', __FILE__)
|
3
|
-
|
4
|
-
def write_presenter
|
5
|
-
template 'presenter.rb', "app/presenters/#{file_name_root}_presenter.rb"
|
6
|
-
end
|
7
|
-
|
8
|
-
def write_presenter_spec
|
9
|
-
template 'presenter_spec.rb', "spec/presenters/#{file_name_root}_presenter_spec.rb"
|
10
|
-
end
|
11
|
-
|
12
|
-
protected
|
13
|
-
|
14
|
-
def file_name_root
|
15
|
-
name.underscore
|
16
|
-
end
|
17
|
-
|
18
|
-
def class_name
|
19
|
-
name.camelize
|
20
|
-
end
|
21
|
-
|
22
|
-
def single_name
|
23
|
-
name.underscore.singularize
|
24
|
-
end
|
25
|
-
end
|