hobo_rapid 1.4.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/README.markdown +5 -0
  2. data/VERSION +1 -0
  3. data/app/controllers/dev_controller.rb +25 -0
  4. data/app/helpers/hobo_rapid_helper.rb +197 -0
  5. data/hobo_rapid.gemspec +26 -0
  6. data/lib/hobo_rapid/railtie.rb +6 -0
  7. data/lib/hobo_rapid.rb +13 -0
  8. data/taglibs/buttons/buttons.dryml +1 -0
  9. data/taglibs/buttons/create_button.dryml +40 -0
  10. data/taglibs/buttons/delete-button.dryml +75 -0
  11. data/taglibs/buttons/remote_method_button.dryml +34 -0
  12. data/taglibs/buttons/transition_button.dryml +71 -0
  13. data/taglibs/buttons/transition_link.dryml +22 -0
  14. data/taglibs/buttons/update_button.dryml +29 -0
  15. data/taglibs/cache/cache.dryml +1 -0
  16. data/taglibs/cache/nested_cache.dryml +332 -0
  17. data/taglibs/cards/card.dryml +7 -0
  18. data/taglibs/cards/cards.dryml +1 -0
  19. data/taglibs/cards/search_card.dryml +4 -0
  20. data/taglibs/editors/click_editor.dryml +60 -0
  21. data/taglibs/editors/editors.dryml +27 -0
  22. data/taglibs/editors/live_editor.dryml +37 -0
  23. data/taglibs/forms/error_messages.dryml +21 -0
  24. data/taglibs/forms/form.dryml +101 -0
  25. data/taglibs/forms/formlet.dryml +48 -0
  26. data/taglibs/forms/forms.dryml +5 -0
  27. data/taglibs/forms/submit.dryml +14 -0
  28. data/taglibs/hobo_rapid.dryml +14 -0
  29. data/taglibs/html/a.dryml +156 -0
  30. data/taglibs/html/aside.dryml +5 -0
  31. data/taglibs/html/doctype.dryml +39 -0
  32. data/taglibs/html/empty_tag.dryml +23 -0
  33. data/taglibs/html/footer.dryml +5 -0
  34. data/taglibs/html/header.dryml +5 -0
  35. data/taglibs/html/html.dryml +18 -0
  36. data/taglibs/html/if_ie.dryml +11 -0
  37. data/taglibs/html/image.dryml +11 -0
  38. data/taglibs/html/javascript.dryml +12 -0
  39. data/taglibs/html/section.dryml +12 -0
  40. data/taglibs/html/section_group.dryml +11 -0
  41. data/taglibs/html/stylesheet.dryml +5 -0
  42. data/taglibs/html/table.dryml +174 -0
  43. data/taglibs/i18n/ht.dryml +48 -0
  44. data/taglibs/i18n/human_attribute_name +18 -0
  45. data/taglibs/i18n/human_collection_name.dryml +69 -0
  46. data/taglibs/i18n/i18n.dryml +1 -0
  47. data/taglibs/i18n/model_name_human.dryml +16 -0
  48. data/taglibs/i18n/t.dryml +12 -0
  49. data/taglibs/inputs/after_submit.dryml +32 -0
  50. data/taglibs/inputs/check_many.dryml +25 -0
  51. data/taglibs/inputs/collection_input.dryml +10 -0
  52. data/taglibs/inputs/hidden_field.dryml +48 -0
  53. data/taglibs/inputs/hot_input.dryml +50 -0
  54. data/taglibs/inputs/input.dryml +76 -0
  55. data/taglibs/inputs/input_all.dryml +14 -0
  56. data/taglibs/inputs/input_for.dryml +38 -0
  57. data/taglibs/inputs/input_for_date.dryml +86 -0
  58. data/taglibs/inputs/input_for_enum_string.dryml +26 -0
  59. data/taglibs/inputs/input_many.dryml +131 -0
  60. data/taglibs/inputs/inputs.dryml +1 -0
  61. data/taglibs/inputs/name_one.dryml +74 -0
  62. data/taglibs/inputs/or_cancel.dryml +8 -0
  63. data/taglibs/inputs/select_input.dryml +13 -0
  64. data/taglibs/inputs/select_many.dryml +58 -0
  65. data/taglibs/inputs/select_menu.dryml +23 -0
  66. data/taglibs/inputs/select_one.dryml +46 -0
  67. data/taglibs/inputs/sortable_input_many.dryml +31 -0
  68. data/taglibs/inputs/sti_type_input.dryml +6 -0
  69. data/taglibs/lists/collection.dryml +26 -0
  70. data/taglibs/lists/empty_collection_message.dryml +13 -0
  71. data/taglibs/lists/feckless_fieldset.dryml +94 -0
  72. data/taglibs/lists/field_list.dryml +21 -0
  73. data/taglibs/lists/field_list_v1.dryml +64 -0
  74. data/taglibs/lists/labelled_item_list.dryml +11 -0
  75. data/taglibs/lists/lists.dryml +2 -0
  76. data/taglibs/lists/with_fields.dryml +98 -0
  77. data/taglibs/pages/account.dryml +30 -0
  78. data/taglibs/pages/account_disabled.dryml +19 -0
  79. data/taglibs/pages/flash_message.dryml +23 -0
  80. data/taglibs/pages/forgot_password.dryml +62 -0
  81. data/taglibs/pages/login.dryml +57 -0
  82. data/taglibs/pages/not_found_page.dryml +18 -0
  83. data/taglibs/pages/page_nav.dryml +17 -0
  84. data/taglibs/pages/pages.dryml +12 -0
  85. data/taglibs/pages/permission_denied_page.dryml +24 -0
  86. data/taglibs/plus/collection_preview.dryml +23 -0
  87. data/taglibs/plus/filter_menu.dryml +103 -0
  88. data/taglibs/plus/gravatar.dryml +12 -0
  89. data/taglibs/plus/live_search.dryml +40 -0
  90. data/taglibs/plus/plus.dryml +1 -0
  91. data/taglibs/plus/sortable_collection.dryml +36 -0
  92. data/taglibs/plus/table_plus.dryml +63 -0
  93. data/taglibs/views/a_or_an.dryml +10 -0
  94. data/taglibs/views/collection_name.dryml +28 -0
  95. data/taglibs/views/comma_list.dryml +2 -0
  96. data/taglibs/views/count.dryml +99 -0
  97. data/taglibs/views/links_for_collection.dryml +2 -0
  98. data/taglibs/views/name.dryml +30 -0
  99. data/taglibs/views/nil_view.dryml +10 -0
  100. data/taglibs/views/record_flags.dryml +5 -0
  101. data/taglibs/views/type_name.dryml +24 -0
  102. data/taglibs/views/view.dryml +79 -0
  103. data/taglibs/views/view_for.dryml +42 -0
  104. data/taglibs/views/views.dryml +1 -0
  105. data/taglibs/views/you.dryml +150 -0
  106. data/vendor/assets/javascripts/hobo_rapid.js +1 -0
  107. data/vendor/assets/stylesheets/feckless-fieldset.css +40 -0
  108. data/vendor/assets/stylesheets/hobo-rapid.css +94 -0
  109. data/vendor/assets/stylesheets/hobo_rapid.css +1 -0
  110. metadata +174 -0
@@ -0,0 +1,14 @@
1
+ <!-- This comment shouldn't appear in the cookbook -->
2
+
3
+ <include src="buttons/*"/>
4
+ <include src="cache/*"/>
5
+ <include src="cards/*"/>
6
+ <include src="editors/*"/>
7
+ <include src="forms/*"/>
8
+ <include src="html/*"/>
9
+ <include src="i18n/*"/>
10
+ <include src="inputs/*"/>
11
+ <include src="lists/*"/>
12
+ <include src="pages/*"/>
13
+ <include src="plus/*"/>
14
+ <include src="views/*"/>
@@ -0,0 +1,156 @@
1
+ <!--
2
+ `<a>` is extended in Rapid to automatically provide URLs for Hobo model routes
3
+
4
+ ### Usage
5
+
6
+ The tag behaves as a regular HTML link or anchor if either the href or name attribute is given:
7
+
8
+ <a href="/admin">Admin</a> -> Output is exactly as provided, untouched by Rapid
9
+
10
+ If no href or name is given then the _context_ is used to determine the link URL.
11
+ The helper method `object_url` is used to construct the URL using restful routing:
12
+
13
+ If the context is a class then the link will be an index page:
14
+
15
+ <a with="&BlogPost">My Blog</a> -> <a href="/blog_posts">My Blog</a>
16
+
17
+ If the context is a hobo model instance then the link will be a show page:
18
+
19
+ <% blog_post = BlogPost.find(1) %>
20
+ <a with="&blog_post">My Blog Post</a> -> <a href="/blog_posts/1">My Blog Post</a>
21
+
22
+ An action can be provided for an alternative show page:
23
+
24
+ <a with="&blog_post" action="edit">Edit Post</a> -> <a href="/blog_posts/1/edit">Edit Post</a>
25
+
26
+ Or a new page if the context is a class:
27
+
28
+ <a with="&BlogPost" action="new">New Blog Post</a> -> <a href="/blog_posts/new">New Blog Post</a>
29
+
30
+ ### Additional Features
31
+
32
+ * If the constructed route does not exist then the link will not be created, but the content of the link will still be output. E.g. when `/blog_posts` does not exist (because the hobo model controller does not exist or the index action is disabled):
33
+
34
+ <a with="&BlogPost">My Blog</a> -> My Blog
35
+
36
+ when the show action `/blog_posts/:id` does not exist:
37
+
38
+ <a with="&blog_post">My Blog Post</a> -> My Blog Post
39
+ * If no content text is provided then `<a>` will use the name method on the context to provide the text. E.g.
40
+
41
+ <a with="&blog_post"/> -> <a href="/blog_posts/1">My First Blog Post</a>`
42
+ <a with="&BlogPost"/> -> <a href="/blog_posts">Blog Posts</a>`
43
+ * If `action="new"` then `<a>` will check that the current user has permission to create the object
44
+ * Several useful classes are added automatically to the output `<a>`.
45
+
46
+ ### AJAX
47
+
48
+ The standard AJAX form attributes are supported. This can be used for conventional Ajax:
49
+
50
+ <a href="&refresh_path" update="results">Refresh results</a>
51
+
52
+ Or it can be used with push-state to provide faster links:
53
+
54
+ <a href="somewhere/else" update="body" push-state new-title="Somewhere else">Go somewhere else.</a>
55
+
56
+ In this case the entire body is being refreshed but the headers
57
+ aren't, so will work to link between two dissimilar pages as long as
58
+ the headers are identical.
59
+
60
+ AJAX attributes are supported in both modes: in the "magic" mode where
61
+ RAPID determines the href target or in "passthrough" where you supply
62
+ the href or name.
63
+
64
+ ### Attributes
65
+
66
+ The standard AJAX attributes are supported.
67
+
68
+ * action: If "new", triggers the special behaviour listed above. Otherwise, contains the action to be performed on the context. If neither `action` nor `method` are specified, the action will be "index" or "show", as appropriate.
69
+
70
+ * to: Use this item as the target instead of the current context.
71
+
72
+ * params: These are appended to the target as a query string after a "?". Params are passed as a ruby hash. Example: `params="&{id=>17, name=>'joe'}"`
73
+
74
+ * query-params: if set, current query parameters are mirrored onto the link. If true or blank, all non-ajax query parameters are used. (`query-params`, `query-params="&true"` or `query-params=""`) Otherwise, the specified query parameters are used. (`query-params="page,sort,search"`)
75
+
76
+ * href, name: If either of these attributes are present, the smart features of this tag are turned off.
77
+
78
+ * format: this adds ".#{format}" to the end of the url
79
+
80
+ * subsite: routes the URL using the subsite
81
+
82
+ * force: overrides the permission check if `action` is "new"
83
+
84
+ * method: "get", "put", "post" or "delete". "get" is the default
85
+
86
+ -->
87
+ <def tag="a" attrs="action, to, params, query-params, href, format, subsite, force"><%=
88
+ content = parameters.default
89
+
90
+ ajax_attrs, attributes = attributes.partition_hash(HoboRapidHelper::AJAX_ATTRS)
91
+ unless ajax_attrs.blank?
92
+ add_data_rapid!(attributes, "a", :ajax_attrs => ajax_attrs)
93
+ end
94
+
95
+
96
+ if query_params
97
+ if query_params==true || query_params.blank?
98
+ query_params = query_parameters_filtered
99
+ else
100
+ query_params = query_parameters_filtered(:only => comma_split(query_params))
101
+ end
102
+ params = query_params.merge(params || HashWithIndifferentAccess.new)
103
+ end
104
+
105
+ if href || attributes[:name]
106
+ # Regular link
107
+ href += "?" + params.map { |n, v| "#{n}=#{v}" }.join('&') if !params.blank?
108
+ element(:a, attributes.update(:href => href), content)
109
+ else
110
+ target = to || this
111
+
112
+ if target.nil?
113
+ Dryml.last_if = false
114
+ nil_view
115
+ elsif action == "new"
116
+ # Link to a new object form
117
+ new_record = target.new
118
+ new_record.set_creator(current_user)
119
+ href = object_url(target, "new", params._?.merge(:subsite => subsite))
120
+
121
+ if href && (force || can_create?(new_record))
122
+ new_class_name = if target.respond_to?(:proxy_reflection)
123
+ target.proxy_association.reflection.klass.name
124
+ else
125
+ target.name
126
+ end
127
+
128
+ add_classes!(attributes, "new-#{new_class_name.underscore}-link")
129
+ content = "New #{new_class_name.titleize}" if content.blank?
130
+ Dryml.last_if = true
131
+ element(:a, attributes.update(:href => href), content)
132
+ else
133
+ Dryml.last_if = false
134
+ ""
135
+ end
136
+ else
137
+ # Link to an existing object
138
+
139
+ content = name if content.blank?
140
+
141
+ href = object_url(target, action, (params || {}).merge(:subsite => subsite)) unless (action.nil? && target.try.new_record?)
142
+ if href.nil?
143
+ # This target is registered with Hobo::Routes as not linkable
144
+ content
145
+ else
146
+ css_class = target.try.origin_attribute || target.class.name.underscore.dasherize
147
+ add_classes!(attributes, "#{css_class}-link")
148
+
149
+ href.sub!(/\?|$/, ".#{format}\\0") unless format.blank?
150
+
151
+ # Set default link text if none given
152
+ element(:a, attributes.update(:href => href), content)
153
+ end
154
+ end
155
+ end
156
+ %></def>
@@ -0,0 +1,5 @@
1
+ <!-- A proposed HTML 5 semantic tag. Outputs `<div class="aside">` and works in the same way as `<section>` with empty content. -->
2
+ <def tag="aside" attrs="empty">
3
+ <set body="&parameters.default"/>
4
+ <div class="aside" merge-attrs if="&!body.blank? || empty"><%= body %></div>
5
+ </def>
@@ -0,0 +1,39 @@
1
+ <!-- Renders one of five HTML DOCTYPE declarations, according to the `version` attribute.
2
+
3
+ ### Attributes
4
+ - 'version' - the doctype version, must be one of:
5
+
6
+ - HTML 4.01 STRICT
7
+ - HTML 4.01 TRANSITIONAL
8
+ - XHTML 1.0 STRICT
9
+ - XHTML 1.0 TRANSITIONAL
10
+ - XHTML 1.1
11
+ - HTML
12
+ - html
13
+ - HTML5
14
+ - html5
15
+
16
+ See the source for the actual output
17
+
18
+ -->
19
+ <def tag="doctype" attrs="version"><%=raw(
20
+ case version.upcase
21
+ when "HTML 4.01 STRICT"
22
+ '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" ' +
23
+ '"http://www.w3.org/TR/html4/strict.dtd">'
24
+ when "HTML 4.01 TRANSITIONAL"
25
+ '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ' +
26
+ '"http://www.w3.org/TR/html4/loose.dtd">'
27
+ when "XHTML 1.0 STRICT"
28
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' +
29
+ '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
30
+ when "XHTML 1.0 TRANSITIONAL"
31
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ' +
32
+ '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
33
+ when "XHTML 1.1"
34
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" ' +
35
+ '"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
36
+ when "HTML", "html", "HTML5", "html5"
37
+ '<!DOCTYPE html>'
38
+ end)
39
+ %></def>
@@ -0,0 +1,23 @@
1
+ <!-- empty tags should be written as <br> in HTML and <br /> in XHTML -->
2
+ <!-- nodoc. -->
3
+ <def tag="empty-tag" attrs="tag-name"><%= element(tag_name, attributes, nil, true, true) %></def>
4
+ <!-- nodoc. -->
5
+ <def tag="base"><empty-tag tag-name="base" merge/></def>
6
+ <!-- nodoc. -->
7
+ <def tag="meta"><empty-tag tag-name="meta" merge/></def>
8
+ <!-- nodoc. -->
9
+ <def tag="link"><empty-tag tag-name="link" merge/></def>
10
+ <!-- nodoc. -->
11
+ <def tag="img"><empty-tag tag-name="img" merge/></def>
12
+ <!-- nodoc. -->
13
+ <def tag="br"><empty-tag tag-name="br" merge/></def>
14
+ <!-- nodoc. -->
15
+ <def tag="hr"><empty-tag tag-name="hr" merge/></def>
16
+ <!-- nodoc. -->
17
+ <def tag="frame"><empty-tag tag-name="frame" merge/></def>
18
+ <!-- nodoc. -->
19
+ <def tag="area"><empty-tag tag-name="area" merge/></def>
20
+ <!-- nodoc. -->
21
+ <def tag="param"><empty-tag tag-name="param" merge/></def>
22
+ <!-- nodoc. -->
23
+ <def tag="col"><empty-tag tag-name="col" merge/></def>
@@ -0,0 +1,5 @@
1
+ <!-- A proposed HTML 5 semantic tag. Outputs `<div class="footer">` and works in the same way as `<section>` with empty content. -->
2
+ <def tag="footer" attrs="empty">
3
+ <set body="&parameters.default"/>
4
+ <div class="footer" merge-attrs if="&!body.blank? || empty"><%= body %></div>
5
+ </def>
@@ -0,0 +1,5 @@
1
+ <!-- A proposed HTML 5 semantic tag. Outputs `<div class="header">` and works in the same way as `<section>` with empty content. -->
2
+ <def tag="header" attrs="empty">
3
+ <set body="&parameters.default"/>
4
+ <div class="header" merge-attrs if="&!body.blank? || empty"><%= body %></div>
5
+ </def>
@@ -0,0 +1,18 @@
1
+ <!-- Standard HTML tags that have been enhanced in RAPID, as well as
2
+ closely related tags -->
3
+
4
+
5
+ <!-- Renders an `<html>` tag along with the DOCTYPE specified in the `doctype` attribute.
6
+
7
+ ### Attributes
8
+
9
+ - `doctype` - the version of the DOCTYPE required. See the `version` attribute to `<doctype>`
10
+ -->
11
+ <def tag="html" attrs="doctype">
12
+ <% doctype ||= 'html' -%>
13
+ <doctype version="&doctype"/>
14
+ <% attributes.reverse_merge!(:xmlns => "http://www.w3.org/1999/xhtml") if doctype.upcase =~ /^XHTML/ -%>
15
+ <%=raw "<html#{tag_options(attributes, true)}>" %>
16
+ <set-scoped xmldoctype="&doctype.upcase =~ /^XHTML/"><do param="default"/></set-scoped>
17
+ <%=raw "</html>" %>
18
+ </def>
@@ -0,0 +1,11 @@
1
+ <!-- Renders a conditional comment in order to have some content ignored by all browsers other than Internet Explorer
2
+
3
+ ### Example
4
+
5
+
6
+ <if-ie version="lt IE 7"> ... </if-ie>
7
+
8
+ -->
9
+ <def tag="if-ie" attrs="version">
10
+ <%=raw "<!--[if #{version || 'IE'}]>" %><do param="default"/><%=raw "<![endif]-->" %>
11
+ </def>
@@ -0,0 +1,11 @@
1
+ <!--
2
+ Provides a short hand way of displaying images. All attributes supported by `image_tag` are supported.
3
+
4
+ ### Usage
5
+
6
+ <image src="hobo.png"/> -> <img src="/images/hobo.png"/>
7
+ <image src="blog/funny.jpg" alt="Funny Scene"/> -> <img src="/images/blog/funny.jpg" alt="Funny Scene"/>
8
+ -->
9
+ <def tag="image" attrs="src"><%=
10
+ image_tag(src, Hash[deunderscore_attributes(attributes)])
11
+ %></def>
@@ -0,0 +1,12 @@
1
+ <!-- Simple wrapper for the `javascript_include_tag` helper. The `name` attribute can be a comma-separated list of script file names.
2
+ -->
3
+ <def tag="javascript" attrs="name">
4
+ <if test="&name.is_a?(Symbol)">
5
+ <%= javascript_include_tag name %>
6
+ </if>
7
+ <else>
8
+ <repeat with="&comma_split(name)">
9
+ <%= javascript_include_tag this %>
10
+ </repeat>
11
+ </else>
12
+ </def>
@@ -0,0 +1,12 @@
1
+ <!-- A proposed HTML 5 tag for representing a generic document or application section. Slightly more semantic than `<div>` for indicating document structure. For the time being, `<section>` is output as `<div class="section">`. In Hobo, `<section>` also has one other important behaviour which is different to using `<div>` directly, when the content of the section is empty, the wrapper tag will disappear. e.g.
2
+
3
+ <section>My Section</section> -> <div class="section">My Section</div>
4
+ <section><%# empty %></section> -> (nothing is generated)
5
+ -->
6
+ <def tag="section" attrs="empty, with-flash-messages">
7
+ <set body="&parameters.default" flash="&with_flash_messages && !scope.flash_rendered"/>
8
+ <div class="section #{'with-flash' if flash}" merge-attrs if="&!body.blank? || empty || flash">
9
+ <flash-messages if="&flash"/>
10
+ <%= body %>
11
+ </div>
12
+ </def>
@@ -0,0 +1,11 @@
1
+ <!-- Used as a semantic wrapper around a group of sections and asides. CSS layouts can be provided based on this structure.
2
+
3
+ ### Usage
4
+
5
+ <section-group>
6
+ <section>My First Section</section>
7
+ <section>My Second Section</section>
8
+ <aside>My Aside</aside>
9
+ </section-group>
10
+ -->
11
+ <def tag="section-group"><div class="section-group"><div class="section-group-inner" merge-attrs param="default"></div></div></def>
@@ -0,0 +1,5 @@
1
+ <!-- Simple wrapper for the `stylesheet_link_tag` helper. The `name` attribute can be a comma-separated list of stylesheet names.
2
+ -->
3
+ <def tag="stylesheet" attrs="name">
4
+ <%= stylesheet_link_tag *(comma_split(name) + [deunderscore_attributes(attributes)]) %>
5
+ </def>
@@ -0,0 +1,174 @@
1
+ <!--
2
+ `<table>` is extended in Rapid to provide a shorthand way to output a set of fields for a given collection. This is enabled using the `field` attribute (without the `field` attribute this is just the regular HTML `<table>` tag)
3
+
4
+ ### Usage
5
+
6
+ If the context is an array of blog posts...
7
+
8
+ <table fields="name, created_at, description"/>
9
+
10
+ This will output a header row containing "Name", "Created At" and "Description" followed by a row for each record in the collection. By default, the `<view/>` tag is called for each field in the row. This can be altered with the `field-tag` attribute, e.g.
11
+
12
+ <table fields="name, created_at, description" field-tag="input"/>
13
+
14
+ This will use `<input/>` as the tag in each table cell instead of `<view/>`
15
+
16
+ ### Additional Notes
17
+
18
+ * `<table>` provides parameters based on the names of the fields which can be used to further customise the output. For each field a heading parameter is provided, e.g. name-heading, created-at-heading, description-heading. These can be used to customise the headings:
19
+
20
+ <table fields="name, created_at, description">
21
+ <created-at-heading:>Creation Date</created-at-heading:>
22
+ </table>
23
+ * Similarly, "view" parameters are provided as an additional way to customise the table cells of the table body, e.g. `name-view`, `created-at-view`, `description-view`:
24
+
25
+ <table fields="name, created_at, description">
26
+ <created-at-view:><view format="%d %B %Y"/></created-at-view:>
27
+ </table>
28
+ * By adding an empty `control` parameter, the default control column is enable adding an edit link and delete button for each table row:
29
+
30
+ <table fields="name, created_at, description">
31
+ <controls:/>
32
+ </table>
33
+
34
+ The controls can be further customised using the "edit-link" and "delete-button" parameters:
35
+
36
+ <table fields="name, created_at, description">
37
+ <controls:/>
38
+ <delete-button: label="Nuke Me"/>
39
+ </table>
40
+
41
+ or by providing completely new content for the control column:
42
+
43
+ <table fields="name, created_at, description">
44
+ <controls:>my controls!</controls:>
45
+ </table>
46
+
47
+ ### Using table without ActiveRecord
48
+
49
+ Typical usage for table is to supply the results of an ActiveRecord query as the context. However, it is possible to supply a more generic array as the context instead.
50
+
51
+ #### using the tr parameter
52
+
53
+ If you use the tr parameter you can pass pretty much anything in the array, since you then are supplying the formatting for the row. Giving:
54
+
55
+ <table with="&[1,2,3]">
56
+ <thead:><tr><th>Heading</th></tr></thead:>
57
+ <tr:><td><%= this+7 %></td></tr:>
58
+ </table>
59
+
60
+ Produces:
61
+
62
+ <table>
63
+ <thead>
64
+ <tr><th>Heading</th></tr>
65
+ </thead>
66
+ <tbody>
67
+ <tr class='odd fixnum'><td>8</td></tr>
68
+ <tr class='even fixnum'><td>9</td></tr>
69
+ <tr class='odd fixnum'><td>10</td></tr>
70
+ </tbody>
71
+ </table>
72
+
73
+ #### using OpenStruct
74
+
75
+ If you supply an array of generic objects, you can supply method names to fields and `<table>` will produce a valid table. The only major difference from passing ActiveRecord objects is that this mechanism will not translate table headings.
76
+
77
+ If you've got a Hash, you can use OpenStruct to make the data available via methods. Giving:
78
+
79
+ <% require 'ostruct' %>
80
+ {: .hidden}
81
+
82
+ <table fields="a,b" with="&[OpenStruct.new(:a => 1, :b => 2), OpenStruct.new(:a => 3, :b => 4)]">
83
+ <a-heading:>A</a-heading:>
84
+ <b-heading:>B</b-heading:>
85
+ </table>
86
+
87
+ Produces:
88
+
89
+ <table>
90
+ <thead>
91
+ <tr class='field-heading-row'>
92
+ <th class='a-heading'>A</th>
93
+ <th class='b-heading'>B</th>
94
+ </tr>
95
+ </thead>
96
+ <tbody>
97
+ <tr class='odd open_struct'>
98
+ <td class='a-view'><span class='view '>1</span></td>
99
+ <td class='b-view'><span class='view '>2</span></td>
100
+ </tr>
101
+ <tr class='even open_struct'>
102
+ <td class='a-view'><span class='view '>3</span></td>
103
+ <td class='b-view'><span class='view '>4</span></td>
104
+ </tr>
105
+ </tbody>
106
+ </table>
107
+
108
+ #### without the magic
109
+
110
+ If you don't use either the fields attribute or the tr parameter, all processing is turned off, and your table is emitted verbatim. Giving:
111
+
112
+ <table>
113
+ <thead>
114
+ <tr><th>a</th></tr>
115
+ </thead>
116
+ <tbody>
117
+ <tr><td>b</td></tr>
118
+ </tbody>
119
+ </table>
120
+
121
+ Will emit the above table verbatim.
122
+
123
+ Produces:
124
+ {: .hidden}
125
+
126
+ <table>
127
+ <thead>
128
+ <tr><th>a</th></tr>
129
+ </thead>
130
+ <tbody>
131
+ <tr><td>b</td></tr>
132
+ </tbody>
133
+ </table>
134
+ {: .hidden}
135
+ -->
136
+ <def tag="table" attrs="fields, field-tag, empty">
137
+ <if test="&!(fields || all_parameters.tr?)">
138
+ <%= element("table", attributes, all_parameters.default) %>
139
+ </if>
140
+ <else>
141
+ <% field_tag ||= "view" %>
142
+ <unless test="&this.empty? && !empty">
143
+ <%= element "table", attributes - attrs_for(:with_fields) do %>
144
+ <thead if="&all_parameters[:thead] || fields" param>
145
+ <tr param="field-heading-row">
146
+ <with-field-names merge-attrs="&all_attributes & attrs_for(:with_fields)">
147
+ <th param="#{scope.field_name}-heading"><%= this.member_class ? this.member_class.human_attribute_name(scope.field_name) : scope.field_name.to_s.titleize %></th>
148
+ </with-field-names>
149
+ <th if="&all_parameters[:controls]" class="controls"/>
150
+ </tr>
151
+ </thead>
152
+ <tbody param>
153
+ <repeat>
154
+ <tr param if="&can_view?"
155
+ class="#{scope.even_odd} #{this_type.name.underscore}" data-rapid-context="&typed_id">
156
+ <if test="&fields">
157
+ <with-fields merge-attrs="&all_attributes & attrs_for(:with_fields)" force-all>
158
+ <td param="#{scope.field_name.to_s.sub('?', '').gsub('.', '-')}-view"><call-tag tag="&field_tag"/></td>
159
+ </with-fields>
160
+ <td class="controls" param="controls" if="&all_parameters[:controls]">
161
+ <a param="edit-link" action="edit" if="&can_edit?">
162
+ <t key="hobo.actions.edit_control">Edit</t>
163
+ </a>
164
+ <delete-button param/>
165
+ </td>
166
+ </if>
167
+ </tr>
168
+ </repeat>
169
+ </tbody>
170
+ <tfoot if="&all_parameters[:tfoot]" param/>
171
+ <% end %>
172
+ </unless>
173
+ </else>
174
+ </def>
@@ -0,0 +1,48 @@
1
+ <!--
2
+ Wrapper around the Rails :translate helper with hobo added features.
3
+
4
+ It can be used as a regular helper or as a dryml tag.
5
+
6
+ ### Hobo Added Features
7
+
8
+ `ht` adds some conventions for easier hobo translation.
9
+
10
+ 1. Assumes the first part of the key to be a model name (e.g.: users.index.title -> user)
11
+ 2. Tries to translate the model by lookup for: (e.g.: user-> activerecord.models.user)
12
+ 3. Adds a default fallback to the beginning of the fallback chain by replacing the first part of the key with "hobo" and using the translated model name as additional attribute. This allows us to have default translations (e.g.: hobo.index.title: "{{model}} Index")
13
+
14
+ You can also pass any other :translate option like for example :count.
15
+
16
+ Is also used as a tag in the dryml-view files. The syntax is:
17
+
18
+ <ht key="my.app">My Application</ht>
19
+
20
+ Will lookup the "my.app"-key for your locale and replaces the "My Application" content if found.
21
+
22
+ <ht key="my" app="Program">My Application</ht>
23
+
24
+ Will look up both the "my"- and "app"-key for your locale, and replaces the "My Application" with the "my"-key contents (interpolated using the "app"-key.
25
+
26
+ sample.no.yml-file:
27
+
28
+ "no":
29
+ my: "Mitt {{app}}"
30
+
31
+ The output should be: Mitt Program
32
+
33
+ Another example:
34
+
35
+ <%= ht :key=>'user.index.title', :default=>'Index' %>
36
+ <ht key="user.index.title">Index</ht>
37
+ #=> "Index" # if "user.index.title" or "hobo.index.title" is not found
38
+ #=> "User Index" # with the below en.yml file
39
+
40
+ === en.yml ===
41
+ en:
42
+ hobo:
43
+ index:
44
+ title: %{model} Index
45
+ -->
46
+ <fakedef tag="ht">
47
+ <!-- actually defined in translations.rb -->
48
+ </fakedef>
@@ -0,0 +1,18 @@
1
+ <!-- Wrapper around ActiveRecord::Base.human_attribute_name.
2
+
3
+ #### Attributes
4
+
5
+ - attribute - the attribute to lookup
6
+ - model - (optional) should be a model class or a record object (default to this)
7
+ - count - (optional) should be an integer
8
+
9
+ -->
10
+ <def tag="human-attribute-name" attrs="attribute, model"><%=
11
+ model ||= this
12
+ model = model.class unless model.kind_of? Class
13
+ # prepare symbolized attributes for merging
14
+ attrs = {}
15
+ all_attributes.each_pair{|k,v| attrs[k.to_sym] = v}
16
+ model.human_attribute_name( attribute.to_sym, attrs )
17
+ %>
18
+ </def>
@@ -0,0 +1,69 @@
1
+ <!-- Used to localize and pluralize collection names.
2
+ A collection name is a special case of an attribute name, (indeed you should store the collection names as attribute names in the locale files), so this tag internally uses human_attribute_name to return them.
3
+
4
+ With the `your` attribute and in the special case the context is a Hobo::Model::UserMixin instance it automatically embeds the `your` tag funtionality. (note: :name is added by default as an interpolable variable)
5
+
6
+ ### Attributes
7
+
8
+ - collection - the attribute/collection key to lookup in the `activerecord.attributes` namespace. (e.g. 'roles')
9
+ - count - used to pick the inflected string for the collection. It should be an integer.
10
+ - your - wraps the collection name in a `Your` tag
11
+
12
+ ### Example
13
+
14
+
15
+ it:
16
+ activerecord:
17
+ attributes:
18
+ post:
19
+ comments:
20
+ one: "Commento"
21
+ other: "Commenti"
22
+ user:
23
+ roles:
24
+ one: "Ruolo"
25
+ other: "Ruoli"
26
+ tags:
27
+ your:
28
+ roles:
29
+ current_user:
30
+ one: "Il tuo Ruolo"
31
+ other: "I tuoi Ruoli"
32
+ other_user:
33
+ one: "Ruolo di {{name}}"
34
+ other: Ruoli di {{name}}"
35
+
36
+ context is a Post instance ('your' is ignored)
37
+
38
+ <human-collection-name collection="comments" count="&user.comments.count" your/>
39
+ I18n.locale = :en => "Comment" or "Comments"
40
+ I18n.locale = :it => "Commento" or "Commenti"
41
+
42
+ context is a User instance
43
+
44
+ <human-collection-name collection="roles' count="&user.roles.count" your/>
45
+ I18n.locale = :en => "Your Role" or "Jim's Role" or "Your Roles" or "Jim's Roles"
46
+ I18n.locale = :it => "Il tuo Ruolo" or "Il Ruolo di Jim" or "I tuoi Ruoli" or "I Ruoli di Jim"
47
+
48
+ (output is the same as `<Your key="roles" count=>"&user.roles.count"/>`)
49
+
50
+ <human-collection-name collection="roles" count="&user.roles.count"/>
51
+ I18n.locale = :en => "Role" or "Roles"
52
+ I18n.locale = :it => "Ruolo" or "Ruoli"
53
+ -->
54
+ <def tag="human-collection-name" attrs="collection, count, your"><%
55
+ raise Hobo::Error, "The 'collection' attribute must be defined" if collection.blank?
56
+ belong_class = this.kind_of?(Class) ? this : this.class
57
+ raise Hobo::Error, "The context is not an ActiveRecord::Base instance or class. (this = #{this.typed_id rescue this.inspect})" unless belong_class < ActiveRecord::Base
58
+ # prepare symbolized attributes for merging
59
+ attrs = {}
60
+ all_attributes.each_pair{|k,v| attrs[k.to_sym] = v} -%>
61
+ <% if your && belong_class < Hobo::Model::UserBase && this.kind_of?(Hobo::Model::UserBase) && I18n.locale == :en -%>
62
+ <your key="&collection" merge-attrs="&{:name=>name(:no_wrapper => true)}.merge(attrs)" capitalize>
63
+ <%= belong_class.human_attribute_name(collection.to_sym, attrs) %>
64
+ </your>
65
+ <% else -%>
66
+ <%= belong_class.human_attribute_name( collection.to_sym, attrs ) %>
67
+ <% end %>
68
+ </def>
69
+
@@ -0,0 +1 @@
1
+ <!-- Rapid i18n provides tags related with the Rails-I18n project -->