show_for 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,12 @@
1
+ == 0.2.5
2
+
3
+ * enhancements
4
+ * Add a :value option for attribute (by github.com/ml-gt)
5
+ * Add label_class, content_class, wrapper_class and content_class configuration options (by github.com/wojtekmach)
6
+
7
+ * bug fix
8
+ * Fix problem with label => false and html_safe (label => false) (by github.com/nashby)
9
+
1
10
  == 0.2.4
2
11
 
3
12
  * enhancements
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 PlataformaTec http://blog.plataformatec.com.br/
1
+ Copyright (c) 2012 PlataformaTec http://blog.plataformatec.com.br/
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -22,7 +22,7 @@ ShowFor.setup do |config|
22
22
  # config.collection_tag = :ul
23
23
 
24
24
  # The default iterator to be used when invoking a collection/association.
25
- # config.default_collection_proc = lambda { |value| "<li>#{value}</li>" }
25
+ # config.default_collection_proc = lambda { |value| "<li>#{ERB::Util.h(value)}</li>".html_safe }
26
26
 
27
27
  # The default format to be used in I18n when localizing a Date/Time.
28
28
  # config.i18n_format = :default
@@ -21,7 +21,7 @@ module ShowFor
21
21
  block
22
22
  else
23
23
  association = @object.send(association_name)
24
- values = retrieve_values_from_association(association, options)
24
+ values = values_from_association(association, options)
25
25
 
26
26
  if options.delete(:to_sentence)
27
27
  values.to_sentence
@@ -37,7 +37,7 @@ module ShowFor
37
37
 
38
38
  protected
39
39
 
40
- def retrieve_values_from_association(association, options) #:nodoc:
40
+ def values_from_association(association, options) #:nodoc:
41
41
  sample = association.is_a?(Array) ? association.first : association
42
42
 
43
43
  if options[:method]
@@ -2,15 +2,10 @@ module ShowFor
2
2
  module Attribute
3
3
  def attribute(attribute_name, options={}, &block)
4
4
  apply_default_options!(attribute_name, options)
5
+ block = block_from_value_option(attribute_name, options) unless block
5
6
  collection_block, block = block, nil if collection_block?(block)
6
7
 
7
- value = if block
8
- block
9
- elsif @object.respond_to?(:"human_#{attribute_name}")
10
- @object.send :"human_#{attribute_name}"
11
- else
12
- @object.send(attribute_name)
13
- end
8
+ value = attribute_value(attribute_name, &block)
14
9
 
15
10
  wrap_label_and_content(attribute_name, value, options, &collection_block)
16
11
  end
@@ -19,20 +14,48 @@ module ShowFor
19
14
  apply_default_options!(attribute_name, options)
20
15
  collection_block, block = block, nil if collection_block?(block)
21
16
 
22
- value = if block
17
+ value = attribute_value(attribute_name, &block)
18
+
19
+ wrap_content(attribute_name, value, options, &collection_block)
20
+ end
21
+
22
+ def attributes(*attribute_names)
23
+ attribute_names.map do |attribute_name|
24
+ attribute(attribute_name)
25
+ end.join.html_safe
26
+ end
27
+
28
+ private
29
+
30
+ def attribute_value(attribute_name, &block)
31
+ if block
23
32
  block
24
33
  elsif @object.respond_to?(:"human_#{attribute_name}")
25
34
  @object.send :"human_#{attribute_name}"
26
35
  else
27
36
  @object.send(attribute_name)
28
37
  end
29
- wrap_content(attribute_name, value, options, &collection_block)
30
38
  end
31
39
 
32
- def attributes(*attribute_names)
33
- attribute_names.map do |attribute_name|
34
- attribute(attribute_name)
35
- end.join.html_safe
40
+ def block_from_value_option(attribute_name, options)
41
+ case options[:value]
42
+ when nil
43
+ nil
44
+ when Symbol
45
+ block_from_symbol(attribute_name, options)
46
+ else
47
+ lambda { options[:value] }
48
+ end
49
+ end
50
+
51
+ def block_from_symbol(attribute_name, options)
52
+ attribute = @object.send(attribute_name)
53
+ case attribute
54
+ when Array, Hash
55
+ lambda { |element| element.send(options[:value]) }
56
+ else
57
+ lambda { attribute.send(options[:value]) }
58
+ end
36
59
  end
37
60
  end
38
61
  end
@@ -36,7 +36,7 @@ module ShowFor
36
36
  def apply_default_options!(name, options) #:nodoc:
37
37
  html_class = "#{object_name}_#{name}".gsub(/\W/, '')
38
38
  wrapper_html = options[:wrapper_html] ||= {}
39
- wrapper_html[:class] = "#{html_class} #{wrapper_html[:class]}".strip
39
+ wrapper_html[:class] = "#{html_class} #{wrapper_html[:class]}".rstrip
40
40
  end
41
41
 
42
42
  # Gets the default tag set in ShowFor module and apply (if defined)
@@ -45,15 +45,14 @@ module ShowFor
45
45
  def wrap_with(type, content, options) #:nodoc:
46
46
  tag = options.delete(:"#{type}_tag") || ShowFor.send(:"#{type}_tag")
47
47
 
48
- html = if tag
48
+ if tag
49
+ type_class = ShowFor.send :"#{type}_class"
49
50
  html_options = options.delete(:"#{type}_html") || {}
50
- html_options[:class] = "#{type} #{html_options[:class]}".strip
51
+ html_options[:class] = "#{type_class} #{html_options[:class]}".rstrip
51
52
  @template.content_tag(tag, content, html_options)
52
53
  else
53
54
  content
54
55
  end
55
-
56
- html
57
56
  end
58
57
 
59
58
  # Returns true if the block is supposed to iterate through a collection,
@@ -27,7 +27,7 @@ module ShowFor
27
27
  value
28
28
  end
29
29
 
30
- options[:content_html] = options.dup if apply_options
30
+ options[:content_html] = options.except(:content_tag) if apply_options
31
31
  wrap_with(:content, content, options)
32
32
  end
33
33
 
@@ -35,13 +35,12 @@ module ShowFor
35
35
 
36
36
  def collection_handler(value, options, &block) #:nodoc:
37
37
  iterator = collection_block?(block) ? block : ShowFor.default_collection_proc
38
- response = ""
39
38
 
40
- value.each do |item|
41
- response << template.capture(item, &iterator)
42
- end
39
+ response = value.map do |item|
40
+ template.capture(item, &iterator)
41
+ end.join.html_safe
43
42
 
44
- wrap_with(:collection, response.html_safe, options)
43
+ wrap_with(:collection, response, options)
45
44
  end
46
45
  end
47
- end
46
+ end
@@ -13,7 +13,7 @@ module ShowFor
13
13
  tag = html_options.delete(:show_for_tag) || ShowFor.show_for_tag
14
14
 
15
15
  html_options[:id] ||= dom_id(object)
16
- html_options[:class] = "show_for #{dom_class(object)} #{html_options[:class]}".strip
16
+ html_options[:class] = "show_for #{dom_class(object)} #{html_options[:class]}".rstrip
17
17
 
18
18
  builder = html_options.delete(:builder) || ShowFor::Builder
19
19
  content = capture(builder.new(object, self), &block)
@@ -9,7 +9,7 @@ module ShowFor
9
9
  human_attribute_name(text_or_attribute)
10
10
  end
11
11
 
12
- return nil.to_s if label == false
12
+ return ''.html_safe if label == false
13
13
  options[:label_html] = options.dup if apply_options
14
14
 
15
15
  label = ShowFor.label_proc.call(label) if options.fetch(:wrap_label, true) && ShowFor.label_proc
@@ -1,3 +1,3 @@
1
1
  module ShowFor
2
- VERSION = "0.2.4".freeze
2
+ VERSION = "0.2.5".freeze
3
3
  end
data/lib/show_for.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'action_view'
1
2
  require 'show_for/helper'
2
3
 
3
4
  module ShowFor
@@ -9,21 +10,33 @@ module ShowFor
9
10
  mattr_accessor :label_tag
10
11
  @@label_tag = :strong
11
12
 
13
+ mattr_accessor :label_class
14
+ @@label_class = :label
15
+
12
16
  mattr_accessor :separator
13
17
  @@separator = "<br />"
14
18
 
15
19
  mattr_accessor :content_tag
16
20
  @@content_tag = nil
17
21
 
22
+ mattr_accessor :content_class
23
+ @@content_class = :content
24
+
18
25
  mattr_accessor :blank_content_class
19
26
  @@blank_content_class = "blank"
20
27
 
21
28
  mattr_accessor :wrapper_tag
22
29
  @@wrapper_tag = :p
23
30
 
31
+ mattr_accessor :wrapper_class
32
+ @@wrapper_class = :wrapper
33
+
24
34
  mattr_accessor :collection_tag
25
35
  @@collection_tag = :ul
26
36
 
37
+ mattr_accessor :collection_class
38
+ @@collection_class = :collection
39
+
27
40
  mattr_accessor :default_collection_proc
28
41
  @@default_collection_proc = lambda { |value| "<li>#{ERB::Util.html_escape(value)}</li>".html_safe }
29
42
 
@@ -32,7 +45,7 @@ module ShowFor
32
45
 
33
46
  mattr_accessor :association_methods
34
47
  @@association_methods = [ :name, :title, :to_s ]
35
-
48
+
36
49
  mattr_accessor :label_proc
37
50
  @@label_proc = nil
38
51
 
@@ -45,4 +58,4 @@ module ShowFor
45
58
  def self.setup
46
59
  yield self
47
60
  end
48
- end
61
+ end
@@ -0,0 +1,72 @@
1
+ require 'test_helper'
2
+
3
+ class AssociationTest < ActionView::TestCase
4
+ test "show_for works with belongs_to/has_one associations" do
5
+ with_association_for @user, :company
6
+ assert_select "div.show_for p.wrapper", /PlataformaTec/
7
+ end
8
+
9
+ test "show_for accepts :using as option to tell how to retrieve association value" do
10
+ with_association_for @user, :company, :using => :alternate_name
11
+ assert_select "div.show_for p.wrapper", /Alternate PlataformaTec/
12
+ end
13
+
14
+ test "show_for accepts :in to tell to retrieve an attribute from association" do
15
+ with_attribute_for @user, :alternate_name, :in => :company
16
+ assert_select "div.show_for p.wrapper", /Alternate PlataformaTec/
17
+ end
18
+
19
+ test "show_for forwards all options send with :in to association" do
20
+ with_attribute_for @user, :alternate_name, :in => :tags, :to_sentence => true
21
+ assert_no_select "div.show_for p.wrapper ul.collection"
22
+ assert_select "div.show_for p.wrapper", /Alternate Tag 1, Alternate Tag 2, and Alternate Tag 3/
23
+ end
24
+
25
+ test "show_for works with has_many/has_and_belongs_to_many associations" do
26
+ with_association_for @user, :tags
27
+ assert_select "div.show_for p.wrapper ul.collection"
28
+ assert_select "div.show_for p.wrapper ul.collection li", "Tag 1"
29
+ assert_select "div.show_for p.wrapper ul.collection li", "Tag 2"
30
+ assert_select "div.show_for p.wrapper ul.collection li", "Tag 3"
31
+ end
32
+
33
+ test "show_for accepts :using as option to tell how to retrieve association values" do
34
+ with_association_for @user, :tags, :using => :alternate_name
35
+ assert_select "div.show_for p.wrapper ul.collection"
36
+ assert_select "div.show_for p.wrapper ul.collection li", "Alternate Tag 1"
37
+ assert_select "div.show_for p.wrapper ul.collection li", "Alternate Tag 2"
38
+ assert_select "div.show_for p.wrapper ul.collection li", "Alternate Tag 3"
39
+ end
40
+
41
+ test "show_for accepts :to_sentence as option in collection associations" do
42
+ with_association_for @user, :tags, :to_sentence => true
43
+ assert_no_select "div.show_for p.wrapper ul.collection"
44
+ assert_select "div.show_for p.wrapper", /Tag 1, Tag 2, and Tag 3/
45
+ end
46
+
47
+ test "show_for accepts :join as option in collection associations" do
48
+ with_association_for @user, :tags, :join => ", "
49
+ assert_no_select "div.show_for p.wrapper ul.collection"
50
+ assert_select "div.show_for p.wrapper", /Tag 1, Tag 2, Tag 3/
51
+ end
52
+
53
+ test "show_for accepts a block without argument in collection associations" do
54
+ with_association_for @user, :tags do
55
+ @user.tags.map(&:name).to_sentence
56
+ end
57
+ assert_no_select "div.show_for p.wrapper ul.collection"
58
+ assert_select "div.show_for p.wrapper", /Tag 1, Tag 2, and Tag 3/
59
+ end
60
+
61
+ test "show_for accepts a block with argument in collection associations" do
62
+ with_association_for @user, :tags, :collection_tag => :p do |tag|
63
+ assert_kind_of Tag, tag
64
+ content_tag(:span, tag.name)
65
+ end
66
+ assert_no_select "div.show_for p.wrapper ul.collection"
67
+ assert_select "div.show_for p.wrapper p.collection"
68
+ assert_select "div.show_for p.wrapper p.collection span", "Tag 1"
69
+ assert_select "div.show_for p.wrapper p.collection span", "Tag 2"
70
+ assert_select "div.show_for p.wrapper p.collection span", "Tag 3"
71
+ end
72
+ end
@@ -0,0 +1,167 @@
1
+ require 'test_helper'
2
+
3
+ class AttributeTest < ActionView::TestCase
4
+ # COLLECTIONS
5
+ test "show_for accepts an attribute as a collection" do
6
+ with_attribute_for @user, :scopes
7
+ assert_select "div.show_for p.wrapper ul.collection"
8
+ assert_select "div.show_for p.wrapper ul.collection li", :count => 3
9
+ end
10
+
11
+ test "show_for accepts an attribute as a collection with a block to iterate the collection" do
12
+ with_attribute_for @user, :scopes do |scope|
13
+ content_tag :span, scope
14
+ end
15
+ assert_select "div.show_for p.wrapper ul.collection"
16
+ assert_select "div.show_for p.wrapper ul.collection span", :count => 3
17
+ end
18
+
19
+ test "show_for treats symbol for :value as method on each element of collection" do
20
+ with_attribute_for @user, :scopes, :value => :upcase
21
+ @user.scopes.each do |scope|
22
+ assert_select "div.show_for p.wrapper ul.collection", /#{scope.upcase}/
23
+ end
24
+ end
25
+
26
+ test "show_for allows collection tag to be configured globally" do
27
+ swap ShowFor, :collection_tag => :ol, :collection_class => "my_collection" do
28
+ with_attribute_for @user, :scopes
29
+ assert_select "div.show_for p.wrapper ol.my_collection"
30
+ end
31
+ end
32
+
33
+ test "show_for allows collection tag to be changed by attribute" do
34
+ with_attribute_for @user, :scopes, :collection_tag => :ol
35
+ assert_select "div.show_for p.wrapper ol.collection"
36
+ end
37
+
38
+ test "show_for allows collection tag html to be configured by attribute" do
39
+ with_attribute_for @user, :scopes, :collection_html => { :id => "thecollection", :class => "special" }
40
+ assert_select "div.show_for p.wrapper ul#thecollection.special.collection"
41
+ end
42
+
43
+ # CONTENT
44
+ test "show_for allows content tag to be configured globally" do
45
+ swap ShowFor, :content_tag => :span, :content_class => :my_content do
46
+ with_attribute_for @user, :name
47
+ assert_select "div.show_for p.wrapper span.my_content"
48
+ end
49
+ end
50
+
51
+ test "show_for allows content tag to be changed by attribute" do
52
+ with_attribute_for @user, :name, :content_tag => :span
53
+ assert_select "div.show_for p.wrapper span.content"
54
+ end
55
+
56
+ test "show_for allows content tag html to be configured by attribute" do
57
+ with_attribute_for @user, :name, :content_tag => :span, :content_html => { :id => "thecontent", :class => "special" }
58
+ assert_select "div.show_for p.wrapper span#thecontent.special.content"
59
+ end
60
+
61
+ test "show_for accepts an attribute as string" do
62
+ with_attribute_for @user, :name
63
+ assert_select "div.show_for p.wrapper", /ShowFor/
64
+ end
65
+
66
+ test "show_for accepts an attribute as time" do
67
+ with_attribute_for @user, :created_at
68
+ assert_select "div.show_for p.wrapper", /#{Regexp.escape(I18n.l(@user.created_at))}/
69
+ end
70
+
71
+ test "show_for accepts an attribute as date" do
72
+ with_attribute_for @user, :updated_at
73
+ assert_select "div.show_for p.wrapper", /#{Regexp.escape(I18n.l(@user.updated_at))}/
74
+ end
75
+
76
+ test "show_for accepts an attribute as time with format options" do
77
+ with_attribute_for @user, :created_at, :format => :long
78
+ assert_select "div.show_for p.wrapper", /#{Regexp.escape(I18n.l(@user.created_at, :format => :long))}/
79
+ end
80
+
81
+ test "show_for accepts an attribute as true" do
82
+ with_attribute_for @user, :active
83
+ assert_select "div.show_for p.wrapper", /Yes/
84
+ end
85
+
86
+ test "show_for accepts an attribute as true which can be localized" do
87
+ store_translations(:en, :show_for => { :yes => "Hell yeah!" }) do
88
+ with_attribute_for @user, :active
89
+ assert_select "div.show_for p.wrapper", /Hell yeah!/
90
+ end
91
+ end
92
+
93
+ test "show_for accepts an attribute as false" do
94
+ with_attribute_for @user, :invalid
95
+ assert_select "div.show_for p.wrapper", /No/
96
+ end
97
+
98
+ test "show_for accepts an attribute as false which can be localized" do
99
+ store_translations(:en, :show_for => { :no => "Hell no!" }) do
100
+ with_attribute_for @user, :invalid
101
+ assert_select "div.show_for p.wrapper", /Hell no!/
102
+ end
103
+ end
104
+
105
+ test "show_for accepts nil and or blank attributes" do
106
+ with_attribute_for @user, :description
107
+ assert_select "div.show_for p.wrapper", /Not specified/
108
+ end
109
+
110
+ test "show_for accepts not spcified message can be localized" do
111
+ store_translations(:en, :show_for => { :blank => "OMG! It's blank!" }) do
112
+ with_attribute_for @user, :description
113
+ assert_select "div.show_for p.wrapper", /OMG! It's blank!/
114
+ end
115
+ end
116
+
117
+ test "show_for uses :if_blank if attribute is blank" do
118
+ with_attribute_for @user, :description, :if_blank => "No description provided"
119
+ assert_select "div.show_for p.wrapper", /No description provided/
120
+ end
121
+
122
+ test "show_for accepts a block to supply the content" do
123
+ with_attribute_for @user, :description do
124
+ "This description is not blank"
125
+ end
126
+ assert_select "div.show_for p.wrapper", /This description/
127
+ end
128
+
129
+ test "show_for escapes content by default" do
130
+ @user.name = "<b>hack you!</b>"
131
+ with_attribute_for @user, :name
132
+ assert_no_select "div.show_for p.wrapper b"
133
+ assert_select "div.show_for p.wrapper", /&lt;b&gt;/
134
+ end
135
+
136
+ test "show_for works with html_safe marked strings" do
137
+ @user.name = "<b>hack you!</b>".html_safe
138
+ with_attribute_for @user, :name
139
+ assert_select "div.show_for p.wrapper b", "hack you!"
140
+ end
141
+
142
+ test "show_for uses :value if supplied" do
143
+ with_attribute_for @user, :name, :value => "Calculated Value"
144
+ assert_select "div.show_for p.wrapper", /Calculated Value/
145
+ end
146
+
147
+ test "show_for ignores :value if a block is supplied" do
148
+ with_attribute_for @user, :name, :value => "Calculated Value" do
149
+ @user.name.upcase
150
+ end
151
+ assert_select "div.show_for p.wrapper", /#{@user.name.upcase}/
152
+ end
153
+
154
+ test "show_for treats symbol for :value as method on attribute" do
155
+ with_attribute_for @user, :name, :value => :upcase
156
+ assert_select "div.show_for p.wrapper", /#{@user.name.upcase}/
157
+ end
158
+
159
+ # ATTRIBUTES
160
+ test "show_for attributes wraps each attribute with a label and content" do
161
+ with_attributes_for @user, :name, :email
162
+ assert_select "div.show_for p.user_name.wrapper", /ShowFor/
163
+ assert_select "p.user_name strong.label", "Super User Name!"
164
+ assert_select "div.show_for p.user_email.wrapper", /Not specified/
165
+ assert_select "p.user_email strong.label", "Email"
166
+ end
167
+ end