attrtastic 0.2.2 → 0.3.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/.gitignore +4 -20
- data/Gemfile +4 -0
- data/Gemfile.lock +50 -0
- data/LICENSE +1 -1
- data/README.md +16 -13
- data/Rakefile +6 -36
- data/attrtastic.gemspec +20 -76
- data/doc/Attrtastic/SemanticAttributesBuilder.html +340 -347
- data/doc/Attrtastic/SemanticAttributesHelper.html +100 -66
- data/doc/Attrtastic.html +29 -12
- data/doc/_index.html +9 -9
- data/doc/class_list.html +3 -3
- data/doc/css/full_list.css +6 -3
- data/doc/css/style.css +51 -9
- data/doc/file.README.html +21 -18
- data/doc/file_list.html +1 -1
- data/doc/frames.html +1 -1
- data/doc/index.html +21 -18
- data/doc/js/app.js +107 -4
- data/doc/js/full_list.js +78 -35
- data/doc/js/jquery.js +150 -15
- data/doc/method_list.html +7 -7
- data/doc/top-level-namespace.html +9 -6
- data/init.rb +2 -0
- data/lib/attrtastic/semantic_attributes_builder.rb +333 -0
- data/lib/attrtastic/semantic_attributes_helper.rb +55 -0
- data/lib/attrtastic/version.rb +3 -0
- data/lib/attrtastic.rb +2 -389
- data/rails/init.rb +1 -2
- data/test/helper.rb +2 -2
- data/test/test_attribute.rb +3 -5
- data/test/test_attributes.rb +26 -54
- data/test/test_attrtastic.rb +9 -8
- data/test/test_semantic_attributes_helper.rb +5 -8
- metadata +97 -32
- data/VERSION +0 -1
data/lib/attrtastic.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "attrtastic/semantic_attributes_helper"
|
2
|
+
require "attrtastic/semantic_attributes_builder"
|
1
3
|
##
|
2
4
|
# Attrtastic, in its assumption, should be similar to formtastic and
|
3
5
|
# ease displaying AR informations, help create scaffolded show and index
|
@@ -5,394 +7,5 @@
|
|
5
7
|
#
|
6
8
|
# @author Boruta Mirosław
|
7
9
|
module Attrtastic
|
8
|
-
|
9
|
-
class SemanticAttributesBuilder
|
10
|
-
|
11
|
-
# Only for testing purposes
|
12
|
-
attr_reader :record, :template
|
13
|
-
|
14
|
-
def initialize(record, template)
|
15
|
-
@record, @template = record, template
|
16
|
-
end
|
17
|
-
|
18
|
-
##
|
19
|
-
# Creates block of attributes with optional header. Attributes are surrounded with ordered list.
|
20
|
-
#
|
21
|
-
# @overload attributes(options = {}, &block)
|
22
|
-
# Creates attributes list without header, yields block to include each attribute
|
23
|
-
#
|
24
|
-
# @param [Hash] options Options for formating attributes block
|
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
|
28
|
-
# @yield Block which can call #attribute to include attribute value
|
29
|
-
#
|
30
|
-
# @example
|
31
|
-
# <% attr.attributes do %>
|
32
|
-
# <%= attr.attribute :name %>
|
33
|
-
# <%= attr.attribute :email %>
|
34
|
-
# <% end %>
|
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
|
-
#
|
72
|
-
# @overload attributes(header, options = {}, &block)
|
73
|
-
# Creates attributes list with header and yields block to include each attribute
|
74
|
-
#
|
75
|
-
# @param [String] header Header of attributes section
|
76
|
-
# @param [Hash] options Options for formating attributes block
|
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.
|
82
|
-
# @yield Block which can call #attribute to include attribute value
|
83
|
-
# @yieldparam builder Builder instance holding actual record (retivable via #record)
|
84
|
-
#
|
85
|
-
# @example
|
86
|
-
# <% attr.attributes "User info" do %>
|
87
|
-
# <%= attr.attribute :name" %>
|
88
|
-
# <%= attr.attribute :email %>
|
89
|
-
# <% end %>
|
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
|
-
#
|
121
|
-
# @overload attributes(*symbols, options = {})
|
122
|
-
# Creates attributes list without header, attributes are given as list of symbols (record properties)
|
123
|
-
#
|
124
|
-
# @param [Symbol, ...] symbols List of attributes
|
125
|
-
# @param [Hash] options Options for formating attributes block
|
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
|
129
|
-
#
|
130
|
-
# @example
|
131
|
-
# <% attr.attributes :name, :email %>
|
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
|
-
#
|
145
|
-
# @overload attributes(header, *symbols, options = {})
|
146
|
-
# Creates attributes list with header, attributes are given as list of symbols (record properties)
|
147
|
-
#
|
148
|
-
# @param [String] header Header of attributes section
|
149
|
-
# @param [Symbol, ...] symbols Optional list of attributes
|
150
|
-
# @param [Hash] options Options for formating attributes block
|
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
|
153
|
-
#
|
154
|
-
# @example
|
155
|
-
# <% attr.attributes "User info" :name, :email %>
|
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
|
-
#
|
169
|
-
# @example All together
|
170
|
-
# <% attr.attributes "User info", :name, :email, :class => "user_info", :header_class => "header important" %>
|
171
|
-
#
|
172
|
-
# @example With block
|
173
|
-
# <% attr.attributes "User info" :class => "user_info", :header_class => "header important" do %>
|
174
|
-
# <%= attr.attribute :name %>
|
175
|
-
# <%= attr.attribute :email %>
|
176
|
-
# <% end %>
|
177
|
-
#
|
178
|
-
# @see #attribute
|
179
|
-
def attributes(*args, &block)
|
180
|
-
options = {}
|
181
|
-
if args.last and args.last.kind_of? Hash
|
182
|
-
options = args.last
|
183
|
-
args = args[0 .. -2]
|
184
|
-
end
|
185
|
-
options[:html] ||= {}
|
186
|
-
|
187
|
-
if args.first and args.first.is_a? String
|
188
|
-
options[:name] = args.shift
|
189
|
-
end
|
190
|
-
|
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
|
-
value_options = options.clone
|
202
|
-
value_options[:html][:class] = [ options[:html][:class], value.class.to_s.underscore ].compact.join(" ")
|
203
|
-
|
204
|
-
attributes_for(value, args, options, &block)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
end
|
209
|
-
|
210
|
-
##
|
211
|
-
# Creates list entry for single record attribute
|
212
|
-
#
|
213
|
-
# @overload attribute(method, options = {})
|
214
|
-
# Creates entry for record attribute
|
215
|
-
#
|
216
|
-
# @param [Symbol] method Attribute name of given record
|
217
|
-
# @param [Hash] options Options
|
218
|
-
# @option options [Hash] :html ({}) Hash with optional :class, :label_class and :value_class names of class for html
|
219
|
-
# @option options [String] :label Label for attribute entry, overrides default label name from symbol
|
220
|
-
# @option options [String] :value Value of attribute entry, overrides default value from record
|
221
|
-
# @option options [Boolean] :display_empty (false) Indicates if print value of given attribute even if it is blank?
|
222
|
-
#
|
223
|
-
# @example
|
224
|
-
# <%= attr.attribute :name %>
|
225
|
-
#
|
226
|
-
# @example
|
227
|
-
# <%= attr.attribute :name, :label => "Full user name" %>
|
228
|
-
#
|
229
|
-
# @example
|
230
|
-
# <%= attr.attribute :name, :value => @user.full_name %>
|
231
|
-
#
|
232
|
-
# @overload attribute(method, options = {}, &block)
|
233
|
-
# Creates entry for attribute given with block
|
234
|
-
#
|
235
|
-
# @param [Symbol] method Attribute name of given record
|
236
|
-
# @param [Hash] options Options
|
237
|
-
# @option options [Hash] :html ({}) Hash with optional :class, :label_class and :value_class names of classes for html
|
238
|
-
# @option options [String] :label Label for attribute entry, overrides default label name from symbol
|
239
|
-
# @yield Block which is executed in place of value for attribute
|
240
|
-
#
|
241
|
-
# @example
|
242
|
-
# <% attr.attribute :name do %>
|
243
|
-
# <%= link_to @user.full_name, user_path(@user) %>
|
244
|
-
#
|
245
|
-
# @overload attribute(options = {}, &block)
|
246
|
-
# Creates entry for attribute with given block, options[:label] is mandatory in this case.
|
247
|
-
#
|
248
|
-
# @param [:Hash] options Options
|
249
|
-
# @option options [Hash] :html ({}) Hash with optional :class, :label_class and :value_class names of classes for html
|
250
|
-
# @option options [String] :label Mandatory label for attribute entry
|
251
|
-
# @yield Block which is executed in place of value for attribute
|
252
|
-
#
|
253
|
-
# @example
|
254
|
-
# <% attr.attribute :label => "User link" do %>
|
255
|
-
# <%= link_to @user.full_name, user_path(@user) %>
|
256
|
-
#
|
257
|
-
# @example
|
258
|
-
# <%= attr.attribute :name, :display_empty => true %>
|
259
|
-
#
|
260
|
-
# @example
|
261
|
-
# <% attr.attribute :label => "User link" do %>
|
262
|
-
# <%= link_to @user.full_name, user_path(@user) %>
|
263
|
-
#
|
264
|
-
def attribute(*args, &block)
|
265
|
-
options = {}
|
266
|
-
if args.last and args.last.kind_of? Hash
|
267
|
-
options = args.last
|
268
|
-
args = args[0 .. -2]
|
269
|
-
end
|
270
|
-
options[:html] ||= {}
|
271
|
-
|
272
|
-
method = args.shift
|
273
|
-
|
274
|
-
html_label_class = [ "label", options[:html][:label_class] ].compact.join(" ")
|
275
|
-
html_value_class = [ "value", options[:html][:value_class] ].compact.join(" ")
|
276
|
-
html_class = [ "attribute", options[:html][:class] ].compact.join(" ")
|
277
|
-
|
278
|
-
label = options.key?(:label) ? options[:label] : label_for_attribute(method)
|
279
|
-
label_content = template.content_tag(:span, label, :class => html_label_class)
|
280
|
-
|
281
|
-
unless block_given?
|
282
|
-
value = options.key?(:value) ? options[:value] : value_of_attribute(method)
|
283
|
-
value_content = template.content_tag(:span, value, :class => html_value_class)
|
284
|
-
|
285
|
-
if value.present? or options[:display_empty]
|
286
|
-
content = [ label_content, value_content ].join
|
287
|
-
template.content_tag(:li, content, :class => html_class)
|
288
|
-
end
|
289
|
-
else
|
290
|
-
template.concat(template.tag(:li, {:class => html_class}, true))
|
291
|
-
template.concat(label_content)
|
292
|
-
template.concat(template.tag(:span, {:class => html_value_class}, true))
|
293
|
-
yield
|
294
|
-
template.concat("</span>")
|
295
|
-
template.concat("</li>")
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
private
|
300
|
-
|
301
|
-
def attributes_for(object, methods, options, &block)
|
302
|
-
new_builder = self.class.new(object, template)
|
303
|
-
|
304
|
-
html_class = [ "attributes", options[:html].delete(:class) ].compact.join(" ")
|
305
|
-
html_header_class = [ "legend", options[:html].delete(:header_class) ].compact.join(" ")
|
306
|
-
|
307
|
-
template.concat(template.tag(:div, {:class => html_class}, true))
|
308
|
-
|
309
|
-
header = options[:name]
|
310
|
-
|
311
|
-
if header.present?
|
312
|
-
template.concat(template.content_tag(:div, header, :class => html_header_class))
|
313
|
-
end
|
314
|
-
|
315
|
-
if block_given?
|
316
|
-
template.concat(template.tag(:ol, {}, true))
|
317
|
-
yield(new_builder)
|
318
|
-
template.concat("</ol>")
|
319
|
-
elsif methods.present?
|
320
|
-
template.concat(template.tag(:ol, {}, true))
|
321
|
-
attrs = methods.map {|method| new_builder.attribute(method, options)}.compact.join
|
322
|
-
template.concat(attrs)
|
323
|
-
template.concat("</ol>")
|
324
|
-
end
|
325
|
-
|
326
|
-
template.concat("</div>")
|
327
|
-
end
|
328
|
-
|
329
|
-
def label_for_attribute(method)
|
330
|
-
if record.class.respond_to?(:human_attribute_name)
|
331
|
-
record.class.human_attribute_name(method.to_s)
|
332
|
-
else
|
333
|
-
method.to_s.send(:humanize)
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
def value_of_attribute(method)
|
338
|
-
value = record.send(method)
|
339
|
-
value_methods = [ :to_label, :display_name, :full_name, :name, :title, :username, :login, :value ]
|
340
|
-
value_method = value_methods.find { |m| value.respond_to?(m) } || :to_s
|
341
|
-
value.send(value_method)
|
342
|
-
end
|
343
|
-
|
344
|
-
end
|
345
|
-
|
346
|
-
##
|
347
|
-
# Helper which should be included in ActionView. Adds #semantic_attributes_for
|
348
|
-
# method, which helps printing attributes for given record, similar to
|
349
|
-
# formtastic's sematnic_form_for
|
350
|
-
#
|
351
|
-
# @example
|
352
|
-
# ActionView::Base.send :include, Attrtastic::SemanticAttributesHelper
|
353
|
-
#
|
354
|
-
# @example Example of useage
|
355
|
-
# <% semantic_attributes_for @user do |attr| %>
|
356
|
-
# <% attr.attributes "User info" do %>
|
357
|
-
# <%= attr.attribute :name %>
|
358
|
-
# <%= attr.attribute :email %>
|
359
|
-
# <% end %>
|
360
|
-
# <% attr.attributes "User details" do %>
|
361
|
-
# <%= attr.attribute :weight %>
|
362
|
-
# <%= attr.attribute :height %>
|
363
|
-
# <%= attr.attribute :age %>
|
364
|
-
# <% end %>
|
365
|
-
# <% end %>
|
366
|
-
module SemanticAttributesHelper
|
367
|
-
|
368
|
-
##
|
369
|
-
# Creates attributes for given object
|
370
|
-
#
|
371
|
-
# @param[ActiveRecord] record AR instance record for which to display attributes
|
372
|
-
# @param[Hash] options Opions
|
373
|
-
# @option options [Hash] :html ({}) Hash with optional :class html class name for html block
|
374
|
-
# @yield [attr] Block which is yield inside of markup
|
375
|
-
# @yieldparam [SemanticAttributesBuilder] builder Builder for attributes for given AR record
|
376
|
-
#
|
377
|
-
# @example
|
378
|
-
# <% semantic_attributes_for @user do |attr| %>
|
379
|
-
# <% attr.attributes do %>
|
380
|
-
# <%= attr.attribute :name %>
|
381
|
-
# <%= attr.attribute :email %>
|
382
|
-
# <% end %>
|
383
|
-
# <% end %>
|
384
|
-
#
|
385
|
-
def semantic_attributes_for(record, options = {}, &block)
|
386
|
-
options[:html] ||= {}
|
387
|
-
|
388
|
-
html_class = [ "attrtastic", record.class.to_s.underscore, options[:html][:class] ].compact.join(" ")
|
389
|
-
|
390
|
-
concat(tag(:div, { :class => html_class}, true))
|
391
|
-
yield SemanticAttributesBuilder.new(record, self) if block_given?
|
392
|
-
concat("</div>")
|
393
|
-
end
|
394
|
-
|
395
|
-
end
|
396
|
-
|
397
10
|
end
|
398
11
|
|
data/rails/init.rb
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__),
|
2
|
-
ActionView::Base.send :include, Attrtastic::SemanticAttributesHelper
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "init"))
|
data/test/helper.rb
CHANGED
@@ -6,7 +6,7 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
6
6
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
7
|
require 'attrtastic'
|
8
8
|
|
9
|
-
class Test::Unit::TestCase
|
9
|
+
class TestCase < Test::Unit::TestCase
|
10
10
|
def html(string)
|
11
11
|
string.split(/\n/m).map(&:strip).join
|
12
12
|
end
|
@@ -22,7 +22,7 @@ class Test::Unit::TestCase
|
|
22
22
|
]
|
23
23
|
|
24
24
|
ActionView::Base.send :include, Attrtastic::SemanticAttributesHelper
|
25
|
-
@template = ActionView::Base.new.tap{ |av| av.output_buffer =
|
25
|
+
@template = ActionView::Base.new.tap{ |av| av.output_buffer = ActiveSupport::SafeBuffer.new }
|
26
26
|
@user_builder = Attrtastic::SemanticAttributesBuilder.new(@user, @template)
|
27
27
|
@blog_builder = Attrtastic::SemanticAttributesBuilder.new(@blog, @template)
|
28
28
|
end
|
data/test/test_attribute.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
class TestAttribute <
|
3
|
+
class TestAttribute < TestCase
|
4
4
|
|
5
5
|
context "attribute" do
|
6
6
|
|
@@ -113,13 +113,12 @@ class TestAttribute < Test::Unit::TestCase
|
|
113
113
|
</li>
|
114
114
|
EOHTML
|
115
115
|
|
116
|
-
@user_builder.attribute :full_name do
|
116
|
+
actual = @user_builder.attribute :full_name do
|
117
117
|
@user_builder.template.output_buffer << "John Doe"
|
118
118
|
3.times do
|
119
119
|
@user_builder.template.output_buffer << "!"
|
120
120
|
end
|
121
121
|
end
|
122
|
-
actual = @template.output_buffer.to_s
|
123
122
|
assert_equal expected, actual
|
124
123
|
end
|
125
124
|
|
@@ -131,13 +130,12 @@ class TestAttribute < Test::Unit::TestCase
|
|
131
130
|
</li>
|
132
131
|
EOHTML
|
133
132
|
|
134
|
-
@user_builder.attribute :label => "Full name" do
|
133
|
+
actual = @user_builder.attribute :label => "Full name" do
|
135
134
|
@user_builder.template.output_buffer << "John Doe"
|
136
135
|
3.times do
|
137
136
|
@user_builder.template.output_buffer << "!"
|
138
137
|
end
|
139
138
|
end
|
140
|
-
actual = @template.output_buffer.to_s
|
141
139
|
assert_equal expected, actual
|
142
140
|
end
|
143
141
|
|