hobo 1.3.0.pre31 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES-1.1.txt +5253 -0
- data/CHANGES.txt +255 -5095
- data/VERSION +1 -1
- data/hobo.gemspec +1 -2
- data/lib/generators/hobo/admin_subsite/USAGE +25 -0
- data/lib/generators/hobo/admin_subsite/admin_subsite_generator.rb +2 -1
- data/lib/generators/hobo/assets/USAGE +5 -0
- data/lib/generators/hobo/assets/templates/application.dryml.erb +1 -1
- data/lib/generators/hobo/controller/USAGE +3 -0
- data/lib/generators/hobo/i18n/USAGE +3 -0
- data/lib/generators/hobo/i18n/templates/app.fr.yml +26 -0
- data/lib/generators/hobo/i18n/templates/app.nb.yml +25 -0
- data/lib/generators/hobo/i18n/templates/hobo.de.yml +1 -0
- data/lib/generators/hobo/i18n/templates/hobo.en.yml +3 -2
- data/lib/generators/hobo/i18n/templates/hobo.es.yml +1 -0
- data/lib/generators/hobo/i18n/templates/hobo.fr.yml +195 -0
- data/lib/generators/hobo/i18n/templates/hobo.it.yml +1 -0
- data/lib/generators/hobo/i18n/templates/hobo.nb.yml +198 -0
- data/lib/generators/hobo/i18n/templates/hobo.pt-PT.yml +1 -0
- data/lib/generators/hobo/i18n/templates/hobo.ru.yml +1 -0
- data/lib/generators/hobo/model/USAGE +2 -2
- data/lib/generators/hobo/rapid/templates/hobo-rapid.js +15 -30
- data/lib/generators/hobo/rapid/templates/themes/clean/public/stylesheets/clean.css +1 -0
- data/lib/generators/hobo/resource/USAGE +39 -0
- data/lib/generators/hobo/routes/router.rb +2 -2
- data/lib/generators/hobo/setup_wizard/setup_wizard_generator.rb +23 -9
- data/lib/generators/hobo/subsite.rb +13 -2
- data/lib/generators/hobo/subsite/USAGE +24 -0
- data/lib/generators/hobo/subsite_taglib/USAGE +4 -0
- data/lib/generators/hobo/subsite_taglib/templates/taglib.dryml.erb +1 -1
- data/lib/generators/hobo/test_framework/USAGE +2 -0
- data/lib/generators/hobo/user_controller/USAGE +3 -0
- data/lib/generators/hobo/user_controller/templates/controller.rb.erb +3 -0
- data/lib/generators/hobo/user_mailer/USAGE +2 -0
- data/lib/generators/hobo/user_model/USAGE +2 -9
- data/lib/generators/hobo/user_resource/USAGE +10 -0
- data/lib/hobo.rb +1 -1
- data/lib/hobo/controller/authentication_support.rb +0 -22
- data/lib/hobo/controller/model.rb +15 -13
- data/lib/hobo/controller/{user.rb → user_base.rb} +43 -32
- data/lib/hobo/extensions/action_controller/hobo_methods.rb +25 -1
- data/lib/hobo/extensions/active_record/associations/collection.rb +12 -3
- data/lib/hobo/extensions/active_record/associations/reflection.rb +1 -1
- data/lib/hobo/extensions/active_record/relation_with_origin.rb +4 -0
- data/lib/hobo/helper.rb +6 -1
- data/lib/hobo/helper/translations.rb +1 -1
- data/lib/hobo/model.rb +55 -19
- data/lib/hobo/model/lifecycles.rb +3 -3
- data/lib/hobo/model/lifecycles/lifecycle.rb +7 -3
- data/lib/hobo/model/permissions.rb +1 -0
- data/lib/hobo/model/scopes/automatic_scopes.rb +0 -2
- data/lib/hobo/model/view_hints.rb +1 -0
- data/lib/hobo/rapid/generators/rapid/forms.dryml.erb +2 -1
- data/lib/hobo/rapid/generators/rapid/pages.dryml.erb +10 -11
- data/lib/hobo/rapid/helper.rb +4 -3
- data/lib/hobo/rapid/taglibs/rapid_core.dryml +92 -67
- data/lib/hobo/rapid/taglibs/rapid_editing.dryml +35 -15
- data/lib/hobo/rapid/taglibs/rapid_forms.dryml +46 -22
- data/lib/hobo/rapid/taglibs/rapid_i18n.dryml +103 -37
- data/lib/hobo/rapid/taglibs/rapid_lifecycles.dryml +3 -1
- data/lib/hobo/rapid/taglibs/rapid_pages.dryml +3 -3
- data/lib/hobo/rapid/taglibs/rapid_plus.dryml +49 -45
- data/test/irt/generators/partials/_subsite_taglib_variables.rb +1 -1
- metadata +38 -33
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
|
14
14
|
<% each_controller do -%>
|
15
|
-
|
15
|
+
<% next unless @controller < Hobo::Controller::Model %>
|
16
16
|
<!-- ====== <%= model.name %> Pages ====== -->
|
17
17
|
<%
|
18
18
|
new_link = linkable?(:new)
|
@@ -124,11 +124,10 @@ end
|
|
124
124
|
|
125
125
|
unless model.view_hints.secondary_children.empty?
|
126
126
|
aside_collections = model.view_hints.secondary_children.map { |c| [model.reflections[c], model.reverse_reflection(c)] }
|
127
|
-
aside_collections.reject! { |refl, reverse| reverse.nil? }
|
128
127
|
end
|
129
128
|
-%>
|
130
129
|
<def tag="show-page" for="<%= model.name %>">
|
131
|
-
<page merge title="#{ht '<%=model_key %>.show.title', :default=>['<%=sq_escape model_name %>'] }">
|
130
|
+
<page merge title="#{ht '<%=model_key %>.show.title', :default=>['<%=sq_escape model_name %>'], :name => name(:no_wrapper => true) }">
|
132
131
|
|
133
132
|
<body: class="show-page <%= model_class %>" param/>
|
134
133
|
|
@@ -142,8 +141,8 @@ end
|
|
142
141
|
<a:<%= back_link %> param="parent-link">« <ht key="<%= model_key %>.actions.back_to_parent" parent="<%= back_link_human_name %>" name="&this">Back to <name/></ht></a:<%= back_link %>>
|
143
142
|
<% end -%>
|
144
143
|
<h2 param="heading">
|
145
|
-
<ht key="<%= model_key %>.show.heading" name="
|
146
|
-
<name/>
|
144
|
+
<ht key="<%= model_key %>.show.heading" name="#{name(:no_wrapper => true)}">
|
145
|
+
<%= model_name %> <name/>
|
147
146
|
</ht>
|
148
147
|
</h2>
|
149
148
|
<% if boolean_fields -%>
|
@@ -160,7 +159,7 @@ end
|
|
160
159
|
<% if edit_link -%>
|
161
160
|
|
162
161
|
<a action="edit" if="&can_edit?" param="edit-link">
|
163
|
-
<ht key="<%= model_key %>.actions.edit" name="
|
162
|
+
<ht key="<%= model_key %>.actions.edit" name="#{name(:no_wrapper => true)}">
|
164
163
|
Edit <%= model_name %>
|
165
164
|
</ht>
|
166
165
|
</a>
|
@@ -169,7 +168,7 @@ end
|
|
169
168
|
|
170
169
|
<section param="content-body">
|
171
170
|
<% if main_content -%>
|
172
|
-
<view:<%= main_content %> param="description"/>
|
171
|
+
<view:<%= main_content %> param="description" />
|
173
172
|
<% end -%>
|
174
173
|
<% if show_fields.any? -%>
|
175
174
|
<field-list fields="<%= show_fields * ', ' %>" param/>
|
@@ -216,7 +215,7 @@ end
|
|
216
215
|
|
217
216
|
<aside param>
|
218
217
|
<% for refl, reverse_refl in aside_collections -%>
|
219
|
-
<% if linkable?(refl.klass, :"index_for_#{reverse_refl.name}") -%>
|
218
|
+
<% if reverse_refl && linkable?(refl.klass, :"index_for_#{reverse_refl.name}") -%>
|
220
219
|
<collection-preview:<%= refl.name %>.recent param="<%= refl.name %>-preview">
|
221
220
|
<heading-content:><human-collection-name with="&this.origin" collection="<%= refl.name %>" your/></heading-content:>
|
222
221
|
</collection-preview:<%= refl.name %>.recent>
|
@@ -244,14 +243,14 @@ end
|
|
244
243
|
name_attribute = model.name_attribute
|
245
244
|
-%>
|
246
245
|
<def tag="edit-page" for="<%= model.name %>">
|
247
|
-
<page merge title="#{ht '<%= model_key %>.edit.title', :default=>['Edit <%= sq_escape model_name %>'] }">
|
246
|
+
<page merge title="#{ht '<%= model_key %>.edit.title', :default=>['Edit <%= sq_escape model_name %>'], :name => name(:no_wrapper => true) }">
|
248
247
|
|
249
248
|
<body: class="edit-page <%= model_class %>" param/>
|
250
249
|
|
251
250
|
<content:>
|
252
251
|
<section param="content-header">
|
253
252
|
<h2 param="heading">
|
254
|
-
<ht key="<%= model_key %>.edit.heading" name="
|
253
|
+
<ht key="<%= model_key %>.edit.heading" name="#{name(:no_wrapper => true)}">
|
255
254
|
Edit <%= model_name %>
|
256
255
|
</ht>
|
257
256
|
</h2>
|
@@ -314,7 +313,7 @@ new_link = :new.in?(actions)
|
|
314
313
|
|
315
314
|
<section param="content-body">
|
316
315
|
<% if new_link -%>
|
317
|
-
<a action="new" to="
|
316
|
+
<a action="new" to="&@<%= owner %>.<%= collection_name %>" param="new-link">
|
318
317
|
<ht key="<%= model_key %>.actions.new" >New <%=model_name %></ht>
|
319
318
|
</a>
|
320
319
|
|
data/lib/hobo/rapid/helper.rb
CHANGED
@@ -120,15 +120,16 @@ module Hobo
|
|
120
120
|
edit_text = this._?.to_s
|
121
121
|
attributes.update(:hobo_edit_text => edit_text) unless edit_text.nil?
|
122
122
|
|
123
|
-
update = attributes.delete(:update)
|
124
|
-
|
123
|
+
if update = attributes.delete(:update)
|
124
|
+
attributes = add_classes(attributes, update_elements_class(update))
|
125
|
+
end
|
125
126
|
|
126
127
|
view(attributes)
|
127
128
|
end
|
128
129
|
|
129
130
|
|
130
131
|
|
131
|
-
AJAX_CALLBACKS = [ :
|
132
|
+
AJAX_CALLBACKS = [ :success, :failure, :complete ]
|
132
133
|
|
133
134
|
AJAX_ATTRS = AJAX_CALLBACKS + [ :update, :type, :method,
|
134
135
|
:script, :form, :params, :confirm, :message,
|
@@ -93,7 +93,15 @@ This will use `<input/>` as the tag in each table cell instead of `<view/>`
|
|
93
93
|
<table fields="name, created_at, description">
|
94
94
|
<controls:/>
|
95
95
|
</table>
|
96
|
-
|
96
|
+
|
97
|
+
The controls can be further customised using the "edit-link" and "delete-button" parameters:
|
98
|
+
|
99
|
+
<table fields="name, created_at, description">
|
100
|
+
<controls:/>
|
101
|
+
<delete-button: label="Nuke Me"/>
|
102
|
+
</table>
|
103
|
+
|
104
|
+
or by providing completely new content for the control column:
|
97
105
|
|
98
106
|
<table fields="name, created_at, description">
|
99
107
|
<controls:>my controls!</controls:>
|
@@ -124,7 +132,9 @@ This will use `<input/>` as the tag in each table cell instead of `<view/>`
|
|
124
132
|
<td param="#{scope.field_name.to_s.sub('?', '').gsub('.', '-')}-view"><call-tag tag="&field_tag"/></td>
|
125
133
|
</with-fields>
|
126
134
|
<td class="controls" param="controls" if="&all_parameters[:controls]">
|
127
|
-
<a param="edit-link" action="edit" if="&can_edit?"
|
135
|
+
<a param="edit-link" action="edit" if="&can_edit?">
|
136
|
+
<t key="hobo.actions.edit_control">Edit</t>
|
137
|
+
</a>
|
128
138
|
<delete-button param/>
|
129
139
|
</td>
|
130
140
|
</if>
|
@@ -157,24 +167,35 @@ Provides a short hand way of displaying images in public/images
|
|
157
167
|
|
158
168
|
|
159
169
|
<!-- Renders some standard JavaScript code that various features of the Rapid library rely on. This tag would typicallu be called from your `<page>` tag. The default Rapid pages include this already. -->
|
160
|
-
<def tag="hobo-rapid-javascripts"
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
170
|
+
<def tag="hobo-rapid-javascripts">
|
171
|
+
<script type="text/javascript" param="default"><%=
|
172
|
+
res = 'var hoboParts = {};'
|
173
|
+
# FIXME: This should interrogate the model-router - not the models
|
174
|
+
unless Hobo::Model.all_models.empty?
|
175
|
+
# Tell JS code how to pluralize names, unless they follow the simple rule
|
176
|
+
names = Hobo::Model.all_models.map do |m|
|
177
|
+
m = m.name.underscore
|
178
|
+
"#{m}: '#{m.pluralize}'" unless m.pluralize == m + 's'
|
179
|
+
end.compact
|
180
|
+
res << "var pluralisations = {#{names * ', '}}; "
|
181
|
+
end
|
182
|
+
base = [base_url, subsite].compact.join("/")
|
183
|
+
res << "urlBase = '#{base}'; hoboPagePath = '#{request.fullpath}'"
|
184
|
+
if protect_against_forgery?
|
185
|
+
res << "; formAuthToken = { name: '#{request_forgery_protection_token}', value: '#{form_authenticity_token}' }"
|
186
|
+
end
|
187
|
+
res
|
188
|
+
%></script>
|
189
|
+
</def>
|
190
|
+
|
191
|
+
|
192
|
+
<def tag="part-contexts-javascripts">
|
193
|
+
<% unless (storage = part_contexts_storage).blank? %>
|
194
|
+
<script type="text/javascript"><%=
|
195
|
+
storage
|
196
|
+
%></script>
|
197
|
+
<% end %>
|
198
|
+
</def>
|
178
199
|
|
179
200
|
<!-- Renders the name of the current context using a variety of methods.
|
180
201
|
|
@@ -445,7 +466,7 @@ Assuming the context is a blog post...
|
|
445
466
|
|
446
467
|
truncate = 30 if truncate == true
|
447
468
|
the_view = self.truncate(the_view, :length => truncate.to_i) if truncate
|
448
|
-
the_view = the_view.strip
|
469
|
+
the_view = the_view.html_safe? ? the_view.strip.html_safe : the_view.strip
|
449
470
|
|
450
471
|
if no_wrapper
|
451
472
|
the_view
|
@@ -483,12 +504,14 @@ Assuming the context is a blog post...
|
|
483
504
|
<!-- Renders localized `number_with_delimiter this`, or `format % this` if the `format` attribute is given -->
|
484
505
|
<def tag="view" for="Numeric" attrs="format"><%= format ? format % this : number_with_delimiter(this) %></def>
|
485
506
|
|
486
|
-
<!--
|
507
|
+
<!-- If `this.html_safe?`, returns this unchanged. Otherwise renders `this` with HTML escaping and newlines replaced with `<br>` tags -->
|
487
508
|
<def tag="view" for="string"><%=
|
488
|
-
if
|
509
|
+
if this.html_safe?
|
510
|
+
this
|
511
|
+
elsif !(this.class == String) && this.respond_to?(:to_html) # workaround for Maruku which adds String#to_html : (
|
489
512
|
this.to_html(scope.xmldoctype)
|
490
513
|
else
|
491
|
-
h(this).gsub("\n", "<br#{scope.xmldoctype ? ' /' : ''}>")
|
514
|
+
h(this).gsub("\n", "<br#{scope.xmldoctype ? ' /' : ''}>").html_safe
|
492
515
|
end
|
493
516
|
%></def>
|
494
517
|
|
@@ -513,10 +536,9 @@ The label can be customised using the `label` attribute, e.g.
|
|
513
536
|
<count:comments label="blog post comment"/> -> <span class="count">12 blog post comments</span>
|
514
537
|
|
515
538
|
You can pass a summary attribute, which will generate a complete localized sentence. It allows 2 options:
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
If the lookup fails, it will fallback to the english default sentences consistent with the count.
|
539
|
+
|
540
|
+
- boolean (e.g. `<count summary/>`): it will lookup the 'tags.count.default' key in the locale file. If the lookup fails, it will fallback to the english default sentences consistent with the count.
|
541
|
+
- String (e.g. `<count summary="offer"/>`): it will lookup the 'tags.count.offer' key in the locale file. If the lookup fails, it will fallback to the english default sentences consistent with the count.
|
520
542
|
|
521
543
|
### Examples
|
522
544
|
|
@@ -532,18 +554,22 @@ You can pass a summary attribute, which will generate a complete localized sente
|
|
532
554
|
one: "Puoi scegliere solo una {{label}}"
|
533
555
|
other: "Puoi scegliere tra {{count}} {{label}}"
|
534
556
|
|
535
|
-
|
557
|
+
with :en locale and boolean summary (internal defaults)
|
558
|
+
|
536
559
|
<count:comments summary/> -> <span class="count">There is 1 Comment</span>
|
537
560
|
<count:viewings summary/> -> <span class="count">There are 3 Viewings</span>
|
538
|
-
(note: just add the locale english strings to use like the following examples)
|
539
561
|
|
540
|
-
|
562
|
+
(note: just add the locale english strings to use like the following examples)
|
563
|
+
|
564
|
+
with :it locale and boolean summary (key "tags.count.default")
|
565
|
+
|
541
566
|
<count:comments summary/>
|
542
567
|
-> count => 0 -> <span class="count">Non ci sono Commenti</span>
|
543
568
|
-> count => 1 -> <span class="count">C'è solo 1 Commento</span>
|
544
569
|
-> count => 5 -> <span class="count">Ci sono 5 Commenti</span>
|
545
570
|
|
546
|
-
|
571
|
+
with :it locale and summary="choice" (key "tags.count.choice")
|
572
|
+
|
547
573
|
<count:comments summary="choice"/>
|
548
574
|
-> count => 0 -> <span class="count">Non ci sono Commenti da scegliere</span>
|
549
575
|
-> count => 1 -> <span class="count">Puoi scegliere solo 1 Commento</span>
|
@@ -596,6 +622,8 @@ You can pass a summary attribute, which will generate a complete localized sente
|
|
596
622
|
end
|
597
623
|
%></span></def>
|
598
624
|
|
625
|
+
<!-- Equivalent to `<you capitalize/>`-->
|
626
|
+
<def tag="You"><you merge capitalize/></def>
|
599
627
|
|
600
628
|
<!-- Renders a `<link rel="Stylesheet" type="text/css">` to include the default stylesheet for the selected theme (select with `<set-theme>`). Included in the default pages.
|
601
629
|
-->
|
@@ -611,9 +639,9 @@ You can pass a summary attribute, which will generate a complete localized sente
|
|
611
639
|
|
612
640
|
The context should be a user object. If `this == current_user` the "you" form is rendered, otherwise the form with the user's name:
|
613
641
|
|
614
|
-
|
615
|
-
|
616
|
-
|
642
|
+
- `<you have/> new mail` -> "you have new mail" or "Jim has new mail"
|
643
|
+
- `<you are/> now an admin` -> "you are now an admin" or "Jim is now an admin"
|
644
|
+
- `<you do/>n't want to go there` -> "you don't want to go there" or "Jim doesn't want to go there"
|
617
645
|
|
618
646
|
The tag is also localized in the namespaces "tags.you.current_user" and "tags.you.other_user".
|
619
647
|
Each namespace can contain the legacy keys "have", "are", "do" used for the respective attributes,
|
@@ -636,15 +664,15 @@ that you add the keys in the correct namespaces.
|
|
636
664
|
are: "{{name}} è"
|
637
665
|
can: "{{name}} può"
|
638
666
|
|
639
|
-
|
640
|
-
|
641
|
-
|
667
|
+
- `<you have/> un nuovo messaggio.` -> "Hai un nuovo messaggio." or "Jim ha un nuovo messaggio."
|
668
|
+
- `Adesso <you are/> amministratore.` -> "Adesso sei amministratore." or "Adesso Jim è amministratore."
|
669
|
+
- `<you can/> scrivere.` -> "Puoi scrivere." or "Jim può scrivere."
|
642
670
|
|
643
671
|
(note: :name is added by default as an interpolable variable)
|
644
672
|
|
645
673
|
### Attributes
|
646
674
|
|
647
|
-
|
675
|
+
- capitalize: the first letter of the resulting sentence will be capitalized
|
648
676
|
|
649
677
|
|
650
678
|
### Additional Notes
|
@@ -666,36 +694,36 @@ The "titleize" attribute is deprecated: use "capitalize" instead.
|
|
666
694
|
</if>
|
667
695
|
<else>
|
668
696
|
<do param="default">
|
669
|
-
<%= s = t("tags.you.other_user.#{k || attributes.keys.first || 'default'}", :name=>
|
670
|
-
:default=>"#{
|
697
|
+
<%= s = t("tags.you.other_user.#{k || attributes.keys.first || 'default'}", :name=>name(:no_wrapper => true),
|
698
|
+
:default=>"#{name(:no_wrapper => true)} #{'has' if attributes[:have]}#{'is' if attributes[:are]}#{'does' if attributes[:do]}")
|
671
699
|
(titleize||capitalize) ? s.sub(/^./){|c| c.upcase} : s %>
|
672
700
|
</do>
|
673
701
|
</else>
|
674
702
|
</def>
|
675
703
|
|
676
|
-
<!-- Equivalent to `<
|
677
|
-
<def tag="
|
704
|
+
<!-- Equivalent to `<your ... capitalize/>`-->
|
705
|
+
<def tag="Your"><your merge capitalize/></def>
|
678
706
|
|
679
707
|
<!-- Similar to `<you>`, but renders "Your" or "Fred's" or equivalent localized strings
|
680
708
|
|
681
709
|
### Attributes
|
682
710
|
|
683
|
-
|
684
|
-
|
685
|
-
|
711
|
+
- capitalize: the first letter of the resulting sentence will be capitalized
|
712
|
+
- count: used in pluralization. If omitted it will be set to 1.
|
713
|
+
- key: used to lookup the translation in the locale file. It allows 3 different options:
|
686
714
|
- single key like 'message': simple translation in 'tags.your.message.current_user'
|
687
715
|
or 'tags.your.message.other_user'
|
688
716
|
- composite key like 'any.namespace.message': translation as for the previous case, but it will
|
689
|
-
translate also the 'any.namespace.message' and will interpolate the variable
|
717
|
+
translate also the 'any.namespace.message' and will interpolate the variable `<key>` (in this case :message)
|
690
718
|
in the translation
|
691
719
|
- when key is omitted it will be set to "default" and will do the translation with that key.
|
692
720
|
Pass other meaningful attributes to achieve a dynamic usage
|
693
|
-
|
721
|
+
- any other attribute passed to the tag will be used as a variable for interpolation
|
694
722
|
|
695
723
|
Notes
|
696
724
|
|
697
|
-
|
698
|
-
|
725
|
+
- The :name variable is added by default as an interpolable variable
|
726
|
+
- If no translation is found an automatic (only english) default is generated:
|
699
727
|
the Your/Jim's string, joined to the tag content.
|
700
728
|
If you pass an explicit 'default' attribute you will override the automatic default.
|
701
729
|
|
@@ -718,24 +746,25 @@ Notes
|
|
718
746
|
other: "Tue {{entry}}"
|
719
747
|
other_user: "{{entry}} di {{name}}"
|
720
748
|
|
721
|
-
|
722
|
-
-> count => 1 -> "Tuo Messaggio" or "Messaggio di Jim"
|
723
|
-
-> count => 5 -> "Tuoi Messaggi" or "Messaggi di Jim"
|
749
|
+
- `<your key="message" count=>"&messages.count"/>`:
|
724
750
|
|
725
|
-
-
|
726
|
-
|
727
|
-
-> count => 5 -> "Tue Entrate" or "Entrate di Jim"
|
751
|
+
- count => 1: "Tuo Messaggio" or "Messaggio di Jim"
|
752
|
+
- count => 5: "Tuoi Messaggi" or "Messaggi di Jim"
|
728
753
|
|
729
|
-
|
730
|
-
|
754
|
+
- `<your key="activerecord.models.entry" count=>"&this.entries.count"/>`:
|
755
|
+
|
756
|
+
- count => 1: "Tua Entrata" or "Entrata di Jim"
|
757
|
+
- count => 5: "Tue Entrate" or "Entrate di Jim"
|
731
758
|
|
759
|
+
- `<your>Posts</your>`: "your Posts" or "Jim's Posts"
|
760
|
+
-->
|
732
761
|
<def tag="your" attrs="key, capitalize"><%=
|
733
762
|
key ||= 'default'
|
734
763
|
# prepare symbolized attributes for merging
|
735
764
|
attrs = {}
|
736
765
|
attributes.each_pair{|k,v| attrs[k.to_sym] = v}
|
737
766
|
d = "#{your_default} #{all_parameters.default}"
|
738
|
-
options = {:default=>[d], :count=>(attrs[:count]||1), :name=>
|
767
|
+
options = {:default=>[d], :count=>(attrs[:count]||1), :name=>name(:no_wrapper => true)}
|
739
768
|
your_key = key.split('.').last
|
740
769
|
unless key.eql?(your_key) || attrs.has_key?(your_key.to_sym)
|
741
770
|
options[your_key.to_sym] = t(key, :count=>options[:count], :default=>your_key.titleize)
|
@@ -750,8 +779,10 @@ Notes
|
|
750
779
|
capitalize ? s.sub(/^./){|c| c.upcase} : s
|
751
780
|
%></def>
|
752
781
|
|
753
|
-
<!--
|
754
|
-
<def tag="
|
782
|
+
<!-- Capitalised version of `<a-or-an>` -->
|
783
|
+
<def tag="A-or-An" attrs="word"><%=
|
784
|
+
(word =~ /^[aeiou]/i ? "An " : "A ") + word
|
785
|
+
%></def>
|
755
786
|
|
756
787
|
<!-- Deprecated. It's harder than you think to do this (e.g. an umbrealla, an user)
|
757
788
|
-->
|
@@ -760,12 +791,6 @@ Notes
|
|
760
791
|
%></def>
|
761
792
|
|
762
793
|
|
763
|
-
<!-- Capitalised version of `<a-or-an>` -->
|
764
|
-
<def tag="A-or-An" attrs="word"><%=
|
765
|
-
(word =~ /^[aeiou]/i ? "An " : "A ") + word
|
766
|
-
%></def>
|
767
|
-
|
768
|
-
|
769
794
|
<!-- Renders a collection of string joined with ", ", or some other string passed in the `join` attribute -->
|
770
795
|
<def tag="comma-list" attrs="join"><%= this.join(join || ", ") %></def>
|
771
796
|
|
@@ -81,25 +81,45 @@ This tag does not sanitize HTML; this is provided by HtmlString before saving to
|
|
81
81
|
|
82
82
|
### Attributes
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
-
|
89
|
-
|
90
|
-
|
84
|
+
- `include-none` - whether to include a 'none' option (i.e. set the foreign key to null). If this value is not supplied, the default is "true" if the current value is nil; otherwise the default is "false". One implication of this is that the default may change when the form is re-rendered due to a validation failure. Setting this value explicitly is recommended.
|
85
|
+
- `blank-message` - the message for the 'none' option. Defaults to "(No `<model-name>`)", e.g. "(No Product)"
|
86
|
+
- `options` - an array of records to include in the menu. Defaults to the all the records in the target table that match any `:conditions` declared on the `belongs_to` (subject to `limit`)
|
87
|
+
- `sort` - whether to sort the array of options. Defaults to no sorting.
|
88
|
+
- `limit` - if `options` is not specified, this limits the number of records. Default: 100
|
89
|
+
- `text_method` - The method to call on each record to get the text for the option. Multiple methods are supported ie "institution.name"
|
90
|
+
- `update` - one or more DOM ID's (comma separated string or an array) to be updated as part of the ajax call.
|
91
91
|
|
92
92
|
NOTE: yes that's *DOM ID's* not part-names. A common source of confusion because by default the part name and DOM ID are the same.
|
93
93
|
|
94
94
|
-->
|
95
|
-
<def tag="select-one-editor" attrs="include-none, blank-message, sort,
|
95
|
+
<def tag="select-one-editor" attrs="include-none, blank-message, options, sort, limit, text-method, update"><%
|
96
96
|
raise Hobo::Error.new("Not allowed to edit") unless can_edit?
|
97
97
|
blank_message ||= ht("#{this_type.name.to_s.underscore}.select_one_editor.blank_message", :count => 0, :default => "(No #{this_type.name.to_s.titleize})")
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
98
|
+
limit ||= 100
|
99
|
+
|
100
|
+
if options.blank? || !options.first.respond_to?(:first)
|
101
|
+
options ||= begin
|
102
|
+
conditions = ActiveRecord::Associations::BelongsToAssociation.new(this_parent, this_field_reflection).send(:conditions)
|
103
|
+
order = this_field_reflection.klass.default_order
|
104
|
+
this_field_reflection.klass.all(:conditions => conditions, :limit => limit, :order => order).select {|x| can_view?(x)}
|
105
|
+
end
|
106
|
+
|
107
|
+
id_method = this_field_reflection.options[:primary_key] || this_field_reflection.klass.primary_key
|
108
|
+
if text_method.nil?
|
109
|
+
select_options = options.map { |x| [name(:with => x, :no_wrapper => true), x.send(id_method)] }
|
110
|
+
else
|
111
|
+
select_options = options.map do |x|
|
112
|
+
[ text_method.split(".").inject(x) { |v, method| v.send(method) },
|
113
|
+
x.send(id_method) ]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
else
|
117
|
+
# handle the old style, where options could be passed an options_for_select style array
|
118
|
+
select_options = options
|
119
|
+
end
|
120
|
+
select_options = select_options.sort if sort
|
121
|
+
select_options.insert(0, [blank_message, ""]) if include_none || (this.nil? && include_none != false)
|
122
|
+
|
103
123
|
f = ajax_updater(object_url(this_parent, :method => :put),
|
104
124
|
update,
|
105
125
|
:method => "put",
|
@@ -108,7 +128,7 @@ This tag does not sanitize HTML; this is provided by HtmlString before saving to
|
|
108
128
|
} })
|
109
129
|
%>
|
110
130
|
<select onchange="#{f}" merge-attrs>
|
111
|
-
<%= options_for_select(
|
131
|
+
<%= options_for_select(select_options, this ? this.send(id_method) : "") %>
|
112
132
|
</select>
|
113
133
|
</def>
|
114
134
|
|
@@ -216,7 +236,7 @@ This tag does not sanitize HTML; this is provided by HtmlString before saving to
|
|
216
236
|
-->
|
217
237
|
<def tag="integer-select-editor" attrs="options, min, max, update, nil-option, message">
|
218
238
|
<% options ||= (min.to_i..max.to_i).to_a %>
|
219
|
-
<select class="integer editor #{
|
239
|
+
<select class="integer editor #{update_elements_class(update)} #{model_id_class(this_parent, this_field)}"
|
220
240
|
merge-attrs="&message ? attributes.merge(:hobo_message => message) : attributes">
|
221
241
|
<if test="&this.nil?"><option value=""><%= nil_option || "Choose a value" %></option></if>
|
222
242
|
<%= options_for_select(options.*.to_s, this.to_s) %>
|