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.
Files changed (47) hide show
  1. data/README.md +141 -1
  2. data/lib/generators/prospecto/install/USAGE +12 -0
  3. data/lib/generators/prospecto/install/install_generator.rb +13 -0
  4. data/lib/generators/prospecto/install/templates/application_presenter.rb +6 -0
  5. data/lib/generators/prospecto/install/templates/application_presenter_spec.rb +4 -0
  6. data/lib/generators/{presenter → prospecto/presenter}/USAGE +1 -1
  7. data/lib/generators/prospecto/presenter/presenter_generator.rb +35 -0
  8. data/lib/generators/prospecto/presenter/templates/presenter.rb +13 -0
  9. data/lib/generators/{presenter → prospecto/presenter}/templates/presenter_spec.rb +0 -0
  10. data/lib/prospecto/presenter_view.rb +22 -1
  11. data/lib/prospecto/version.rb +1 -1
  12. metadata +22 -84
  13. data/lib/generators/presenter/presenter_generator.rb +0 -25
  14. data/lib/generators/presenter/templates/presenter.rb +0 -8
  15. data/test/dummy/README.rdoc +0 -261
  16. data/test/dummy/Rakefile +0 -7
  17. data/test/dummy/app/assets/javascripts/application.js +0 -15
  18. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  19. data/test/dummy/app/controllers/application_controller.rb +0 -3
  20. data/test/dummy/app/helpers/application_helper.rb +0 -2
  21. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  22. data/test/dummy/config/application.rb +0 -56
  23. data/test/dummy/config/boot.rb +0 -10
  24. data/test/dummy/config/database.yml +0 -25
  25. data/test/dummy/config/environment.rb +0 -5
  26. data/test/dummy/config/environments/development.rb +0 -37
  27. data/test/dummy/config/environments/production.rb +0 -67
  28. data/test/dummy/config/environments/test.rb +0 -37
  29. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  30. data/test/dummy/config/initializers/inflections.rb +0 -15
  31. data/test/dummy/config/initializers/mime_types.rb +0 -5
  32. data/test/dummy/config/initializers/secret_token.rb +0 -7
  33. data/test/dummy/config/initializers/session_store.rb +0 -8
  34. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  35. data/test/dummy/config/locales/en.yml +0 -5
  36. data/test/dummy/config/routes.rb +0 -58
  37. data/test/dummy/config.ru +0 -4
  38. data/test/dummy/log/development.log +0 -0
  39. data/test/dummy/log/test.log +0 -42
  40. data/test/dummy/public/404.html +0 -26
  41. data/test/dummy/public/422.html +0 -26
  42. data/test/dummy/public/500.html +0 -25
  43. data/test/dummy/public/favicon.ico +0 -0
  44. data/test/dummy/script/rails +0 -6
  45. data/test/prospecto_test.rb +0 -4
  46. data/test/test_helper.rb +0 -17
  47. data/test/view_test.rb +0 -17
data/README.md CHANGED
@@ -1,3 +1,143 @@
1
1
  # Prospecto
2
2
 
3
- *Simple rails presenter that emphasizes using plain old ruby.*
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,6 @@
1
+ class ApplicationPresenter < Prospecto::PresenterView
2
+ # Place common functionality here that will be shared with all presenters.
3
+
4
+ # Use of the Prospecto::PresenterView is completely optional and just gives a
5
+ # little initialization sugar.
6
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe ApplicationPresenter do
4
+ end
@@ -6,7 +6,7 @@ Description:
6
6
  presenter and the controller.
7
7
 
8
8
  Example:
9
- rails generate presenter User
9
+ rails generate prospecto:presenter User
10
10
 
11
11
  This will create:
12
12
  app/presenters/user_presenter.rb
@@ -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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Prospecto
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
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.1.3
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-05-17 00:00:00.000000000 Z
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: &70145041443540 !ruby/object:Gem::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: *70145041443540
24
+ version_requirements: *70296683085180
25
25
  - !ruby/object:Gem::Dependency
26
- name: sqlite3
27
- requirement: &70145041442140 !ruby/object:Gem::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: *70145041442140
35
+ version_requirements: *70296683083860
36
36
  - !ruby/object:Gem::Dependency
37
- name: turn
38
- requirement: &70145041441240 !ruby/object:Gem::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: *70145041441240
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/presenter/presenter_generator.rb
55
- - lib/generators/presenter/templates/presenter.rb
56
- - lib/generators/presenter/templates/presenter_spec.rb
57
- - lib/generators/presenter/USAGE
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: -2556641238186213598
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: -2556641238186213598
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: Seperation of views and templates for rails projects.
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
@@ -1,8 +0,0 @@
1
- class <%= class_name %>Presenter < Prospecto::PresenterView
2
- # The presenter class is completely optional and just gives a
3
- # little initialization sugar. Ala:
4
- #
5
- # accepts :<%= single_name %>
6
- # presents :<%= single_name %>_public
7
- #
8
- end