viewtastic 0.1.0 → 0.1.1
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 +82 -0
- data/init.rb +1 -0
- data/lib/duck_punches/array/each_with_presenter.rb +4 -0
- data/lib/viewtastic.rb +4 -0
- data/lib/viewtastic/activation.rb +1 -1
- data/lib/viewtastic/base.rb +101 -75
- metadata +5 -4
- data/README +0 -13
data/README.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# Viewtastic #
|
2
|
+
|
3
|
+
|
4
|
+
## Installation ##
|
5
|
+
|
6
|
+
Install the gem
|
7
|
+
|
8
|
+
gem install viewtastic
|
9
|
+
|
10
|
+
Load the gem in your `environment.rb` file
|
11
|
+
|
12
|
+
config.gem "viewtastic"
|
13
|
+
|
14
|
+
## Usage ##
|
15
|
+
|
16
|
+
My presenters go into the `app/presenters` directory of the application so this is added to the load_path in Rails by default by Viewtastic.
|
17
|
+
|
18
|
+
### Presenters ###
|
19
|
+
|
20
|
+
A Presenter inherits from `Viewtastic::Base` and should use the `presents` method to declare presented objects.
|
21
|
+
|
22
|
+
class CommentPresenter < Viewtastic::Base
|
23
|
+
presents :comment
|
24
|
+
end
|
25
|
+
|
26
|
+
This gives you several 'magic' methods:
|
27
|
+
|
28
|
+
* All attributes of comment with the prefix 'comment'. For instance: `comment_body`, `comment_post`, `comment_created_at`.
|
29
|
+
* `comment_dom_id` is the same as calling `dom_id(comment)` in a view.
|
30
|
+
|
31
|
+
If you want to skip the prefix and just have the attribute name, you can declare:
|
32
|
+
|
33
|
+
presents :comment => [:body, :created_at]
|
34
|
+
|
35
|
+
and you get `presenter.body` and `presenter.created_at`.
|
36
|
+
|
37
|
+
|
38
|
+
Assuming you have a `Comment` model and your controller has a helper method `current_user` that returns the user currently logged in, you could make the following presenter to help in presenting products.
|
39
|
+
|
40
|
+
class CommentPresenter < Viewtastic::Base
|
41
|
+
presents :comment
|
42
|
+
|
43
|
+
def dom_id
|
44
|
+
comment_dom_id
|
45
|
+
end
|
46
|
+
|
47
|
+
def owner?
|
48
|
+
controller.current_user.comments.include?(comment)
|
49
|
+
end
|
50
|
+
|
51
|
+
def links
|
52
|
+
returning([]) do |links|
|
53
|
+
links << link_to("Edit", [:edit, comment]) if owner?
|
54
|
+
links << link_to("Reply", [:new, :comment]) if controller.current_user
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
### Convenience ###
|
60
|
+
|
61
|
+
`each_with_presenter` is available on any `Array`, and it is designed to reuse a single Presenter instance and pass every element in the array as the presented object.
|
62
|
+
|
63
|
+
In your view (maybe `posts/show.html.erb`):
|
64
|
+
|
65
|
+
<ul>
|
66
|
+
<% @post.comments.each_with_presenter(CommentPresenter, :comment) do |comment| %>
|
67
|
+
<li id="<%= comment.dom_id %>">
|
68
|
+
<%= comment.body %>
|
69
|
+
<%= comment.links %>
|
70
|
+
</li>
|
71
|
+
<% end %>
|
72
|
+
</ul>
|
73
|
+
|
74
|
+
## Credits ##
|
75
|
+
|
76
|
+
* [ActivePresenter](http://github.com/giraffesoft/active_presenter) was the inspiration for this project and some of the presenter code was used from ActivePresenter.
|
77
|
+
* [Authlogic](http://github.com/binarylogic/authlogic) -- the Authlogic activation code is used to activate Viewtastic on each request.
|
78
|
+
|
79
|
+
## License ##
|
80
|
+
|
81
|
+
|
82
|
+
Copyright (c) 2009 Istvan Hoka, released under the MIT license
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Rails.configuration.load_paths << "app/presenters"
|
@@ -1,4 +1,8 @@
|
|
1
1
|
class Array
|
2
|
+
# Wrap each element in the Array with a presenter specified by @presenter_class@ and
|
3
|
+
# assigned as the model for @object_name@.
|
4
|
+
# @presenter_options@ are set once on the initial presenter instance.
|
5
|
+
#
|
2
6
|
def each_with_presenter(presenter_class, object_name, presenter_options={}, &block)
|
3
7
|
presenter = presenter_class.new(presenter_options)
|
4
8
|
each do |object|
|
data/lib/viewtastic.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Viewtastic
|
2
2
|
module Activation
|
3
3
|
# Lets Viewtastic know about the controller object via a before filter, AKA "activates" viewtastic.
|
4
|
-
# Borrowed from
|
4
|
+
# Borrowed from Authlogic.
|
5
5
|
#
|
6
6
|
def self.included(klass) # :nodoc:
|
7
7
|
if defined?(::ApplicationController)
|
data/lib/viewtastic/base.rb
CHANGED
@@ -1,101 +1,127 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Viewtastic
|
2
|
+
# Base class for presenters. See README.md for usage.
|
3
|
+
#
|
4
|
+
class Base
|
5
|
+
include ActionView::Helpers::UrlHelper
|
6
|
+
include ActionView::Helpers::TextHelper
|
7
|
+
include ActionView::Helpers::TagHelper
|
8
|
+
|
9
|
+
class_inheritable_accessor :presented
|
10
|
+
self.presented = []
|
5
11
|
|
6
|
-
|
7
|
-
|
12
|
+
delegate :protect_against_forgery?,
|
13
|
+
:request_forgery_protection_token,
|
14
|
+
:form_authenticity_token,
|
15
|
+
:dom_id,
|
16
|
+
:to => :controller
|
8
17
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
class << self
|
19
|
+
# Indicates which models are to be presented.
|
20
|
+
#
|
21
|
+
# class CommentPresenter < Viewtastic::Base
|
22
|
+
# presents :comment, :post
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# If you want to delegate messages to models without prefixing them with the model name, specify them in an Array:
|
26
|
+
#
|
27
|
+
# class PresenterWithTwoAddresses < ActivePresenter::Base
|
28
|
+
# presents :post, :comment => [:body, :created_at]
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
def presents(*types)
|
32
|
+
types_and_attributes = types.extract_options!
|
18
33
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
34
|
+
types_and_attributes.each do |name, delegates|
|
35
|
+
attr_accessor name
|
36
|
+
presented << name
|
37
|
+
delegates.each do |msg|
|
38
|
+
delegate msg, :to => name
|
39
|
+
end
|
24
40
|
end
|
25
|
-
end
|
26
41
|
|
27
|
-
|
28
|
-
|
42
|
+
attr_accessor *types
|
43
|
+
self.presented += types
|
29
44
|
|
30
|
-
|
31
|
-
|
32
|
-
|
45
|
+
presented.each do |name|
|
46
|
+
define_method("#{name}_dom_id") do |*args|
|
47
|
+
send(:dom_id, send(name), *args)
|
48
|
+
end
|
33
49
|
end
|
34
50
|
end
|
35
|
-
end
|
36
51
|
|
37
|
-
|
38
|
-
|
39
|
-
|
52
|
+
def controller=(value) #:nodoc:
|
53
|
+
Thread.current[:viewtastic_controller] = value
|
54
|
+
end
|
40
55
|
|
41
|
-
|
42
|
-
|
43
|
-
|
56
|
+
def controller #:nodoc:
|
57
|
+
Thread.current[:viewtastic_controller]
|
58
|
+
end
|
44
59
|
|
45
|
-
|
46
|
-
|
60
|
+
def activated? #:nodoc:
|
61
|
+
!controller.nil?
|
62
|
+
end
|
47
63
|
end
|
48
|
-
end
|
49
64
|
|
50
|
-
|
51
|
-
|
65
|
+
# Accepts arguments in two forms. If you had a CommentPresenter that presented a Comment model and a Post model, you would write the follwoing:
|
66
|
+
#
|
67
|
+
# 1. CommentPresenter.new(:comment => Comment.new, :post => @post)
|
68
|
+
# 2. CommentPresenter.new(Comment.new, @post) - it will introspect on the model's class; the order is not important.
|
69
|
+
#
|
70
|
+
# You can even mix the two:
|
71
|
+
# CommentPresenter.new(Comment.new, :post => @post)
|
72
|
+
#
|
73
|
+
def initialize(*values)
|
74
|
+
keys_and_values = values.extract_options!
|
52
75
|
|
53
|
-
|
54
|
-
|
55
|
-
|
76
|
+
keys_and_values.each do |name, instance|
|
77
|
+
send("#{name}=", instance)
|
78
|
+
end
|
56
79
|
|
57
|
-
|
58
|
-
|
80
|
+
values.each do |value|
|
81
|
+
send("#{value.class.name.underscore}=", value)
|
82
|
+
end
|
59
83
|
end
|
60
|
-
end
|
61
84
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
85
|
+
def method_missing(method_name, *args, &block)
|
86
|
+
if method_name.to_s =~ /_(path|url)$/
|
87
|
+
# Delegate all named routes to the controller
|
88
|
+
controller.send(method_name, *args)
|
89
|
+
elsif presented_attribute?(method_name)
|
90
|
+
delegate_message(method_name, *args, &block)
|
91
|
+
else
|
92
|
+
super
|
93
|
+
end
|
70
94
|
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def controller
|
74
|
-
self.class.controller
|
75
|
-
end
|
76
95
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
96
|
+
# The current controller performing the request is accessible with this.
|
97
|
+
#
|
98
|
+
def controller
|
99
|
+
self.class.controller
|
81
100
|
end
|
101
|
+
|
102
|
+
protected
|
103
|
+
def delegate_message(method_name, *args, &block) #:nodoc:
|
104
|
+
presentable = presentable_for(method_name)
|
105
|
+
send(presentable).send(flatten_attribute_name(method_name, presentable), *args, &block)
|
106
|
+
end
|
82
107
|
|
83
|
-
|
84
|
-
|
85
|
-
|
108
|
+
def presentable_for(method_name) #:nodoc:
|
109
|
+
presented.sort_by { |k| k.to_s.size }.reverse.detect do |type|
|
110
|
+
method_name.to_s.starts_with?(attribute_prefix(type))
|
111
|
+
end
|
86
112
|
end
|
87
|
-
end
|
88
113
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
114
|
+
def presented_attribute?(method_name) #:nodoc:
|
115
|
+
p = presentable_for(method_name)
|
116
|
+
!p.nil? && send(p).respond_to?(flatten_attribute_name(method_name,p))
|
117
|
+
end
|
93
118
|
|
94
|
-
|
95
|
-
|
96
|
-
|
119
|
+
def flatten_attribute_name(name, type) #:nodoc:
|
120
|
+
name.to_s.gsub(/^#{attribute_prefix(type)}/, '')
|
121
|
+
end
|
97
122
|
|
98
|
-
|
99
|
-
|
100
|
-
|
123
|
+
def attribute_prefix(type) #:nodoc:
|
124
|
+
"#{type}_"
|
125
|
+
end
|
126
|
+
end
|
101
127
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: viewtastic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Istvan Hoka
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-12-01 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -21,15 +21,16 @@ extensions: []
|
|
21
21
|
|
22
22
|
extra_rdoc_files:
|
23
23
|
- LICENSE
|
24
|
-
- README
|
24
|
+
- README.md
|
25
25
|
files:
|
26
26
|
- LICENSE
|
27
|
+
- init.rb
|
27
28
|
- lib/duck_punches/array/each_with_presenter.rb
|
28
29
|
- lib/viewtastic.rb
|
29
30
|
- lib/viewtastic/activation.rb
|
30
31
|
- lib/viewtastic/base.rb
|
31
32
|
- lib/viewtastic/test_case.rb
|
32
|
-
- README
|
33
|
+
- README.md
|
33
34
|
has_rdoc: true
|
34
35
|
homepage: http://github.com/ihoka/viewtastic
|
35
36
|
licenses: []
|