prospecto 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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