view 1.0.0.alpha.1 → 1.0.0.alpha.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +29 -44
- data/lib/view/formatter.rb +126 -35
- data/lib/view/formatters/array.rb +32 -0
- data/lib/view/formatters/auto.rb +47 -24
- data/lib/view/formatters/blank.rb +20 -0
- data/lib/view/formatters/boolean.rb +17 -1
- data/lib/view/formatters/currency.rb +1 -1
- data/lib/view/formatters/date.rb +3 -2
- data/lib/view/formatters/datetime.rb +3 -2
- data/lib/view/formatters/delimited.rb +1 -1
- data/lib/view/formatters/file_link.rb +1 -1
- data/lib/view/formatters/guess.rb +18 -0
- data/lib/view/formatters/html_safe.rb +2 -1
- data/lib/view/formatters/human.rb +1 -1
- data/lib/view/formatters/image.rb +1 -1
- data/lib/view/formatters/link.rb +1 -1
- data/lib/view/formatters/percentage.rb +1 -1
- data/lib/view/formatters/phone.rb +1 -1
- data/lib/view/formatters/precision.rb +1 -1
- data/lib/view/formatters/self.rb +4 -1
- data/lib/view/formatters/sentence.rb +18 -23
- data/lib/view/formatters/size.rb +1 -1
- data/lib/view/helper.rb +1 -1
- data/lib/view/version.rb +1 -1
- data/lib/view.rb +81 -13
- data/spec/view/formatter_spec.rb +13 -0
- data/spec/view/formatters/auto_spec.rb +13 -16
- data/spec/view/formatters/blank_spec.rb +23 -0
- data/spec/view/formatters/boolean_spec.rb +6 -6
- data/spec/view/formatters/date_spec.rb +3 -3
- data/spec/view/formatters/datetime_spec.rb +2 -2
- data/spec/view/formatters/guess_spec.rb +25 -0
- data/spec/view/formatters/self_spec.rb +1 -1
- data/spec/view/formatters/sentence_spec.rb +17 -1
- metadata +28 -10
- data/lib/view/formatters/nil.rb +0 -11
- data/spec/view/formatters/nil_spec.rb +0 -15
- data/spec/view/view_spec.rb +0 -13
data/README.rdoc
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
= View
|
2
2
|
|
3
|
+
{Source}[http://github.com/iain/view] | {Documentation}[http://rubydoc.info/github/iain/view/master/frames]
|
4
|
+
|
3
5
|
Automatic viewer. Very configurable. Very flexible. Very alpha (for now).
|
4
6
|
|
5
7
|
It is made for displaying stuff in views. This can be very handy for DSLs that create views.
|
@@ -11,7 +13,7 @@ But first, the view!
|
|
11
13
|
|
12
14
|
Use it from your views:
|
13
15
|
|
14
|
-
|
16
|
+
<%= view @post %>
|
15
17
|
|
16
18
|
View will try to figure out what the most logical way is to present the object you passed in.
|
17
19
|
If the @post object has a title for instance, it will use that.
|
@@ -20,7 +22,7 @@ See the auto formatter for more information.
|
|
20
22
|
|
21
23
|
You can use view anywhere you like:
|
22
24
|
|
23
|
-
puts View.
|
25
|
+
puts View.format(@post)
|
24
26
|
|
25
27
|
But beware that for many formatters, a reference to the template is required.
|
26
28
|
It is a helper for the view part of your application after all.
|
@@ -29,55 +31,56 @@ It is a helper for the view part of your application after all.
|
|
29
31
|
|
30
32
|
View will automatically try to choose the proper formatter. You can specify a formatter yourself:
|
31
33
|
|
32
|
-
|
34
|
+
<%= view @post.created_at, :as => :date %>
|
33
35
|
|
34
36
|
You can add a block to specify your own behavior. The parsed value is passed in as a block-variable.
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
+
<%= view @post.author do |author| %>
|
39
|
+
<%= link_to author, @post.author %>
|
40
|
+
<% end %>
|
38
41
|
|
39
42
|
Most formatters pass their options down to the method they use, such as the image formatter:
|
40
43
|
|
41
|
-
|
44
|
+
<%= view @user.avatar, :as => :image, :size => "40x40", :class => "avatar" %>
|
42
45
|
|
43
46
|
== Examples
|
44
47
|
|
45
48
|
There are many formatters included (18 and counting), but here are some interesting use cases of some of them.
|
46
49
|
|
47
50
|
# Options are passed to the helper methods:
|
48
|
-
|
51
|
+
view @post, :as => :link, :method => :delete, :confirm => "are you sure?"
|
49
52
|
|
50
53
|
# Renders a link to the edit_page of the post:
|
51
|
-
|
54
|
+
view @post, :as => :link, :path => [ :edit ]
|
52
55
|
|
53
56
|
# Renders a sentence of links:
|
54
|
-
|
57
|
+
view Post.all, :each => { :as => :link }
|
55
58
|
|
56
59
|
# When using paperclip, renders the image:
|
57
|
-
|
60
|
+
view @project.logo, :as => :image
|
58
61
|
|
59
62
|
# Renders "yes" or "no" (with I18n support!)
|
60
|
-
|
63
|
+
view @user.admin?
|
61
64
|
|
62
65
|
See the formatters in lib/views/formatters to see their full documentation.
|
63
66
|
|
64
67
|
== Adding formatters
|
65
68
|
|
66
|
-
You can add a formatter by inheriting from View::Formatter
|
67
|
-
The only method you need to implement is the
|
69
|
+
You can add a formatter by inheriting from +View::Formatter+.
|
70
|
+
The only method you need to implement is the +format+ method.
|
68
71
|
|
69
72
|
In the class you have access to the following methods:
|
70
73
|
|
71
|
-
* value
|
72
|
-
* options
|
73
|
-
* all_options
|
74
|
-
* template
|
74
|
+
* +value+: the object passed in
|
75
|
+
* +options+: a filtered hash of options
|
76
|
+
* +all_options+: the unfiltered hash
|
77
|
+
* +template+: call methods like link_to on this
|
75
78
|
|
76
79
|
If you wanted a uppercase formatter for example, you could do this:
|
77
80
|
|
78
81
|
class Uppercase < View::Formatter
|
79
82
|
|
80
|
-
def
|
83
|
+
def format
|
81
84
|
value.to_s.upcase
|
82
85
|
end
|
83
86
|
|
@@ -85,7 +88,7 @@ If you wanted a uppercase formatter for example, you could do this:
|
|
85
88
|
|
86
89
|
The name of the formatter is automatically infered from the name of the class.
|
87
90
|
|
88
|
-
You can use the
|
91
|
+
You can use the +.as+ method to specify a different name.
|
89
92
|
|
90
93
|
class Foo < View::Formatter
|
91
94
|
as :bar
|
@@ -99,20 +102,20 @@ You can control which options are allowed, by adding reserved options:
|
|
99
102
|
end
|
100
103
|
|
101
104
|
Now, the options method will return the options passed by the user, minus foo and bar.
|
102
|
-
To use them, in your code, use the all_options method.
|
105
|
+
To use them, in your code, use the +all_options+ method.
|
103
106
|
This is done to easily pass the options to another method, without cluttering:
|
104
107
|
|
105
108
|
class Paragraph < View::Formatter
|
106
|
-
def
|
109
|
+
def format
|
107
110
|
template.content_tag(:p, value.to_s, options)
|
108
111
|
end
|
109
112
|
end
|
110
113
|
|
111
|
-
To more tightly control which options are allowed, specify the
|
114
|
+
To more tightly control which options are allowed, specify the allowed options:
|
112
115
|
|
113
116
|
class Size < View::Formatter
|
114
117
|
self.allowed_options = [ :separator, :delimiter, :precision ]
|
115
|
-
def
|
118
|
+
def format
|
116
119
|
template.number_to_human_size(value, options)
|
117
120
|
end
|
118
121
|
end
|
@@ -121,33 +124,15 @@ You can use the existing formatters as examples.
|
|
121
124
|
|
122
125
|
== Configuration:
|
123
126
|
|
124
|
-
See lib/view.rb for information on configuration.
|
127
|
+
See +lib/view.rb+ for information on configuration.
|
125
128
|
|
126
129
|
== Installation
|
127
130
|
|
128
|
-
|
129
|
-
|
130
|
-
In Rails 3, just add it to your Gemfile:
|
131
|
+
Just add it to your Gemfile:
|
131
132
|
|
132
133
|
gem 'view'
|
133
134
|
|
134
|
-
Run
|
135
|
-
|
136
|
-
=== Rails 2
|
137
|
-
|
138
|
-
In Rails 2, add it to app/environment.rb:
|
139
|
-
|
140
|
-
config.gem 'view'
|
141
|
-
|
142
|
-
And run <tt>rake gems:install</tt> to get it.
|
143
|
-
|
144
|
-
Afterwards, include the helper mehtod manually, by editing app/helpers/application_helper.rb:
|
145
|
-
|
146
|
-
module ApplicationHelper
|
147
|
-
include View::Helper
|
148
|
-
end
|
149
|
-
|
150
|
-
Caution: some helpers may use new helper methods from Rails 3 and might not work in Rails 2.
|
135
|
+
Run +bundle install+ and you're ready to go!
|
151
136
|
|
152
137
|
== Contributing
|
153
138
|
|
data/lib/view/formatter.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module View
|
2
2
|
|
3
|
+
# @abstract Subclass and override {#format} to implement your own formatter.
|
3
4
|
class Formatter
|
4
5
|
|
5
6
|
attr_reader :value, :template, :block
|
@@ -13,58 +14,150 @@ module View
|
|
13
14
|
class_inheritable_array :allowed_options
|
14
15
|
self.allowed_options = []
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
@options = options
|
19
|
-
@template = template
|
20
|
-
@block = block
|
21
|
-
end
|
22
|
-
|
17
|
+
# When you inherit from View::Formatter, the formatters goes on the list,
|
18
|
+
# but in reverse order, so that newer formatters kan override older ones.
|
23
19
|
def self.inherited(formatter)
|
24
20
|
super
|
25
21
|
formatters.unshift(formatter)
|
26
22
|
end
|
27
23
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
# Specify your own name for the formatter. By default the name of the class
|
25
|
+
# will be used (without any namespacing), but you can override it yourself
|
26
|
+
# by calling this method.
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# class SomeStrangeName < View::Formatter
|
30
|
+
# as :real_name
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# View.format @foo, :as => :real_name
|
34
|
+
#
|
35
|
+
# @param [Symbol] type The new name of the formatter
|
32
36
|
def self.as(type)
|
33
37
|
@type = type
|
34
38
|
end
|
35
39
|
|
40
|
+
# @return [String] the type of the formatter, either set via +.as+ or
|
41
|
+
# automatically deducted from the class name.
|
42
|
+
#
|
43
|
+
# @see .as
|
36
44
|
def self.type
|
37
45
|
@type || name.split('::').last.underscore
|
38
46
|
end
|
39
47
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
48
|
+
# By default, blank values (nil, empty strings, etc), will override any
|
49
|
+
# formatter you specified. This way empty values are handled globally.
|
50
|
+
#
|
51
|
+
# If you don't want this, you can either turn it off per formatter.
|
52
|
+
# Call this method to turn it off.
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# class IHandleMyOwnBlank < View::Formatter
|
56
|
+
# skip_blank_formatter
|
57
|
+
# # etc...
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# @see View::Blank
|
61
|
+
def self.skip_blank_formatter
|
62
|
+
@skip_blank_formatter = true
|
63
|
+
end
|
64
|
+
|
65
|
+
# If you didn't specify a format instance method inside specific
|
66
|
+
# formatters, this will raise an error.
|
67
|
+
#
|
68
|
+
# @abstract Subclass and override {#format} to implement your own formatter.
|
69
|
+
# @return [String] the formatted value
|
44
70
|
def format
|
45
|
-
if block
|
46
|
-
captured_value
|
47
|
-
else
|
48
|
-
formatted_value
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def to_s
|
53
71
|
msg <<-MSG.squeeze(' ')
|
54
|
-
The only thing a formatter needs to do is implement the #
|
72
|
+
The only thing a formatter needs to do is implement the #format method.
|
55
73
|
If you see this error, you forgot to do that for the #{self.class.type} formatter.
|
56
74
|
MSG
|
57
75
|
raise NotImplementedError.new(msg)
|
58
76
|
end
|
59
77
|
|
78
|
+
# The "safe" options that you can toss around to helper methods.
|
79
|
+
#
|
80
|
+
# You can specify which methods are "safe" by white listing or black
|
81
|
+
# listing. White listing takes precedence over black listing.
|
82
|
+
#
|
83
|
+
# To access options that are filtered out, use +all_options+.
|
84
|
+
# It's generally a good idea to black list options that you use inside your
|
85
|
+
# formatter.
|
86
|
+
#
|
87
|
+
# The options +:as+ and +:block_arguments+ are black listed by default.
|
88
|
+
#
|
89
|
+
# @example White listing:
|
90
|
+
#
|
91
|
+
# class Sentence < View::Formatter
|
92
|
+
# self.allowed_options = [ :words_connector, :last_word_connector ]
|
93
|
+
#
|
94
|
+
# def format
|
95
|
+
# value.to_sentence(options)
|
96
|
+
# end
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# @example Black listing:
|
100
|
+
#
|
101
|
+
# class Link < View::Formatter
|
102
|
+
# self.reserved_options = [ :to ]
|
103
|
+
#
|
104
|
+
# def format
|
105
|
+
# template.link_to(value.to_s, all_options[:to], options)
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# @return [Hash] filtered options
|
110
|
+
# @see #all_options
|
60
111
|
def options
|
61
112
|
default_options.merge(all_options).delete_if do |key, value|
|
62
113
|
option_not_allowed?(key)
|
63
114
|
end
|
64
115
|
end
|
65
116
|
|
117
|
+
# This calls the format action. You can override it to do something with
|
118
|
+
# the formatted value. This doesn't (and shouldn't) do any formatting
|
119
|
+
# itself.
|
120
|
+
#
|
121
|
+
# @see #format
|
122
|
+
def to_s
|
123
|
+
format
|
124
|
+
end
|
125
|
+
|
126
|
+
# @return All options, unfiltered.
|
127
|
+
# @see #options
|
128
|
+
def all_options
|
129
|
+
@options
|
130
|
+
end
|
131
|
+
|
66
132
|
private
|
67
133
|
|
134
|
+
def self.skip_blank_formatter?
|
135
|
+
@skip_blank_formatter
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.format(*args, &block)
|
139
|
+
new(*args, &block).send(:format!)
|
140
|
+
end
|
141
|
+
|
142
|
+
def format!
|
143
|
+
if block
|
144
|
+
captured_value
|
145
|
+
else
|
146
|
+
formatted_value
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.formatters
|
151
|
+
View.formatters ||= []
|
152
|
+
end
|
153
|
+
|
154
|
+
def initialize(value, options = {}, template = nil, &block)
|
155
|
+
@value = value
|
156
|
+
@options = options
|
157
|
+
@template = template
|
158
|
+
@block = block
|
159
|
+
end
|
160
|
+
|
68
161
|
def template_can_capture?
|
69
162
|
template && template.respond_to?(:capture)
|
70
163
|
end
|
@@ -78,31 +171,29 @@ module View
|
|
78
171
|
end
|
79
172
|
|
80
173
|
def captured_value_by_template
|
81
|
-
template.capture(
|
174
|
+
template.capture(*block_arguments, &block)
|
82
175
|
end
|
83
176
|
|
84
177
|
def captured_return_value
|
85
|
-
block.call(
|
178
|
+
block.call(*block_arguments)
|
86
179
|
end
|
87
180
|
|
88
181
|
def formatted_value
|
182
|
+
formatter_not_found unless formatter
|
89
183
|
formatter.new(value, all_options, template, &block).to_s
|
90
184
|
end
|
91
185
|
|
92
186
|
def formatter
|
93
|
-
|
187
|
+
blank_formatter || find_formatter
|
94
188
|
end
|
95
189
|
|
96
190
|
def formatter_not_found
|
191
|
+
formatter_names = self.class.formatters.map { |formatter| formatter.type.to_s }
|
97
192
|
raise "Couldn't find the #{as} formatter. Got: #{formatter_names.join(', ')}"
|
98
193
|
end
|
99
194
|
|
100
|
-
def formatter_names
|
101
|
-
self.class.formatters.map { |formatter| formatter.type.to_s }
|
102
|
-
end
|
103
|
-
|
104
195
|
def find_formatter
|
105
|
-
self.class.formatters.find { |formatter| formatter.type.to_s == as.to_s }
|
196
|
+
@formatter ||= self.class.formatters.find { |formatter| formatter.type.to_s == as.to_s }
|
106
197
|
end
|
107
198
|
|
108
199
|
def option_not_allowed?(key)
|
@@ -114,15 +205,15 @@ module View
|
|
114
205
|
end
|
115
206
|
|
116
207
|
def block_arguments
|
117
|
-
all_options[:block_arguments] || []
|
208
|
+
all_options[:block_arguments] || [ formatted_value ]
|
118
209
|
end
|
119
210
|
|
120
211
|
def as
|
121
212
|
all_options[:as] || View.default_formatter
|
122
213
|
end
|
123
214
|
|
124
|
-
def
|
125
|
-
|
215
|
+
def blank_formatter
|
216
|
+
Blank if !find_formatter.skip_blank_formatter? && value.blank?
|
126
217
|
end
|
127
218
|
|
128
219
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module View
|
2
|
+
|
3
|
+
# @abstract Subclass this for html safe lists with formatted each support.
|
4
|
+
class Array < Formatter
|
5
|
+
|
6
|
+
def to_s
|
7
|
+
if all_safe?
|
8
|
+
super.html_safe
|
9
|
+
else
|
10
|
+
super
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def all_safe?
|
15
|
+
formatted_values.all? do |element|
|
16
|
+
element.respond_to?(:html_safe?) && element.html_safe?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def formatted_values
|
21
|
+
@formatted_values ||= value.map do |element|
|
22
|
+
View.format(element, each, template, &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def each
|
27
|
+
all_options[:each] || { :as => View.default_formatter }
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/lib/view/formatters/auto.rb
CHANGED
@@ -1,47 +1,70 @@
|
|
1
1
|
module View
|
2
2
|
|
3
|
+
# The auto formatter tries to figure out what other formatter should be the
|
4
|
+
# most appropriate to use and delegates the formatting to that formatter.
|
5
|
+
#
|
6
|
+
# This is fully configurable too. See Auto.add
|
3
7
|
class Auto < Formatter
|
4
8
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
skip_blank_formatter
|
10
|
+
|
11
|
+
# Adds behavior to check which view should automatically be used.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
#
|
15
|
+
# View::Auto.add :boolean do
|
16
|
+
# value == true || value == false
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# @param [Symbol] formatter_name The name of the formatter
|
20
|
+
#
|
21
|
+
# @yield The block is eval'd inside the formatter, so you can use the
|
22
|
+
# instance methods that are available for every formatters, like +value+
|
23
|
+
# and +options+.
|
24
|
+
#
|
25
|
+
# @yieldreturn [true, false] The first block to evaluate to true will
|
26
|
+
# determine the formatter. New blocks are checked first.
|
27
|
+
def self.add(formatter_name, &block)
|
28
|
+
auto_formatters.unshift(:formatter => formatter_name, :block => block)
|
11
29
|
end
|
12
30
|
|
13
|
-
|
14
|
-
|
31
|
+
private
|
32
|
+
|
33
|
+
def format
|
34
|
+
format!
|
15
35
|
end
|
16
36
|
|
17
|
-
def
|
18
|
-
|
37
|
+
def self.auto_formatters
|
38
|
+
@auto_formatters ||= []
|
19
39
|
end
|
20
40
|
|
21
|
-
def
|
22
|
-
|
41
|
+
def as
|
42
|
+
as = self.class.auto_formatters.find { |auto| instance_eval(&auto[:block]) }
|
43
|
+
as ? as[:formatter] : :guess
|
23
44
|
end
|
24
45
|
|
25
|
-
|
26
|
-
value.
|
46
|
+
add :datetime do
|
47
|
+
value.respond_to?(:strftime)
|
27
48
|
end
|
28
49
|
|
29
|
-
|
30
|
-
value.respond_to?(
|
50
|
+
add :file_link do
|
51
|
+
View.file_methods.any? { |method| value.respond_to?(method) }
|
31
52
|
end
|
32
53
|
|
33
|
-
|
34
|
-
|
54
|
+
add View.default_list_formatter do
|
55
|
+
value.respond_to?(:each)
|
35
56
|
end
|
36
57
|
|
37
|
-
|
38
|
-
|
58
|
+
add :link do
|
59
|
+
all_options.has_key?(:to)
|
39
60
|
end
|
40
61
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
62
|
+
add :blank do
|
63
|
+
value.blank?
|
64
|
+
end
|
65
|
+
|
66
|
+
add :boolean do
|
67
|
+
value == true || value == false
|
45
68
|
end
|
46
69
|
|
47
70
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module View
|
2
|
+
|
3
|
+
# The default formatter for blank objects, like nil, empty strings and empty
|
4
|
+
# arrays. It will display an empty string or something else, which you can
|
5
|
+
# configure with I18n.
|
6
|
+
#
|
7
|
+
# @example config/locales/en.yml
|
8
|
+
# en:
|
9
|
+
# view:
|
10
|
+
# blank: "nothing"
|
11
|
+
#
|
12
|
+
class Blank < Formatter
|
13
|
+
|
14
|
+
def format
|
15
|
+
::I18n.t(:blank, :scope => :view, :default => "").html_safe
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -1,8 +1,24 @@
|
|
1
1
|
module View
|
2
2
|
|
3
|
+
# The default formatter for booleans.
|
4
|
+
#
|
5
|
+
# It will display "Yes" or "No".
|
6
|
+
#
|
7
|
+
# You can configure it with I18n. When writing 'true' and 'false' as keys in
|
8
|
+
# yaml, please don't forget the quotes.
|
9
|
+
#
|
10
|
+
# @example config/locales/en.yml
|
11
|
+
# en:
|
12
|
+
# view:
|
13
|
+
# booleans:
|
14
|
+
# 'true': Yup
|
15
|
+
# 'false': Nope
|
16
|
+
#
|
3
17
|
class Boolean < Formatter
|
4
18
|
|
5
|
-
|
19
|
+
skip_blank_formatter
|
20
|
+
|
21
|
+
def format
|
6
22
|
::I18n.t(boolean_value.to_s, :scope => [:view, :booleans], :default => default)
|
7
23
|
end
|
8
24
|
|
data/lib/view/formatters/date.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
module View
|
2
|
+
|
3
|
+
# This formatter is the fallback formatter for auto. It figures out which
|
4
|
+
# method will be called to get a proper version to render.
|
5
|
+
#
|
6
|
+
# @see View.guessing_methods
|
7
|
+
class Guess < Formatter
|
8
|
+
|
9
|
+
def format
|
10
|
+
View.guessing_methods.each do |method|
|
11
|
+
return value.send(method) if value.respond_to?(method)
|
12
|
+
end
|
13
|
+
value
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/lib/view/formatters/link.rb
CHANGED
data/lib/view/formatters/self.rb
CHANGED
@@ -1,31 +1,26 @@
|
|
1
1
|
module View
|
2
2
|
|
3
|
-
|
3
|
+
# This formatter is for arrays and stuff into a sentence.
|
4
|
+
#
|
5
|
+
# You can pass the options for sentence and, like any other array formatter,
|
6
|
+
# you can pass an each option, that contains the options for every element in
|
7
|
+
# the array.
|
8
|
+
#
|
9
|
+
# If you don't pass any options in each, it will autoformat every element.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# View.format @dates, :as => :sentence,
|
14
|
+
# :each => { :as => :date, :format => :short }
|
15
|
+
#
|
16
|
+
# @see View::Array
|
17
|
+
# @see http://rubydoc.info/docs/rails/3.0.0/Array:to_sentence
|
18
|
+
class Sentence < Array
|
4
19
|
|
5
20
|
self.allowed_options = [ :words_connector, :two_words_connector, :last_word_connector ]
|
6
21
|
|
7
|
-
def
|
8
|
-
|
9
|
-
sentence.html_safe
|
10
|
-
else
|
11
|
-
sentence
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def all_safe?
|
16
|
-
formatted_values.all? { |element| element.html_safe? }
|
17
|
-
end
|
18
|
-
|
19
|
-
def formatted_values
|
20
|
-
value.map { |element| View.to_s(element, each, template, &block) }
|
21
|
-
end
|
22
|
-
|
23
|
-
def sentence
|
24
|
-
formatted_values.to_sentence if value.present?
|
25
|
-
end
|
26
|
-
|
27
|
-
def each
|
28
|
-
all_options[:each] || { :as => View.default_formatter }
|
22
|
+
def format
|
23
|
+
formatted_values.to_sentence(options)
|
29
24
|
end
|
30
25
|
|
31
26
|
end
|
data/lib/view/formatters/size.rb
CHANGED
data/lib/view/helper.rb
CHANGED
data/lib/view/version.rb
CHANGED
data/lib/view.rb
CHANGED
@@ -4,26 +4,94 @@ module View
|
|
4
4
|
autoload :Helper, 'view/helper'
|
5
5
|
autoload :VERSION, 'view/version'
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
class << self
|
8
|
+
# Used by the guess filter, these are the methods used to format an object.
|
9
|
+
# It will use the first method that the object responds to.
|
10
|
+
attr_accessor :guessing_methods
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
# To determine if something is an uploaded image, it checks
|
13
|
+
# to see whether it responds to one of these methods.
|
14
|
+
attr_accessor :file_methods
|
12
15
|
|
13
|
-
|
14
|
-
|
16
|
+
# To show an image, it will use one of these methods to get the src
|
17
|
+
# attribute.
|
18
|
+
attr_accessor :path_methods
|
15
19
|
|
16
|
-
|
17
|
-
|
20
|
+
# You can set a default argument for rendering images, like the style or size
|
21
|
+
# of the image. It will be passed to one of the path_methods.
|
22
|
+
attr_accessor :path_arguments
|
18
23
|
|
19
|
-
|
20
|
-
|
24
|
+
# Which formatter will be used by default. The default is auto, which does
|
25
|
+
# all sorts of interesting stuff to see what to do.
|
26
|
+
attr_accessor :default_formatter
|
21
27
|
|
22
|
-
|
28
|
+
# The auto formatter will choose this formatter by default when your value is
|
29
|
+
# an array (or really, something that responds to +each+).
|
30
|
+
attr_accessor :default_list_formatter
|
23
31
|
|
32
|
+
# Holds a list of formatters. It will be filled automatically by inheriting
|
33
|
+
# from View::Formatter.
|
34
|
+
attr_accessor :formatters
|
24
35
|
|
25
|
-
|
26
|
-
|
36
|
+
# Shorthand for configuring this gem.
|
37
|
+
#
|
38
|
+
# @example In +config/initializers/view.rb+
|
39
|
+
#
|
40
|
+
# View.configure do |config|
|
41
|
+
# config.default_formatter = :self
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# @yield [config] The View module
|
45
|
+
def configure
|
46
|
+
yield self
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
self.guessing_methods = %w|to_label display_name full_name name title
|
52
|
+
username login value to_s|
|
53
|
+
self.file_methods = %w|mounted_as file? public_filename|
|
54
|
+
self.path_methods = %w|mounted_as url public_filename|
|
55
|
+
self.path_arguments = []
|
56
|
+
self.default_formatter = :auto
|
57
|
+
self.default_list_formatter = :sentence
|
58
|
+
|
59
|
+
|
60
|
+
# This is the main method to use this gem. Any formatting from outside this
|
61
|
+
# gem should be done through this method (notwithstanding custom formatters).
|
62
|
+
#
|
63
|
+
# In every day usage you will access it through the +view+ helper method,
|
64
|
+
# because most formatters require a view to render links or images. Any
|
65
|
+
# helper method should also point to this method.
|
66
|
+
#
|
67
|
+
# @see View::Helper#view
|
68
|
+
#
|
69
|
+
# @example Rendering a link
|
70
|
+
# module PostsHelper
|
71
|
+
# def link_to_post
|
72
|
+
# View.format @post, :as => :link, self
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# @param [Object] value the object to be shown
|
77
|
+
# @param [Hash] options Any extra options
|
78
|
+
#
|
79
|
+
# @option options [Symbol] :as (:auto) The name of the formatter
|
80
|
+
# @option options [Array] :block_arguments (nil) Overrides the arguments passed to
|
81
|
+
# the block of this method.
|
82
|
+
#
|
83
|
+
# @param [ActionView::Template] Template the view instance on which to call
|
84
|
+
# helper methods like +link_to+ and +image_tag+.
|
85
|
+
# You need this for many formatters.
|
86
|
+
#
|
87
|
+
# @yield [formatted_string] The block will be captured (using the template if
|
88
|
+
# possible) to alter the formatted string that would otherwise be returned.
|
89
|
+
# Consider it as a final modifier after the view formatter has done its
|
90
|
+
# work.
|
91
|
+
#
|
92
|
+
# @return [String] the object formatted to a string
|
93
|
+
def self.format(value, options = {}, template = nil, &block)
|
94
|
+
Formatter.format(value, options, template, &block)
|
27
95
|
end
|
28
96
|
|
29
97
|
end
|
@@ -2,24 +2,21 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe "Auto formatter" do
|
4
4
|
|
5
|
-
it "
|
6
|
-
|
7
|
-
View.to_s(object).should == "some label"
|
5
|
+
it "formats like a boolean automatically" do
|
6
|
+
View.format(true).should == "Yes"
|
8
7
|
end
|
9
8
|
|
10
|
-
it "
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
View.
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
object = Struct.new(:login).new("loginname")
|
22
|
-
View.to_s(object).should == "loginname"
|
9
|
+
it "is configurable" do
|
10
|
+
foo = Class.new(View::Formatter) do
|
11
|
+
as :foo
|
12
|
+
def format
|
13
|
+
"!!!#{value}!!!"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
View::Auto.add :foo do
|
17
|
+
value == "foobar"
|
18
|
+
end
|
19
|
+
View.format("foobar").should == "!!!foobar!!!"
|
23
20
|
end
|
24
21
|
|
25
22
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Blank formatter" do
|
4
|
+
|
5
|
+
it "formats nil" do
|
6
|
+
View.format(nil).should == ""
|
7
|
+
end
|
8
|
+
|
9
|
+
it "formats empty strings" do
|
10
|
+
View.format(" ").should == ""
|
11
|
+
end
|
12
|
+
|
13
|
+
it "formats empty arrays" do
|
14
|
+
View.format([]).should == ""
|
15
|
+
end
|
16
|
+
|
17
|
+
it "uses i18n for nil" do
|
18
|
+
with_translation :view => { :blank => "nothing" } do
|
19
|
+
View.format(nil).should == "nothing"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -3,24 +3,24 @@ require 'spec_helper'
|
|
3
3
|
describe "Boolean formatter" do
|
4
4
|
|
5
5
|
it "formats true" do
|
6
|
-
View.
|
6
|
+
View.format(true).should == "Yes"
|
7
7
|
end
|
8
8
|
|
9
9
|
it "formats false" do
|
10
|
-
View.
|
10
|
+
View.format(false).should == "No"
|
11
11
|
end
|
12
12
|
|
13
13
|
it "formats boolean values" do
|
14
|
-
View.
|
15
|
-
View.
|
14
|
+
View.format("h", :as => :boolean).should == "Yes"
|
15
|
+
View.format(nil, :as => :boolean).should == "No"
|
16
16
|
end
|
17
17
|
|
18
18
|
it "localizes booleans" do
|
19
19
|
with_translation :view => { :booleans => { :true => "yup" } } do
|
20
|
-
View.
|
20
|
+
View.format(true).should == "yup"
|
21
21
|
end
|
22
22
|
with_translation :view => { :booleans => { :false => "nope" } } do
|
23
|
-
View.
|
23
|
+
View.format(false).should == "nope"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -5,18 +5,18 @@ describe "Date formatter" do
|
|
5
5
|
it "localizes dates" do
|
6
6
|
date = Date.new(2010, 10, 11)
|
7
7
|
with_translation :date => { :formats => { :foo => "%A" }, :day_names => [ "zondag", "maandag" ] } do
|
8
|
-
View.
|
8
|
+
View.format(date, :format => :foo).should == "maandag"
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
it "formats dates" do
|
13
13
|
date = Date.new(2010, 10, 10)
|
14
|
-
View.
|
14
|
+
View.format(date).should == "2010-10-10"
|
15
15
|
end
|
16
16
|
|
17
17
|
it "forces datetimes to date" do
|
18
18
|
time = Time.new(2010, 10, 10, 8, 45, 30, '+01:00')
|
19
|
-
View.
|
19
|
+
View.format(time, :as => :date).should == "2010-10-10"
|
20
20
|
end
|
21
21
|
|
22
22
|
end
|
@@ -4,13 +4,13 @@ describe "Datetime formatter" do
|
|
4
4
|
|
5
5
|
it "formats" do
|
6
6
|
time = Time.new(2010, 10, 10, 8, 45, 30, '+01:00')
|
7
|
-
View.
|
7
|
+
View.format(time).should == "Sun, 10 Oct 2010 08:45:30 +0100"
|
8
8
|
end
|
9
9
|
|
10
10
|
it "localizes" do
|
11
11
|
time = Time.new(2010, 10, 10, 8, 45, 30, '+01:00')
|
12
12
|
with_translation :time => { :formats => { :short => "%d-%m-%Y %H:%M" } } do
|
13
|
-
View.
|
13
|
+
View.format(time, :format => :short).should == "10-10-2010 08:45"
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Guess formatter" do
|
4
|
+
|
5
|
+
it "guesses the to_label" do
|
6
|
+
object = Struct.new(:to_label).new("some label")
|
7
|
+
View.format(object).should == "some label"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "guesses to_s" do
|
11
|
+
object = Struct.new(:to_s).new("string")
|
12
|
+
View.format(object).should == "string"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "guesses a name" do
|
16
|
+
object = Struct.new(:name).new("my name")
|
17
|
+
View.format(object).should == "my name"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "guesses a login" do
|
21
|
+
object = Struct.new(:login).new("loginname")
|
22
|
+
View.format(object).should == "loginname"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -4,7 +4,23 @@ describe "Sentence formatter" do
|
|
4
4
|
|
5
5
|
it "constructs a sentence" do
|
6
6
|
object = [ 1, 2, 3 ]
|
7
|
-
View.
|
7
|
+
View.format(object).should == "1, 2, and 3"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "has options for each element" do
|
11
|
+
object = [ Date.today ]
|
12
|
+
subject = View.format(object, :each => { :format => :short })
|
13
|
+
subject.should == I18n.l(Date.today, :format => :short)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "makes the sentence html safe if all elements are" do
|
17
|
+
object = [ "safe".html_safe ]
|
18
|
+
View.format(object).should be_html_safe
|
19
|
+
end
|
20
|
+
|
21
|
+
it "doesn't make the sentence html safe if not all elements are safe" do
|
22
|
+
object = [ "safe".html_safe, "unsafe" ]
|
23
|
+
View.format(object).should_not be_html_safe
|
8
24
|
end
|
9
25
|
|
10
26
|
end
|
metadata
CHANGED
@@ -7,8 +7,8 @@ version: !ruby/object:Gem::Version
|
|
7
7
|
- 0
|
8
8
|
- 0
|
9
9
|
- alpha
|
10
|
-
-
|
11
|
-
version: 1.0.0.alpha.
|
10
|
+
- 2
|
11
|
+
version: 1.0.0.alpha.2
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Iain Hecker
|
@@ -16,10 +16,24 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-10-
|
19
|
+
date: 2010-10-10 00:00:00 +02:00
|
20
20
|
default_executable:
|
21
|
-
dependencies:
|
22
|
-
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: rails
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
version: 3.0.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
23
37
|
description: A very extensible way of viewing objects, easily integrated with other gems
|
24
38
|
email:
|
25
39
|
- iain@iain.nl
|
@@ -31,18 +45,20 @@ extra_rdoc_files:
|
|
31
45
|
- README.rdoc
|
32
46
|
files:
|
33
47
|
- lib/view/formatter.rb
|
48
|
+
- lib/view/formatters/array.rb
|
34
49
|
- lib/view/formatters/auto.rb
|
50
|
+
- lib/view/formatters/blank.rb
|
35
51
|
- lib/view/formatters/boolean.rb
|
36
52
|
- lib/view/formatters/currency.rb
|
37
53
|
- lib/view/formatters/date.rb
|
38
54
|
- lib/view/formatters/datetime.rb
|
39
55
|
- lib/view/formatters/delimited.rb
|
40
56
|
- lib/view/formatters/file_link.rb
|
57
|
+
- lib/view/formatters/guess.rb
|
41
58
|
- lib/view/formatters/html_safe.rb
|
42
59
|
- lib/view/formatters/human.rb
|
43
60
|
- lib/view/formatters/image.rb
|
44
61
|
- lib/view/formatters/link.rb
|
45
|
-
- lib/view/formatters/nil.rb
|
46
62
|
- lib/view/formatters/percentage.rb
|
47
63
|
- lib/view/formatters/phone.rb
|
48
64
|
- lib/view/formatters/precision.rb
|
@@ -56,15 +72,16 @@ files:
|
|
56
72
|
- init.rb
|
57
73
|
- README.rdoc
|
58
74
|
- spec/spec_helper.rb
|
75
|
+
- spec/view/formatter_spec.rb
|
59
76
|
- spec/view/formatters/auto_spec.rb
|
77
|
+
- spec/view/formatters/blank_spec.rb
|
60
78
|
- spec/view/formatters/boolean_spec.rb
|
61
79
|
- spec/view/formatters/date_spec.rb
|
62
80
|
- spec/view/formatters/datetime_spec.rb
|
63
|
-
- spec/view/formatters/
|
81
|
+
- spec/view/formatters/guess_spec.rb
|
64
82
|
- spec/view/formatters/self_spec.rb
|
65
83
|
- spec/view/formatters/sentence_spec.rb
|
66
84
|
- spec/view/helper_spec.rb
|
67
|
-
- spec/view/view_spec.rb
|
68
85
|
has_rdoc: true
|
69
86
|
homepage: http://github.com/iain/view
|
70
87
|
licenses: []
|
@@ -101,12 +118,13 @@ specification_version: 3
|
|
101
118
|
summary: Displaying objects automatically
|
102
119
|
test_files:
|
103
120
|
- spec/spec_helper.rb
|
121
|
+
- spec/view/formatter_spec.rb
|
104
122
|
- spec/view/formatters/auto_spec.rb
|
123
|
+
- spec/view/formatters/blank_spec.rb
|
105
124
|
- spec/view/formatters/boolean_spec.rb
|
106
125
|
- spec/view/formatters/date_spec.rb
|
107
126
|
- spec/view/formatters/datetime_spec.rb
|
108
|
-
- spec/view/formatters/
|
127
|
+
- spec/view/formatters/guess_spec.rb
|
109
128
|
- spec/view/formatters/self_spec.rb
|
110
129
|
- spec/view/formatters/sentence_spec.rb
|
111
130
|
- spec/view/helper_spec.rb
|
112
|
-
- spec/view/view_spec.rb
|
data/lib/view/formatters/nil.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "Nil formatter" do
|
4
|
-
|
5
|
-
it "formats nil" do
|
6
|
-
View.to_s(nil).should == ""
|
7
|
-
end
|
8
|
-
|
9
|
-
it "uses i18n for nil" do
|
10
|
-
with_translation :view => { :nil => "nothing" } do
|
11
|
-
View.to_s(nil).should == "nothing"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
data/spec/view/view_spec.rb
DELETED