attrtastic 0.1.3 → 0.2.0

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/Rakefile CHANGED
@@ -15,6 +15,7 @@ begin
15
15
  gem.homepage = "http://github.com/MBO/attrtastic"
16
16
  gem.authors = ["Boruta Miroslaw"]
17
17
  gem.add_development_dependency "yard", ">= 0"
18
+ gem.add_development_dependency "shoulda", ">= 0"
18
19
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
20
  end
20
21
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.2.0
data/attrtastic.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{attrtastic}
8
- s.version = "0.1.3"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Boruta Miroslaw"]
12
- s.date = %q{2010-01-11}
12
+ s.date = %q{2010-01-15}
13
13
  s.description = %q{ Attrtastic, in its assumtion, should be similar in usage to formtastic and
14
14
  ease of displaying AR record informations (attributes). It should help
15
15
  scafforld show/index pages.
@@ -71,11 +71,14 @@ Gem::Specification.new do |s|
71
71
 
72
72
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
73
73
  s.add_development_dependency(%q<yard>, [">= 0"])
74
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
74
75
  else
75
76
  s.add_dependency(%q<yard>, [">= 0"])
77
+ s.add_dependency(%q<shoulda>, [">= 0"])
76
78
  end
77
79
  else
78
80
  s.add_dependency(%q<yard>, [">= 0"])
81
+ s.add_dependency(%q<shoulda>, [">= 0"])
79
82
  end
80
83
  end
81
84
 
data/lib/attrtastic.rb CHANGED
@@ -22,8 +22,9 @@ module Attrtastic
22
22
  # Creates attributes list without header, yields block to include each attribute
23
23
  #
24
24
  # @param [Hash] options Options for formating attributes block
25
- # @option options [String] :class ('') Name of html class(-es) to add to attributes block
26
- # @option options [String] :header_class ('') Name of html class(-es) to add to header
25
+ # @option options [String] :name (nil) Optional header of attributes section
26
+ # @option options [String] :class ('') Name of html class to add to attributes block
27
+ # @option options [String] :header_class ('') Name of html class to add to header
27
28
  # @yield Block which can call #attribute to include attribute value
28
29
  #
29
30
  # @example
@@ -32,14 +33,54 @@ module Attrtastic
32
33
  # <%= attr.attribute :email %>
33
34
  # <% end %>
34
35
  #
36
+ # @example
37
+ # <% attr.attributes :name => "User" do %>
38
+ # <%= attr.attribute :name %>
39
+ # <%= attr.attribute :email %>
40
+ # <% end %>
41
+ #
42
+ # @example
43
+ # <% attr.attributes :for => :user do |user| %>
44
+ # <%= user.attribute :name %>
45
+ # <%= user.attribute :email %>
46
+ # <% user.attribute :profile do %>
47
+ # <%= link_to h(user.record.name), user_path(user.record) %>
48
+ # <% end %>
49
+ # <% end %>
50
+ #
51
+ # @example
52
+ # <% attr.attributes :for => @user do |user| %>
53
+ # <%= user.attribute :name %>
54
+ # <%= user.attribute :email %>
55
+ # <% user.attribute :profile do %>
56
+ # <%= link_to h(@user.name), user_path(@user) %>
57
+ # <% end %>
58
+ # <% end %>
59
+ #
60
+ # @example
61
+ # <% attr.attributes :for => :posts do |post| %>
62
+ # <%= post.attribute :author %>
63
+ # <%= post.attribute :title %>
64
+ # <% end %>
65
+ #
66
+ # @example
67
+ # <% attr.attributes :for => @posts do |post| %>
68
+ # <%= post.attribute :author %>
69
+ # <%= post.attribute :title %>
70
+ # <% end %>
71
+ #
35
72
  # @overload attributes(header, options = {}, &block)
36
73
  # Creates attributes list with header and yields block to include each attribute
37
74
  #
38
75
  # @param [String] header Header of attributes section
39
76
  # @param [Hash] options Options for formating attributes block
40
- # @option options [String] :class ('') Name of html class(-es) to add to attributes block
41
- # @option options [String] :header_class ('') Name of html class(-es) to add to header
77
+ # @option options [String] :class ('') Name of html class to add to attributes block
78
+ # @option options [String] :header_class ('') Name of html class to add to header
79
+ # @option optinos [Symbol,Object] :for Optional new record for new builder
80
+ # passed as argument block. This new record can be symbol of method name for actual
81
+ # record, or any other object which is passed as new record for builder.
42
82
  # @yield Block which can call #attribute to include attribute value
83
+ # @yieldparam builder Builder instance holding actual record (retivable via #record)
43
84
  #
44
85
  # @example
45
86
  # <% attr.attributes "User info" do %>
@@ -47,29 +88,84 @@ module Attrtastic
47
88
  # <%= attr.attribute :email %>
48
89
  # <% end %>
49
90
  #
91
+ # @example
92
+ # <% attr.attributes "User", :for => :user do |user| %>
93
+ # <%= user.attribute :name %>
94
+ # <%= user.attribute :email %>
95
+ # <% user.attribute :profile do %>
96
+ # <%= link_to h(user.record.name), user_path(user.record) %>
97
+ # <% end %>
98
+ # <% end %>
99
+ #
100
+ # @example
101
+ # <% attr.attributes "User", :for => @user do |user| %>
102
+ # <%= user.attribute :name %>
103
+ # <%= user.attribute :email %>
104
+ # <% user.attribute :profile do %>
105
+ # <%= link_to h(@user.name), user_path(@user) %>
106
+ # <% end %>
107
+ # <% end %>
108
+ #
109
+ # @example
110
+ # <% attr.attributes "Post", :for => :posts do |post| %>
111
+ # <%= post.attribute :author %>
112
+ # <%= post.attribute :title %>
113
+ # <% end %>
114
+ #
115
+ # @example
116
+ # <% attr.attributes "Post", :for => @posts do |post| %>
117
+ # <%= post.attribute :author %>
118
+ # <%= post.attribute :title %>
119
+ # <% end %>
120
+ #
50
121
  # @overload attributes(*symbols, options = {})
51
122
  # Creates attributes list without header, attributes are given as list of symbols (record properties)
52
123
  #
53
124
  # @param [Symbol, ...] symbols List of attributes
54
125
  # @param [Hash] options Options for formating attributes block
55
- # @option options [String] :class ('') Name of html class(-es) to add to attributes block
56
- # @option options [String] :header_class ('') Name of html class(-es) to add to header
126
+ # @option options [String] :name (nil) Optional header of attributes section
127
+ # @option options [String] :class ('') Name of html class to add to attributes block
128
+ # @option options [String] :header_class ('') Name of html class to add to header
57
129
  #
58
130
  # @example
59
131
  # <% attr.attributes :name, :email %>
60
132
  #
133
+ # @example
134
+ # <% attr.attributes :name, :email, :for => :author %>
135
+ #
136
+ # @example
137
+ # <% attr.attributes :name, :email, :for => @user %>
138
+ #
139
+ # @example
140
+ # <% attr.attributes :title, :for => :posts %>
141
+ #
142
+ # @example
143
+ # <% attr.attributes :title, :for => @posts %>
144
+ #
61
145
  # @overload attributes(header, *symbols, options = {})
62
146
  # Creates attributes list with header, attributes are given as list of symbols (record properties)
63
147
  #
64
148
  # @param [String] header Header of attributes section
65
149
  # @param [Symbol, ...] symbols Optional list of attributes
66
150
  # @param [Hash] options Options for formating attributes block
67
- # @option options [String] :class ('') Name of html class(-es) to add to attributes block
68
- # @option options [String] :header_class ('') Name of html class(-es) to add to header
151
+ # @option options [String] :class ('') Name of html class to add to attributes block
152
+ # @option options [String] :header_class ('') Name of html class to add to header
69
153
  #
70
154
  # @example
71
155
  # <% attr.attributes "User info" :name, :email %>
72
156
  #
157
+ # @example
158
+ # <% attr.attributes "Author", :name, :email, :for => :author %>
159
+ #
160
+ # @example
161
+ # <% attr.attributes "Author", :name, :email, :for => @user %>
162
+ #
163
+ # @example
164
+ # <% attr.attributes "Post", :title, :for => :posts %>
165
+ #
166
+ # @example
167
+ # <% attr.attributes "Post", :title, :for => @posts %>
168
+ #
73
169
  # @example All together
74
170
  # <% attr.attributes "User info", :name, :email, :class => "user_info", :header_class => "header important" %>
75
171
  #
@@ -88,28 +184,24 @@ module Attrtastic
88
184
  end
89
185
  options[:html] ||= {}
90
186
 
91
- html_class = [ "attributes", options[:html].delete(:class) ].compact.join(" ")
92
- html_header_class = [ "legend", options[:html].delete(:header_class) ].compact.join(" ")
93
-
94
- template.concat(template.tag(:div, {:class => html_class}, true))
95
-
96
187
  if args.first and args.first.is_a? String
97
- header = args.shift
98
- template.concat(template.content_tag(:div, header, :class => html_header_class))
188
+ options[:name] = args.shift
99
189
  end
100
190
 
101
- if block_given?
102
- template.concat(template.tag(:ol, {}, true))
103
- yield
104
- template.concat("</ol>")
105
- elsif args.present?
106
- template.concat(template.tag(:ol, {}, true))
107
- attrs = args.map {|method| attribute(method, options)}.compact.join
108
- template.concat(attrs)
109
- template.concat("</ol>")
191
+ if options[:for].blank?
192
+ attributes_for(record, args, options, &block)
193
+ else
194
+ if options[:for].is_a? Symbol
195
+ for_value = record.send(options[:for])
196
+ else
197
+ for_value = options[:for]
198
+ end
199
+
200
+ [*for_value].each do |value|
201
+ attributes_for(value, args, options, &block)
202
+ end
110
203
  end
111
204
 
112
- template.concat("</div>")
113
205
  end
114
206
 
115
207
  ##
@@ -120,7 +212,7 @@ module Attrtastic
120
212
  #
121
213
  # @param [Symbol] method Attribute name of given record
122
214
  # @param [Hash] options Options
123
- # @option options [String] :html ({}) Hash with optional :class, :label_class and :value_class names of class for html
215
+ # @option options [Hash] :html ({}) Hash with optional :class, :label_class and :value_class names of class for html
124
216
  # @option options [String] :label Label for attribute entry, overrides default label name from symbol
125
217
  # @option options [String] :value Value of attribute entry, overrides default value from record
126
218
  # @option options [Boolean] :display_empty (false) Indicates if print value of given attribute even if it is blank?
@@ -139,24 +231,31 @@ module Attrtastic
139
231
  #
140
232
  # @param [Symbol] method Attribute name of given record
141
233
  # @param [Hash] options Options
142
- # @option options [String] :html ({}) Hahs with optional :class, :label_class and :value_class names of class for html
234
+ # @option options [Hash] :html ({}) Hash with optional :class, :label_class and :value_class names of classes for html
143
235
  # @option options [String] :label Label for attribute entry, overrides default label name from symbol
144
- # @option options [Boolean] :display_empty (false) Indicates if print value of given attribute even if it is blank?
145
236
  # @yield Block which is executed in place of value for attribute
146
237
  #
147
238
  # @example
148
239
  # <% attr.attribute :name do %>
149
240
  # <%= link_to @user.full_name, user_path(@user) %>
150
241
  #
242
+ # @overload attribute(options = {}, &block)
243
+ # Creates entry for attribute with given block, options[:label] is mandatory in this case.
244
+ #
245
+ # @param [:Hash] options Options
246
+ # @option options [Hash] :html ({}) Hash with optional :class, :label_class and :value_class names of classes for html
247
+ # @option options [String] :label Mandatory label for attribute entry
248
+ # @yield Block which is executed in place of value for attribute
249
+ #
151
250
  # @example
152
- # <% attr.attribute :name, :label => "User link" do %>
251
+ # <% attr.attribute :label => "User link" do %>
153
252
  # <%= link_to @user.full_name, user_path(@user) %>
154
253
  #
155
254
  # @example
156
255
  # <%= attr.attribute :name, :display_empty => true %>
157
256
  #
158
257
  # @example
159
- # <% attr.attribute :name, :label => "User link" do %>
258
+ # <% attr.attribute :label => "User link" do %>
160
259
  # <%= link_to @user.full_name, user_path(@user) %>
161
260
  #
162
261
  def attribute(*args, &block)
@@ -196,6 +295,34 @@ module Attrtastic
196
295
 
197
296
  private
198
297
 
298
+ def attributes_for(object, methods, options, &block)
299
+ new_builder = self.class.new(object, template)
300
+
301
+ html_class = [ "attributes", options[:html].delete(:class) ].compact.join(" ")
302
+ html_header_class = [ "legend", options[:html].delete(:header_class) ].compact.join(" ")
303
+
304
+ template.concat(template.tag(:div, {:class => html_class}, true))
305
+
306
+ header = options[:name]
307
+
308
+ if header.present?
309
+ template.concat(template.content_tag(:div, header, :class => html_header_class))
310
+ end
311
+
312
+ if block_given?
313
+ template.concat(template.tag(:ol, {}, true))
314
+ yield(new_builder)
315
+ template.concat("</ol>")
316
+ elsif methods.present?
317
+ template.concat(template.tag(:ol, {}, true))
318
+ attrs = methods.map {|method| new_builder.attribute(method, options)}.compact.join
319
+ template.concat(attrs)
320
+ template.concat("</ol>")
321
+ end
322
+
323
+ template.concat("</div>")
324
+ end
325
+
199
326
  def label_for_attribute(method)
200
327
  if record.class.respond_to?(:human_attribute_name)
201
328
  record.class.human_attribute_name(method.to_s)
@@ -204,9 +331,11 @@ module Attrtastic
204
331
  end
205
332
  end
206
333
 
207
- #@@value_methods = %w/ to_label display_name full_name name title username login value to_s /
208
334
  def value_of_attribute(method)
209
- record.send(method).to_s
335
+ value = record.send(method)
336
+ value_methods = [ :to_label, :display_name, :full_name, :name, :title, :username, :login, :value ]
337
+ value_method = value_methods.find { |m| value.respond_to?(m) } || :to_s
338
+ value.send(value_method)
210
339
  end
211
340
 
212
341
  end
data/test/helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'test/unit'
2
+ require 'shoulda'
2
3
  require 'action_view'
3
4
 
4
5
  $LOAD_PATH.unshift(File.dirname(__FILE__))
@@ -2,121 +2,146 @@ require 'helper'
2
2
 
3
3
  class TestAttribute < Test::Unit::TestCase
4
4
 
5
- def setup
6
- setup_fixtures
7
- end
5
+ context "attribute" do
8
6
 
9
- def test__attribute__output
10
- expected = html <<-EOHTML
11
- <li class="attribute">
12
- <span class="label">Full name</span>
13
- <span class="value">Doe, John</span>
14
- </li>
15
- EOHTML
7
+ setup do
8
+ setup_fixtures
9
+ end
16
10
 
17
- actual = @user_builder.attribute(:full_name)
18
- assert_equal expected, actual
19
- end
11
+ should "generate output" do
12
+ expected = html <<-EOHTML
13
+ <li class="attribute">
14
+ <span class="label">Full name</span>
15
+ <span class="value">Doe, John</span>
16
+ </li>
17
+ EOHTML
20
18
 
21
- def test__attribute__with_empty_value
22
- actual = @user_builder.attribute(:title)
23
- assert_nil actual
19
+ actual = @user_builder.attribute(:full_name)
20
+ assert_equal expected, actual
21
+ end
24
22
 
25
- expected = html <<-EOHTML
26
- <li class="attribute">
27
- <span class="label">Title</span>
28
- <span class="value"></span>
29
- </li>
30
- EOHTML
23
+ should "not show attribute when value is blank" do
24
+ actual = @user_builder.attribute(:title)
25
+ assert_nil actual
26
+ end
31
27
 
32
- actual = @user_builder.attribute(:title, :display_empty => true)
33
- assert_equal expected, actual
34
- end
28
+ should "show attribute with :display_empty => true" do
29
+ expected = html <<-EOHTML
30
+ <li class="attribute">
31
+ <span class="label">Title</span>
32
+ <span class="value"></span>
33
+ </li>
34
+ EOHTML
35
35
 
36
- def test__attribute__with_custom_label
37
- expected = html <<-EOHTML
38
- <li class="attribute">
39
- <span class="label">Name</span>
40
- <span class="value">Doe, John</span>
41
- </li>
42
- EOHTML
36
+ actual = @user_builder.attribute(:title, :display_empty => true)
37
+ assert_equal expected, actual
38
+ end
43
39
 
44
- actual = @user_builder.attribute(:full_name, :label => "Name")
45
- assert_equal expected, actual
46
- end
40
+ should "convert nested object to value" do
41
+ expected = html <<-EOHTML
42
+ <li class="attribute">
43
+ <span class="label">Author</span>
44
+ <span class="value">Doe, John</span>
45
+ </li>
46
+ EOHTML
47
47
 
48
- def test__attribute__with_custom_value
49
- expected = html <<-EOHTML
50
- <li class="attribute">
51
- <span class="label">Full name</span>
52
- <span class="value">Sir Doe, John</span>
53
- </li>
54
- EOHTML
48
+ actual = @blog_builder.attribute(:author_full_name, :label => "Author")
49
+ assert_equal expected, actual
55
50
 
56
- actual = @user_builder.attribute(:full_name, :value => "Sir #{@user.full_name}")
57
- assert_equal expected, actual
58
- end
51
+ actual = @blog_builder.attribute(:author)
52
+ assert_equal expected, actual
53
+ end
59
54
 
60
- def test__attribute__with_empty_custom_value
61
- assert_nil @user_builder.attribute(:full_name, :value => nil)
62
- assert_nil @user_builder.attribute(:full_name, :value => "")
55
+ should "show custom label" do
56
+ expected = html <<-EOHTML
57
+ <li class="attribute">
58
+ <span class="label">Name</span>
59
+ <span class="value">Doe, John</span>
60
+ </li>
61
+ EOHTML
63
62
 
64
- expected = html <<-EOHTML
65
- <li class="attribute">
66
- <span class="label">Full name</span>
67
- <span class="value"></span>
68
- </li>
69
- EOHTML
63
+ actual = @user_builder.attribute(:full_name, :label => "Name")
64
+ assert_equal expected, actual
65
+ end
70
66
 
71
- actual = @user_builder.attribute(:full_name, :value => nil, :display_empty => true)
72
- assert_equal expected, actual
67
+ should "show custom value" do
68
+ expected = html <<-EOHTML
69
+ <li class="attribute">
70
+ <span class="label">Full name</span>
71
+ <span class="value">Sir Doe, John</span>
72
+ </li>
73
+ EOHTML
73
74
 
74
- actual = @user_builder.attribute(:full_name, :value => "", :display_empty => true)
75
- assert_equal expected, actual
76
- end
75
+ actual = @user_builder.attribute(:full_name, :value => "Sir #{@user.full_name}")
76
+ assert_equal expected, actual
77
+ end
78
+
79
+ should "work with custom value blank" do
80
+ assert_nil @user_builder.attribute(:full_name, :value => nil)
81
+ assert_nil @user_builder.attribute(:full_name, :value => "")
82
+
83
+ expected = html <<-EOHTML
84
+ <li class="attribute">
85
+ <span class="label">Full name</span>
86
+ <span class="value"></span>
87
+ </li>
88
+ EOHTML
77
89
 
78
- def test__attribute__with_block
79
- block_run = false
80
- @user_builder.attribute :full_name do
81
- block_run = true
90
+ actual = @user_builder.attribute(:full_name, :value => nil, :display_empty => true)
91
+ assert_equal expected, actual
92
+
93
+ actual = @user_builder.attribute(:full_name, :value => "", :display_empty => true)
94
+ assert_equal expected, actual
82
95
  end
83
- assert block_run
84
- end
85
96
 
86
- def test__attribute__output_with_block
87
- expected = html <<-EOHTML
88
- <li class="attribute">
89
- <span class="label">Full name</span>
90
- <span class="value">John Doe!!!</span>
91
- </li>
92
- EOHTML
93
-
94
- @user_builder.attribute :full_name do
95
- @user_builder.template.output_buffer << "John Doe"
96
- 3.times do
97
- @user_builder.template.output_buffer << "!"
97
+
98
+ context "with block" do
99
+
100
+ should "yield block" do
101
+ block_run = false
102
+ @user_builder.attribute :full_name do
103
+ block_run = true
104
+ end
105
+ assert block_run
98
106
  end
99
- end
100
- actual = @template.output_buffer.to_s
101
- assert_equal expected, actual
102
- end
103
107
 
104
- def test__attribute__with_block_and_custom_label
105
- expected = html <<-EOHTML
106
- <li class="attribute">
107
- <span class="label">Full name</span>
108
- <span class="value">John Doe!!!</span>
109
- </li>
110
- EOHTML
111
-
112
- @user_builder.attribute :label => "Full name" do
113
- @user_builder.template.output_buffer << "John Doe"
114
- 3.times do
115
- @user_builder.template.output_buffer << "!"
108
+ should "generate output" do
109
+ expected = html <<-EOHTML
110
+ <li class="attribute">
111
+ <span class="label">Full name</span>
112
+ <span class="value">John Doe!!!</span>
113
+ </li>
114
+ EOHTML
115
+
116
+ @user_builder.attribute :full_name do
117
+ @user_builder.template.output_buffer << "John Doe"
118
+ 3.times do
119
+ @user_builder.template.output_buffer << "!"
120
+ end
121
+ end
122
+ actual = @template.output_buffer.to_s
123
+ assert_equal expected, actual
116
124
  end
125
+
126
+ should "show custom label" do
127
+ expected = html <<-EOHTML
128
+ <li class="attribute">
129
+ <span class="label">Full name</span>
130
+ <span class="value">John Doe!!!</span>
131
+ </li>
132
+ EOHTML
133
+
134
+ @user_builder.attribute :label => "Full name" do
135
+ @user_builder.template.output_buffer << "John Doe"
136
+ 3.times do
137
+ @user_builder.template.output_buffer << "!"
138
+ end
139
+ end
140
+ actual = @template.output_buffer.to_s
141
+ assert_equal expected, actual
142
+ end
143
+
117
144
  end
118
- actual = @template.output_buffer.to_s
119
- assert_equal expected, actual
120
145
  end
121
146
 
122
147
  end