attrtastic 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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