show_for 0.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.rdoc +150 -0
- data/generators/show_for_install/USAGE +3 -0
- data/generators/show_for_install/show_for_install_generator.rb +19 -0
- data/generators/show_for_install/templates/show_for.rb +30 -0
- data/init.rb +1 -0
- data/lib/show_for/builder.rb +98 -0
- data/lib/show_for/content.rb +49 -0
- data/lib/show_for/helper.rb +25 -0
- data/lib/show_for/label.rb +23 -0
- data/lib/show_for/locale/en.yml +4 -0
- data/lib/show_for/version.rb +3 -0
- data/lib/show_for.rb +42 -0
- data/test/builder_test.rb +305 -0
- data/test/helper_test.rb +31 -0
- data/test/support/misc_helpers.rb +29 -0
- data/test/support/models.rb +45 -0
- data/test/test_helper.rb +37 -0
- metadata +70 -0
data/README.rdoc
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
== ShowFor
|
2
|
+
|
3
|
+
ShowFor allows you to quickly show a model information with I18n features.
|
4
|
+
|
5
|
+
<% show_for @user do |u| %>
|
6
|
+
<%= u.attribute :name %>
|
7
|
+
<%= u.attribute :confirmed? %>
|
8
|
+
<%= u.attribute :created_at, :format => :short %>
|
9
|
+
<%= u.attribute :last_sign_in_at, :if_blank => "User did not access yet"
|
10
|
+
:wrapper_html => { :id => "sign_in_timestamp" } %>
|
11
|
+
|
12
|
+
<% u.attribute :photo do
|
13
|
+
<%= image_url(@user.photo_url) %>
|
14
|
+
end %>
|
15
|
+
|
16
|
+
<%= u.association :company %>
|
17
|
+
<%= u.association :tags, :to_sentence => true %>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
== Installation
|
21
|
+
|
22
|
+
Install the gem:
|
23
|
+
|
24
|
+
sudo gem install show_for
|
25
|
+
|
26
|
+
Configure simple_form gem inside your app:
|
27
|
+
|
28
|
+
config.gem 'show_for'
|
29
|
+
|
30
|
+
Run the generator:
|
31
|
+
|
32
|
+
ruby script/generate show_for_install
|
33
|
+
|
34
|
+
And you're ready to go.
|
35
|
+
|
36
|
+
== Usage
|
37
|
+
|
38
|
+
ShowFor allows you to quickly show a model information with I18n features.
|
39
|
+
|
40
|
+
<% show_for @admin do |a| %>
|
41
|
+
<%= a.attribute :name %>
|
42
|
+
<%= a.attribute :confirmed? %>
|
43
|
+
<%= a.attribute :created_at, :format => :short %>
|
44
|
+
<%= a.attribute :last_sign_in_at, :if_blank => "Administrator did not access yet"
|
45
|
+
:wrapper_html => { :id => "sign_in_timestamp" } %>
|
46
|
+
|
47
|
+
<% a.attribute :photo do %>
|
48
|
+
<%= image_url(@admin.photo_url) %>
|
49
|
+
<% end %>
|
50
|
+
<% end %>
|
51
|
+
|
52
|
+
Will generate something like:
|
53
|
+
|
54
|
+
<div id="admin_1" class="show_for admin">
|
55
|
+
<p class="wrapper admin_name">
|
56
|
+
<b class="label">Name</b><br />
|
57
|
+
José Valim
|
58
|
+
</p>
|
59
|
+
<p class="wrapper admin_confirmed">
|
60
|
+
<b class="label">Confirmed?</b><br />
|
61
|
+
Yes
|
62
|
+
</p>
|
63
|
+
<p class="wrapper admin_created_at">
|
64
|
+
<b class="label">Created at</b><br />
|
65
|
+
13/12/2009 - 19h17
|
66
|
+
</p>
|
67
|
+
<p id="sign_in_timestamp" class="wrapper admin_last_sign_in_at">
|
68
|
+
<b class="label">Last sign in at</b><br />
|
69
|
+
Administrator did not access yet
|
70
|
+
</p>
|
71
|
+
<p class="wrapper admin_photo">
|
72
|
+
<b class="label">Photo</b><br />
|
73
|
+
<img src="path/to/photo" />
|
74
|
+
</p>
|
75
|
+
</div>
|
76
|
+
|
77
|
+
== Value lookup
|
78
|
+
|
79
|
+
To show the proper value, before retrieving the attribute value, show_for first looks if a
|
80
|
+
block without argument was given, otherwise checks if a :"human_#{attribute}" method is defined
|
81
|
+
and, if not, only then retrieve the attribute.
|
82
|
+
|
83
|
+
== Options
|
84
|
+
|
85
|
+
show_for handles a series of options. Those are:
|
86
|
+
|
87
|
+
* :escape * - When the attribute should be escaped. True by default.
|
88
|
+
|
89
|
+
* :format * - Sent to I18n.localize when the attribute is a date/time object.
|
90
|
+
|
91
|
+
* :if_blank * - An object to be used if the value is blank. Not escaped as well.
|
92
|
+
|
93
|
+
Besides, all containers (:label, :content and :wrapper) can have their html
|
94
|
+
options configured through the :label_html, :content_html and :wrapper_html
|
95
|
+
options. Containers can have their tags configured on demand as well through
|
96
|
+
:label_tag, :content_tag and :wrapper_tag options.
|
97
|
+
|
98
|
+
== Label
|
99
|
+
|
100
|
+
show_for also exposes the label method. In case you want to use the default
|
101
|
+
human_attribute_name lookup and the default wrapping:
|
102
|
+
|
103
|
+
a.label :name #=> <b class="label">Name</b>
|
104
|
+
a.label "Name", :id => "my_name" #=> <b class="label" id="my_name">Name</b>
|
105
|
+
|
106
|
+
== Associations
|
107
|
+
|
108
|
+
show_for also supports associations.
|
109
|
+
|
110
|
+
<% show_for @artwork do |a| %>
|
111
|
+
<%= a.association :artist %>
|
112
|
+
<%= a.association :artist, :method => :name_with_title %>
|
113
|
+
|
114
|
+
<%= a.association :tags %>
|
115
|
+
<%= a.association :tags, :to_sentence => true %>
|
116
|
+
<% a.association :tags do
|
117
|
+
@artwork.tags.map(&:name).to_sentence
|
118
|
+
end %>
|
119
|
+
|
120
|
+
<% a.association :fans, :collection_tag => :ol do |fan| %>
|
121
|
+
<li><%= link_to fan.name, fan %></li>
|
122
|
+
<% end %>
|
123
|
+
<% end %>
|
124
|
+
|
125
|
+
The first is a has_one or belongs_to association, which works like an attribute
|
126
|
+
to show_for, except it will retrieve the artist association and try to find a
|
127
|
+
proper method from ShowFor.association_methods to be used. You can pass
|
128
|
+
the option :method to tell (and not guess) which method from the association
|
129
|
+
to use.
|
130
|
+
|
131
|
+
:tags is a has_and_belongs_to_many association which will return a collection.
|
132
|
+
show_for can handle collections by default by wrapping them in list (<ul> with
|
133
|
+
each item wrapped by an <li>). However, it also allows you to give :to_sentence
|
134
|
+
or :join it you want to render them inline.
|
135
|
+
|
136
|
+
You can also pass a block which expects an argument to association. In such cases,
|
137
|
+
a wrapper for the collection is still created and the block just iterates over the
|
138
|
+
collection objects.
|
139
|
+
|
140
|
+
== Contributors
|
141
|
+
|
142
|
+
* José Valim (http://github.com/josevalim)
|
143
|
+
|
144
|
+
== Bugs and Feedback
|
145
|
+
|
146
|
+
If you discover any bugs or want to drop a line, feel free to create an issue on GitHub.
|
147
|
+
|
148
|
+
http://github.com/plataformatec/show_for/issues
|
149
|
+
|
150
|
+
MIT License. Copyright 2009 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class ShowForInstallGenerator < Rails::Generator::Base
|
2
|
+
|
3
|
+
def manifest
|
4
|
+
record do |m|
|
5
|
+
m.directory 'config/initializers'
|
6
|
+
m.template 'show_for.rb', 'config/initializers/show_for.rb'
|
7
|
+
|
8
|
+
m.directory 'config/locales'
|
9
|
+
m.template locale_file, 'config/locales/show_for.en.yml'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def locale_file
|
16
|
+
@locale_file ||= '../../../lib/show_for/locale/en.yml'
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Use this setup block to configure all options available in ShowFor.
|
2
|
+
ShowFor.setup do |config|
|
3
|
+
# The tag which wraps show_for calls.
|
4
|
+
# config.show_for_tag = :div
|
5
|
+
|
6
|
+
# The tag which wraps each attribute/association call. Default is :p.
|
7
|
+
# config.wrapper_tag = :dl
|
8
|
+
|
9
|
+
# The tag used to wrap each label. Default is :strong.
|
10
|
+
# config.label_tag = :dt
|
11
|
+
|
12
|
+
# The tag used to wrap each content (value). Default is nil.
|
13
|
+
# config.content_tag = :dd
|
14
|
+
|
15
|
+
# The separator between label and content. Default is "<br />".
|
16
|
+
# config.separator = "<br />"
|
17
|
+
|
18
|
+
# The tag used to wrap collections. Default is :ul.
|
19
|
+
# config.collection_tag = :ul
|
20
|
+
|
21
|
+
# The default iterator to be used when invoking a collection/association.
|
22
|
+
# config.default_collection_proc = lambda { |value| "<li>#{value}</li>" }
|
23
|
+
|
24
|
+
# The default format to be used in I18n when localizing a Date/Time.
|
25
|
+
# config.i18n_format = :default
|
26
|
+
|
27
|
+
# Whenever a association is given, the first method in association_methods
|
28
|
+
# in which the association responds to is used to retrieve the association labels.
|
29
|
+
# config.association_methods = [ :name, :title, :to_s ]
|
30
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'show_for'
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'show_for/content'
|
2
|
+
require 'show_for/label'
|
3
|
+
|
4
|
+
module ShowFor
|
5
|
+
class Builder
|
6
|
+
include ShowFor::Content
|
7
|
+
include ShowFor::Label
|
8
|
+
|
9
|
+
attr_reader :object, :template
|
10
|
+
|
11
|
+
def initialize(object, template)
|
12
|
+
@object, @template = object, template
|
13
|
+
end
|
14
|
+
|
15
|
+
def attribute(attribute_name, options={}, &block)
|
16
|
+
apply_default_options!(attribute_name, options)
|
17
|
+
collection_block, block = block, nil if collection_block?(block)
|
18
|
+
|
19
|
+
value = if block
|
20
|
+
block
|
21
|
+
elsif @object.respond_to?(:"human_#{attribute_name}")
|
22
|
+
@object.send :"human_#{attribute_name}"
|
23
|
+
else
|
24
|
+
@object.send(attribute_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
wrap_label_and_content(attribute_name, value, options, &collection_block)
|
28
|
+
end
|
29
|
+
|
30
|
+
def association(association_name, options={}, &block)
|
31
|
+
apply_default_options!(association_name, options)
|
32
|
+
|
33
|
+
# If a block with an iterator was given, no need to calculate the labels
|
34
|
+
# since we want the collection to be yielded. Otherwise, calculate the values.
|
35
|
+
value = if collection_block?(block)
|
36
|
+
collection_block = block
|
37
|
+
@object.send(association_name)
|
38
|
+
elsif block
|
39
|
+
block
|
40
|
+
else
|
41
|
+
association = @object.send(association_name)
|
42
|
+
values = retrieve_values_from_association(association, options)
|
43
|
+
|
44
|
+
if options.delete(:to_sentence)
|
45
|
+
values.to_sentence
|
46
|
+
elsif joiner = options.delete(:join)
|
47
|
+
values.join(joiner)
|
48
|
+
else
|
49
|
+
values
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
wrap_label_and_content(association_name, value, options, &collection_block)
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def object_name #:nodoc:
|
59
|
+
@object_name ||= @object.class.name.underscore
|
60
|
+
end
|
61
|
+
|
62
|
+
def wrap_label_and_content(name, value, options, &block) #:nodoc:
|
63
|
+
wrap_with(:wrapper, label(name, options, false) + ShowFor.separator.to_s +
|
64
|
+
content(value, options, false, &block), options, true, value.is_a?(Proc))
|
65
|
+
end
|
66
|
+
|
67
|
+
# Set "#{object_name}_#{attribute_name}" as in the wrapper tag.
|
68
|
+
def apply_default_options!(name, options) #:nodoc:
|
69
|
+
html_class = "#{object_name}_#{name}".gsub(/\W/, '')
|
70
|
+
wrapper_html = options[:wrapper_html] ||= {}
|
71
|
+
wrapper_html[:class] = "#{html_class} #{wrapper_html[:class]}".strip
|
72
|
+
end
|
73
|
+
|
74
|
+
# Gets the default tag set in ShowFor module and apply (if defined)
|
75
|
+
# around the given content. It also check for html_options in @options
|
76
|
+
# hash related to the current type.
|
77
|
+
def wrap_with(type, content, options, safe=false, concat=false) #:nodoc:
|
78
|
+
tag = options.delete(:"#{type}_tag") || ShowFor.send(:"#{type}_tag")
|
79
|
+
|
80
|
+
html = if tag
|
81
|
+
html_options = options.delete(:"#{type}_html") || {}
|
82
|
+
html_options[:class] = "#{type} #{html_options[:class]}".strip
|
83
|
+
@template.content_tag(tag, content, html_options)
|
84
|
+
else
|
85
|
+
content
|
86
|
+
end
|
87
|
+
|
88
|
+
html.html_safe! if safe && html.respond_to?(:html_safe!)
|
89
|
+
concat ? @template.concat(html) : html
|
90
|
+
end
|
91
|
+
|
92
|
+
def retrieve_values_from_association(association, options) #:nodoc:
|
93
|
+
sample = association.is_a?(Array) ? association.first : association
|
94
|
+
method = options[:method] || ShowFor.association_methods.find { |m| sample.respond_to?(m) }
|
95
|
+
association.is_a?(Array) ? association.map(&method) : association.try(method)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module ShowFor
|
2
|
+
module Content
|
3
|
+
def content(value, options={}, apply_options=true, &block)
|
4
|
+
value = options.delete(:if_blank) if value.blank? && value != false
|
5
|
+
|
6
|
+
content = case value
|
7
|
+
when Date, Time, DateTime
|
8
|
+
I18n.l value, :format => options.delete(:format) || ShowFor.i18n_format
|
9
|
+
when TrueClass
|
10
|
+
I18n.t :"show_for.yes", :default => "Yes"
|
11
|
+
when FalseClass
|
12
|
+
I18n.t :"show_for.no", :default => "No"
|
13
|
+
when Array, Hash
|
14
|
+
options[:escape] = false
|
15
|
+
collection_handler(value, options, &block)
|
16
|
+
when Proc
|
17
|
+
options[:escape] = false
|
18
|
+
@template.capture(&value)
|
19
|
+
when NilClass
|
20
|
+
""
|
21
|
+
else
|
22
|
+
value
|
23
|
+
end
|
24
|
+
|
25
|
+
content = @template.send(:h, content) unless options.delete(:escape) == false
|
26
|
+
options[:content_html] = options.dup if apply_options
|
27
|
+
wrap_with(:content, content, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def collection_handler(value, options, &block) #:nodoc:
|
33
|
+
iterator = collection_block?(block) ? block : ShowFor.default_collection_proc
|
34
|
+
response = ""
|
35
|
+
|
36
|
+
value.each do |item|
|
37
|
+
response << template.capture(item, &iterator)
|
38
|
+
end
|
39
|
+
|
40
|
+
wrap_with(:collection, response, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns true if the block is supposed to iterate through a collection,
|
44
|
+
# i.e. it has arity equals to one.
|
45
|
+
def collection_block?(block) #:nodoc:
|
46
|
+
block && block.arity == 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ShowFor
|
2
|
+
module Helper
|
3
|
+
# Creates a div around the object and yields a builder.
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
#
|
7
|
+
# show_for @user do |f|
|
8
|
+
# f.attribute :name
|
9
|
+
# f.attribute :email
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
def show_for(object, html_options={}, &block)
|
13
|
+
tag = html_options.delete(:show_for_tag) || ShowFor.show_for_tag
|
14
|
+
|
15
|
+
html_options[:id] ||= dom_id(object)
|
16
|
+
html_options[:class] = "show_for #{dom_class(object)} #{html_options[:class]}".strip
|
17
|
+
|
18
|
+
concat(content_tag(tag, html_options) do
|
19
|
+
yield ShowFor::Builder.new(object, self)
|
20
|
+
end)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
ActionView::Base.send :include, ShowFor::Helper
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ShowFor
|
2
|
+
module Label
|
3
|
+
def label(text_or_attribute, options={}, apply_options=true)
|
4
|
+
label = if text_or_attribute.is_a?(String)
|
5
|
+
text_or_attribute
|
6
|
+
elsif options.key?(:label)
|
7
|
+
options.delete(:label)
|
8
|
+
else
|
9
|
+
human_attribute_name(text_or_attribute)
|
10
|
+
end
|
11
|
+
|
12
|
+
return "" if label == false
|
13
|
+
options[:label_html] = options.dup if apply_options
|
14
|
+
wrap_with :label, label, options
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def human_attribute_name(attribute) #:nodoc:
|
20
|
+
@object.class.human_attribute_name(attribute.to_s)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/show_for.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'show_for/helper'
|
2
|
+
|
3
|
+
module ShowFor
|
4
|
+
autoload :Builder, 'show_for/builder'
|
5
|
+
|
6
|
+
mattr_accessor :show_for_tag
|
7
|
+
@@show_for_tag = :div
|
8
|
+
|
9
|
+
mattr_accessor :label_tag
|
10
|
+
@@label_tag = :strong
|
11
|
+
|
12
|
+
mattr_accessor :separator
|
13
|
+
@@separator = "<br />"
|
14
|
+
|
15
|
+
mattr_accessor :content_tag
|
16
|
+
@@content_tag = nil
|
17
|
+
|
18
|
+
mattr_accessor :wrapper_tag
|
19
|
+
@@wrapper_tag = :p
|
20
|
+
|
21
|
+
mattr_accessor :collection_tag
|
22
|
+
@@collection_tag = :ul
|
23
|
+
|
24
|
+
mattr_accessor :default_collection_proc
|
25
|
+
@@default_collection_proc = lambda { |value| "<li>#{value}</li>" }
|
26
|
+
|
27
|
+
mattr_accessor :i18n_format
|
28
|
+
@@i18n_format = :default
|
29
|
+
|
30
|
+
mattr_accessor :association_methods
|
31
|
+
@@association_methods = [ :name, :title, :to_s ]
|
32
|
+
|
33
|
+
# Yield self for configuration block:
|
34
|
+
#
|
35
|
+
# ShowFor.setup do |config|
|
36
|
+
# config.i18n_format = :long
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
def self.setup
|
40
|
+
yield self
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,305 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BuilderTest < ActionView::TestCase
|
4
|
+
|
5
|
+
def with_attribute_for(object, attribute, options={}, &block)
|
6
|
+
show_for object do |o|
|
7
|
+
concat(o.attribute(attribute, options, &block))
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def with_association_for(object, association, options={}, &block)
|
12
|
+
show_for object do |o|
|
13
|
+
concat(o.association(association, options, &block))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def with_label_for(object, attribute, options={})
|
18
|
+
show_for object do |o|
|
19
|
+
concat o.label attribute, options
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def with_content_for(object, value, options={})
|
24
|
+
show_for object do |o|
|
25
|
+
concat o.content value, options
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# WRAPPER
|
30
|
+
test "show_for attribute wraps each attribute with a label and content" do
|
31
|
+
with_attribute_for @user, :name
|
32
|
+
assert_select "div.show_for p.user_name.wrapper"
|
33
|
+
assert_select "div.show_for p.wrapper strong.label"
|
34
|
+
assert_select "div.show_for p.wrapper"
|
35
|
+
end
|
36
|
+
|
37
|
+
test "show_for allows wrapper tag to be changed by attribute" do
|
38
|
+
with_attribute_for @user, :name, :wrapper_tag => :span
|
39
|
+
assert_select "div.show_for span.user_name.wrapper"
|
40
|
+
end
|
41
|
+
|
42
|
+
test "show_for allows wrapper html to be configured by attribute" do
|
43
|
+
with_attribute_for @user, :name, :wrapper_html => { :id => "thewrapper", :class => "special" }
|
44
|
+
assert_select "div.show_for p#thewrapper.user_name.wrapper.special"
|
45
|
+
end
|
46
|
+
|
47
|
+
# SEPARATOR
|
48
|
+
test "show_for uses a separator if requested" do
|
49
|
+
with_attribute_for @user, :name
|
50
|
+
assert_select "div.show_for p.wrapper br"
|
51
|
+
end
|
52
|
+
|
53
|
+
test "show_for does not blow if a separator is not set" do
|
54
|
+
swap ShowFor, :separator => nil do
|
55
|
+
with_attribute_for @user, :name
|
56
|
+
assert_select "div.show_for p.wrapper"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# LABEL
|
61
|
+
test "show_for shows a label using the humanized attribute name from model" do
|
62
|
+
with_attribute_for @user, :name
|
63
|
+
assert_select "div.show_for p.wrapper strong.label", "Super User Name!"
|
64
|
+
end
|
65
|
+
|
66
|
+
test "show_for skips label if requested" do
|
67
|
+
with_attribute_for @user, :name, :label => false
|
68
|
+
assert_no_select "div.show_for p.wrapper strong.label"
|
69
|
+
end
|
70
|
+
|
71
|
+
test "show_for allows label to be configured globally" do
|
72
|
+
swap ShowFor, :label_tag => :span do
|
73
|
+
with_attribute_for @user, :name
|
74
|
+
assert_select "div.show_for p.wrapper span.label"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
test "show_for allows label to be changed by attribute" do
|
79
|
+
with_attribute_for @user, :name, :label_tag => :span
|
80
|
+
assert_select "div.show_for p.wrapper span.label"
|
81
|
+
end
|
82
|
+
|
83
|
+
test "show_for allows label html to be configured by attribute" do
|
84
|
+
with_attribute_for @user, :name, :label_html => { :id => "thelabel", :class => "special" }
|
85
|
+
assert_select "div.show_for p.wrapper strong#thelabel.special.label"
|
86
|
+
end
|
87
|
+
|
88
|
+
test "show_for allows label to be set without lookup" do
|
89
|
+
with_attribute_for @user, :name, :label => "Special Label"
|
90
|
+
assert_select "div.show_for p.wrapper strong.label", "Special Label"
|
91
|
+
end
|
92
|
+
|
93
|
+
test "show_for#label accepts the text" do
|
94
|
+
with_label_for @user, "Special Label"
|
95
|
+
assert_select "div.show_for strong.label", "Special Label"
|
96
|
+
end
|
97
|
+
|
98
|
+
test "show_for#label accepts an attribute name" do
|
99
|
+
with_label_for @user, :name
|
100
|
+
assert_select "div.show_for strong.label", "Super User Name!"
|
101
|
+
end
|
102
|
+
|
103
|
+
test "show_for#label accepts html options" do
|
104
|
+
with_label_for @user, :name, :id => "thelabel", :class => "special"
|
105
|
+
assert_select "div.show_for strong#thelabel.special.label"
|
106
|
+
end
|
107
|
+
|
108
|
+
# CONTENT
|
109
|
+
test "show_for allows content tag to be configured globally" do
|
110
|
+
swap ShowFor, :content_tag => :span do
|
111
|
+
with_attribute_for @user, :name
|
112
|
+
assert_select "div.show_for p.wrapper span.content"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
test "show_for allows content tag to be changed by attribute" do
|
117
|
+
with_attribute_for @user, :name, :content_tag => :span
|
118
|
+
assert_select "div.show_for p.wrapper span.content"
|
119
|
+
end
|
120
|
+
|
121
|
+
test "show_for allows content tag html to be configured by attribute" do
|
122
|
+
with_attribute_for @user, :name, :content_tag => :span, :content_html => { :id => "thecontent", :class => "special" }
|
123
|
+
assert_select "div.show_for p.wrapper span#thecontent.special.content"
|
124
|
+
end
|
125
|
+
|
126
|
+
test "show_for accepts an attribute as string" do
|
127
|
+
with_attribute_for @user, :name
|
128
|
+
assert_select "div.show_for p.wrapper", /ShowFor/
|
129
|
+
end
|
130
|
+
|
131
|
+
test "show_for accepts an attribute as time" do
|
132
|
+
with_attribute_for @user, :created_at
|
133
|
+
assert_select "div.show_for p.wrapper", /#{Regexp.escape(I18n.l(@user.created_at))}/
|
134
|
+
end
|
135
|
+
|
136
|
+
test "show_for accepts an attribute as date" do
|
137
|
+
with_attribute_for @user, :updated_at
|
138
|
+
assert_select "div.show_for p.wrapper", /#{Regexp.escape(I18n.l(@user.updated_at))}/
|
139
|
+
end
|
140
|
+
|
141
|
+
test "show_for accepts an attribute as time with format options" do
|
142
|
+
with_attribute_for @user, :created_at, :format => :long
|
143
|
+
assert_select "div.show_for p.wrapper", /#{Regexp.escape(I18n.l(@user.created_at, :format => :long))}/
|
144
|
+
end
|
145
|
+
|
146
|
+
test "show_for accepts an attribute as true" do
|
147
|
+
with_attribute_for @user, :active
|
148
|
+
assert_select "div.show_for p.wrapper", /Yes/
|
149
|
+
end
|
150
|
+
|
151
|
+
test "show_for accepts an attribute as true which can be localized" do
|
152
|
+
store_translations(:en, :show_for => { :yes => "Hell yeah!" }) do
|
153
|
+
with_attribute_for @user, :active
|
154
|
+
assert_select "div.show_for p.wrapper", /Hell yeah!/
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
test "show_for accepts an attribute as false" do
|
159
|
+
with_attribute_for @user, :invalid
|
160
|
+
assert_select "div.show_for p.wrapper", /No/
|
161
|
+
end
|
162
|
+
|
163
|
+
test "show_for accepts an attribute as false which can be localized" do
|
164
|
+
store_translations(:en, :show_for => { :no => "Hell no!" }) do
|
165
|
+
with_attribute_for @user, :invalid
|
166
|
+
assert_select "div.show_for p.wrapper", /Hell no!/
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
test "show_for accepts nil and or blank attributes" do
|
171
|
+
with_attribute_for @user, :description
|
172
|
+
assert_select "div.show_for p.wrapper", "Description"
|
173
|
+
end
|
174
|
+
|
175
|
+
test "show_for uses :if_blank if attribute is blank" do
|
176
|
+
with_attribute_for @user, :description, :if_blank => "No description provided"
|
177
|
+
assert_select "div.show_for p.wrapper", /No description provided/
|
178
|
+
end
|
179
|
+
|
180
|
+
test "show_for accepts a block to supply the content" do
|
181
|
+
with_attribute_for @user, :description do
|
182
|
+
"This description is not blank"
|
183
|
+
end
|
184
|
+
assert_select "div.show_for p.wrapper", /This description/
|
185
|
+
end
|
186
|
+
|
187
|
+
test "show_for escapes content by default" do
|
188
|
+
@user.name = "<b>hack you!</b>"
|
189
|
+
with_attribute_for @user, :name
|
190
|
+
assert_no_select "div.show_for p.wrapper b"
|
191
|
+
assert_select "div.show_for p.wrapper", /<b>/
|
192
|
+
end
|
193
|
+
|
194
|
+
test "show_for does not escape content if chosen" do
|
195
|
+
@user.name = "<b>hack you!</b>"
|
196
|
+
with_attribute_for @user, :name, :escape => false
|
197
|
+
assert_select "div.show_for p.wrapper b", "hack you!"
|
198
|
+
end
|
199
|
+
|
200
|
+
test "show_for#content accepts any object" do
|
201
|
+
with_content_for @user, "Special content"
|
202
|
+
assert_select "div.show_for", "Special content"
|
203
|
+
end
|
204
|
+
|
205
|
+
test "show_for#content accepts :if_blank as option" do
|
206
|
+
with_content_for @user, "", :if_blank => "Got blank"
|
207
|
+
assert_select "div.show_for", "Got blank"
|
208
|
+
end
|
209
|
+
|
210
|
+
test "show_for#content accepts html options" do
|
211
|
+
with_content_for @user, "Special content", :content_tag => :b, :id => "thecontent", :class => "special"
|
212
|
+
assert_select "div.show_for b#thecontent.special.content", "Special content"
|
213
|
+
end
|
214
|
+
|
215
|
+
# COLLECTIONS
|
216
|
+
test "show_for accepts an attribute as a collection" do
|
217
|
+
with_attribute_for @user, :scopes
|
218
|
+
assert_select "div.show_for p.wrapper ul.collection"
|
219
|
+
assert_select "div.show_for p.wrapper ul.collection li", :count => 3
|
220
|
+
end
|
221
|
+
|
222
|
+
test "show_for accepts an attribute as a collection with a block to iterate the collection" do
|
223
|
+
with_attribute_for @user, :scopes do |scope|
|
224
|
+
content_tag :span, scope
|
225
|
+
end
|
226
|
+
assert_select "div.show_for p.wrapper ul.collection"
|
227
|
+
assert_select "div.show_for p.wrapper ul.collection span", :count => 3
|
228
|
+
end
|
229
|
+
|
230
|
+
test "show_for allows collection tag to be configured globally" do
|
231
|
+
swap ShowFor, :collection_tag => :ol do
|
232
|
+
with_attribute_for @user, :scopes
|
233
|
+
assert_select "div.show_for p.wrapper ol.collection"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
test "show_for allows collection tag to be changed by attribute" do
|
238
|
+
with_attribute_for @user, :scopes, :collection_tag => :ol
|
239
|
+
assert_select "div.show_for p.wrapper ol.collection"
|
240
|
+
end
|
241
|
+
|
242
|
+
test "show_for allows collection tag html to be configured by attribute" do
|
243
|
+
with_attribute_for @user, :scopes, :collection_html => { :id => "thecollection", :class => "special" }
|
244
|
+
assert_select "div.show_for p.wrapper ul#thecollection.special.collection"
|
245
|
+
end
|
246
|
+
|
247
|
+
# ASSOCIATIONS
|
248
|
+
test "show_for works with belongs_to/has_one associations" do
|
249
|
+
with_association_for @user, :company
|
250
|
+
assert_select "div.show_for p.wrapper", /PlataformaTec/
|
251
|
+
end
|
252
|
+
|
253
|
+
test "show_for accepts :method as option to tell how to retrieve association value" do
|
254
|
+
with_association_for @user, :company, :method => :alternate_name
|
255
|
+
assert_select "div.show_for p.wrapper", /Alternate PlataformaTec/
|
256
|
+
end
|
257
|
+
|
258
|
+
test "show_for works with has_many/has_and_belongs_to_many associations" do
|
259
|
+
with_association_for @user, :tags
|
260
|
+
assert_select "div.show_for p.wrapper ul.collection"
|
261
|
+
assert_select "div.show_for p.wrapper ul.collection li", "Tag 1"
|
262
|
+
assert_select "div.show_for p.wrapper ul.collection li", "Tag 2"
|
263
|
+
assert_select "div.show_for p.wrapper ul.collection li", "Tag 3"
|
264
|
+
end
|
265
|
+
|
266
|
+
test "show_for accepts :method as option to tell how to retrieve association values" do
|
267
|
+
with_association_for @user, :tags, :method => :alternate_name
|
268
|
+
assert_select "div.show_for p.wrapper ul.collection"
|
269
|
+
assert_select "div.show_for p.wrapper ul.collection li", "Alternate Tag 1"
|
270
|
+
assert_select "div.show_for p.wrapper ul.collection li", "Alternate Tag 2"
|
271
|
+
assert_select "div.show_for p.wrapper ul.collection li", "Alternate Tag 3"
|
272
|
+
end
|
273
|
+
|
274
|
+
test "show_for accepts :to_sentence as option in collection associations" do
|
275
|
+
with_association_for @user, :tags, :to_sentence => true
|
276
|
+
assert_no_select "div.show_for p.wrapper ul.collection"
|
277
|
+
assert_select "div.show_for p.wrapper", /Tag 1, Tag 2, and Tag 3/
|
278
|
+
end
|
279
|
+
|
280
|
+
test "show_for accepts :join as option in collection associations" do
|
281
|
+
with_association_for @user, :tags, :join => ", "
|
282
|
+
assert_no_select "div.show_for p.wrapper ul.collection"
|
283
|
+
assert_select "div.show_for p.wrapper", /Tag 1, Tag 2, Tag 3/
|
284
|
+
end
|
285
|
+
|
286
|
+
test "show_for accepts a block without argument in collection associations" do
|
287
|
+
with_association_for @user, :tags do
|
288
|
+
@user.tags.map(&:name).to_sentence
|
289
|
+
end
|
290
|
+
assert_no_select "div.show_for p.wrapper ul.collection"
|
291
|
+
assert_select "div.show_for p.wrapper", /Tag 1, Tag 2, and Tag 3/
|
292
|
+
end
|
293
|
+
|
294
|
+
test "show_for accepts a block with argument in collection associations" do
|
295
|
+
with_association_for @user, :tags, :collection_tag => :p do |tag|
|
296
|
+
assert_kind_of Tag, tag
|
297
|
+
content_tag(:span, tag.name)
|
298
|
+
end
|
299
|
+
assert_no_select "div.show_for p.wrapper ul.collection"
|
300
|
+
assert_select "div.show_for p.wrapper p.collection"
|
301
|
+
assert_select "div.show_for p.wrapper p.collection span", "Tag 1"
|
302
|
+
assert_select "div.show_for p.wrapper p.collection span", "Tag 2"
|
303
|
+
assert_select "div.show_for p.wrapper p.collection span", "Tag 3"
|
304
|
+
end
|
305
|
+
end
|
data/test/helper_test.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class HelperTest < ActionView::TestCase
|
4
|
+
test "show for yields an instance of ShowFor::Builder" do
|
5
|
+
show_for @user do |f|
|
6
|
+
assert f.instance_of?(ShowFor::Builder)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
test "show for should add default class to form" do
|
11
|
+
show_for @user do |f| end
|
12
|
+
assert_select "div.show_for"
|
13
|
+
end
|
14
|
+
|
15
|
+
test "show for should add object class name as css class to form" do
|
16
|
+
show_for @user do |f| end
|
17
|
+
assert_select "div.show_for.user"
|
18
|
+
end
|
19
|
+
|
20
|
+
test "show for should pass options" do
|
21
|
+
show_for @user, :id => "my_div", :class => "common" do |f| end
|
22
|
+
assert_select "div#my_div.show_for.user.common"
|
23
|
+
end
|
24
|
+
|
25
|
+
test "show for tag should be configurable" do
|
26
|
+
swap ShowFor, :show_for_tag => :p do
|
27
|
+
show_for @user do |f| end
|
28
|
+
assert_select "p.show_for"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module MiscHelpers
|
2
|
+
def store_translations(locale, translations, &block)
|
3
|
+
begin
|
4
|
+
I18n.backend.store_translations locale, translations
|
5
|
+
yield
|
6
|
+
ensure
|
7
|
+
I18n.reload!
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def assert_no_select(*args)
|
12
|
+
assert_raise Test::Unit::AssertionFailedError do
|
13
|
+
assert_select(*args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def swap(object, new_values)
|
18
|
+
old_values = {}
|
19
|
+
new_values.each do |key, value|
|
20
|
+
old_values[key] = object.send key
|
21
|
+
object.send :"#{key}=", value
|
22
|
+
end
|
23
|
+
yield
|
24
|
+
ensure
|
25
|
+
old_values.each do |key, value|
|
26
|
+
object.send :"#{key}=", value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
class Company < Struct.new(:id, :name)
|
4
|
+
def alternate_name
|
5
|
+
"Alternate #{self.name}"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Tag < Struct.new(:id, :name)
|
10
|
+
def self.all(options={})
|
11
|
+
(1..3).map{ |i| Tag.new(i, "Tag #{i}") }
|
12
|
+
end
|
13
|
+
|
14
|
+
def alternate_name
|
15
|
+
"Alternate #{self.name}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class User < OpenStruct
|
20
|
+
# Get rid of deprecation warnings
|
21
|
+
undef_method :id
|
22
|
+
|
23
|
+
def tags
|
24
|
+
Tag.all
|
25
|
+
end
|
26
|
+
|
27
|
+
def company
|
28
|
+
Company.new(1, "PlataformaTec")
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.human_attribute_name(attribute)
|
32
|
+
case attribute
|
33
|
+
when 'name'
|
34
|
+
'Super User Name!'
|
35
|
+
when 'company'
|
36
|
+
'Company Human Name!'
|
37
|
+
else
|
38
|
+
attribute.humanize
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.human_name
|
43
|
+
"User"
|
44
|
+
end
|
45
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
require 'action_controller'
|
5
|
+
require 'action_view/test_case'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'ruby-debug'
|
9
|
+
rescue LoadError
|
10
|
+
end
|
11
|
+
|
12
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib', 'show_for')
|
13
|
+
require 'show_for'
|
14
|
+
|
15
|
+
Dir["#{File.dirname(__FILE__)}/support/*.rb"].each { |f| require f }
|
16
|
+
I18n.default_locale = :en
|
17
|
+
|
18
|
+
class ActionView::TestCase
|
19
|
+
include MiscHelpers
|
20
|
+
|
21
|
+
tests ShowFor::Helper
|
22
|
+
|
23
|
+
setup :setup_new_user
|
24
|
+
|
25
|
+
def setup_new_user(options={})
|
26
|
+
@user = User.new({
|
27
|
+
:id => 1,
|
28
|
+
:name => 'ShowFor',
|
29
|
+
:description => '',
|
30
|
+
:active => true,
|
31
|
+
:invalid => false,
|
32
|
+
:scopes => ["admin", "manager", "visitor"],
|
33
|
+
:created_at => Time.now,
|
34
|
+
:updated_at => Date.today
|
35
|
+
}.merge(options))
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: show_for
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Jos\xC3\xA9 Valim"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-08 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Wrap your objects with a helper to easily show them
|
17
|
+
email: contact@plataformatec.com.br
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- generators/show_for_install/USAGE
|
26
|
+
- generators/show_for_install/show_for_install_generator.rb
|
27
|
+
- generators/show_for_install/templates/show_for.rb
|
28
|
+
- init.rb
|
29
|
+
- lib/show_for.rb
|
30
|
+
- lib/show_for/builder.rb
|
31
|
+
- lib/show_for/content.rb
|
32
|
+
- lib/show_for/helper.rb
|
33
|
+
- lib/show_for/label.rb
|
34
|
+
- lib/show_for/locale/en.yml
|
35
|
+
- lib/show_for/version.rb
|
36
|
+
- README.rdoc
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://github.com/plataformatec/show_for
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options:
|
43
|
+
- --charset=UTF-8
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.3.5
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Wrap your objects with a helper to easily show them
|
65
|
+
test_files:
|
66
|
+
- test/builder_test.rb
|
67
|
+
- test/helper_test.rb
|
68
|
+
- test/support/misc_helpers.rb
|
69
|
+
- test/support/models.rb
|
70
|
+
- test/test_helper.rb
|