hobo 0.8.10 → 0.9.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/CHANGES.txt +126 -2
- data/Rakefile +4 -1
- data/bin/hobo +1 -1
- data/doctest/scopes.rdoctest +11 -4
- data/dryml_generators/rapid/cards.dryml.erb +8 -2
- data/dryml_generators/rapid/forms.dryml.erb +5 -4
- data/dryml_generators/rapid/pages.dryml.erb +150 -65
- data/lib/hobo.rb +1 -1
- data/lib/hobo/accessible_associations.rb +2 -0
- data/lib/hobo/authentication_support.rb +1 -1
- data/lib/hobo/controller.rb +11 -3
- data/lib/hobo/dryml/dryml_doc.rb +1 -1
- data/lib/hobo/fake_initializer.rb +14 -0
- data/lib/hobo/hobo_helper.rb +94 -6
- data/lib/hobo/lifecycles.rb +17 -2
- data/lib/hobo/lifecycles/lifecycle.rb +1 -1
- data/lib/hobo/lifecycles/transition.rb +12 -4
- data/lib/hobo/model.rb +25 -22
- data/lib/hobo/model_controller.rb +42 -37
- data/lib/hobo/model_router.rb +11 -7
- data/lib/hobo/permissions.rb +12 -10
- data/lib/hobo/permissions/associations.rb +1 -1
- data/lib/hobo/static_tags +21 -0
- data/lib/hobo/user.rb +7 -3
- data/lib/hobo/user_controller.rb +7 -7
- data/lib/hobo/view_hints.rb +10 -3
- data/rails_generators/hobo/USAGE +4 -0
- data/rails_generators/hobo_admin_site/USAGE +16 -0
- data/rails_generators/hobo_front_controller/hobo_front_controller_generator.rb +11 -2
- data/rails_generators/hobo_front_controller/templates/controller.rb +6 -0
- data/rails_generators/hobo_front_controller/templates/summary.dryml +103 -0
- data/rails_generators/hobo_model_resource/USAGE +38 -0
- data/rails_generators/hobo_rapid/USAGE +3 -0
- data/rails_generators/hobo_rapid/templates/hobo-rapid.js +7 -3
- data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/clean.css +4 -0
- data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +5 -0
- data/rails_generators/hobo_subsite/USAGE +16 -0
- data/rails_generators/hobo_subsite/hobo_subsite_generator.rb +1 -1
- data/rails_generators/hobo_user_controller/templates/controller.rb +2 -2
- data/rails_generators/hobo_user_model/templates/model.rb +6 -1
- data/taglibs/rapid.dryml +1 -0
- data/taglibs/rapid_core.dryml +4 -4
- data/taglibs/rapid_forms.dryml +29 -21
- data/taglibs/rapid_generics.dryml +3 -1
- data/taglibs/rapid_lifecycles.dryml +14 -9
- data/taglibs/rapid_navigation.dryml +1 -1
- data/taglibs/rapid_plus.dryml +1 -0
- data/taglibs/rapid_summary.dryml +300 -0
- data/taglibs/rapid_support.dryml +1 -1
- data/taglibs/rapid_user_pages.dryml +21 -19
- data/test/permissions/test_permissions.rb +1 -1
- metadata +12 -4
@@ -0,0 +1,38 @@
|
|
1
|
+
Description:
|
2
|
+
The model generator creates stubs for a new model, corresponding
|
3
|
+
controller and it's views.
|
4
|
+
|
5
|
+
The generator takes a model name as its argument. The model name
|
6
|
+
may be given in CamelCase or under_score and should not be
|
7
|
+
suffixed with anything.
|
8
|
+
|
9
|
+
As additional parameters, the generator will take attribute pairs
|
10
|
+
described by name and type. These attributes will be used to
|
11
|
+
prepopulate the migration to create the table for the model and
|
12
|
+
give you a set of predefined fixture. You don't have to think up
|
13
|
+
all attributes up front, but it's a good idea of adding just the
|
14
|
+
baseline of what's needed to start really working with the
|
15
|
+
resource.
|
16
|
+
|
17
|
+
The generator creates a model class in app/models, a test suite in
|
18
|
+
test/unit and test fixtures in test/fixtures/singular_name.yml.
|
19
|
+
The generator creates a controller class in app/controllers with
|
20
|
+
view templates in app/views/controller_name, a helper class in
|
21
|
+
app/helpers, and a functional test suite in test/functional.
|
22
|
+
|
23
|
+
Examples:
|
24
|
+
./script/generate hobo_model_resource account
|
25
|
+
|
26
|
+
This will create an Account model:
|
27
|
+
Model: app/models/account.rb
|
28
|
+
Controller: app/controllers/accounts_controller.rb
|
29
|
+
Helper: app/helpers/accounts_helper.rb
|
30
|
+
Views: app/views/accounts
|
31
|
+
ViewHints: app/viewhints/account_hints.rb
|
32
|
+
Test: test/unit/account_test.rb
|
33
|
+
Test: test/functions/accounts_controller_test.rb
|
34
|
+
Fixtures: test/fixtures/accounts.yml
|
35
|
+
|
36
|
+
./script/generate hobo_model_resource post title:string created_on:date body:text published:boolean
|
37
|
+
|
38
|
+
Creates post model, controller & views with predefined attributes.
|
@@ -655,7 +655,9 @@ SelectManyInput = Behavior.create({
|
|
655
655
|
this.element.down('.items').appendChild(newItem);
|
656
656
|
newItem.down('span').innerHTML = selected.innerHTML
|
657
657
|
this.itemAdded(newItem, selected)
|
658
|
-
selected.
|
658
|
+
var optgroup = new Element("optgroup", {alt:selected.value, label:selected.text})
|
659
|
+
optgroup.addClassName("disabled-option")
|
660
|
+
selected.replace(optgroup)
|
659
661
|
select.value = ""
|
660
662
|
Event.addBehavior.reload()
|
661
663
|
this.element.fire("rapid:add", { element: newItem })
|
@@ -678,8 +680,10 @@ SelectManyInput = Behavior.create({
|
|
678
680
|
element.fire("rapid:change", { element: el })
|
679
681
|
} } )
|
680
682
|
var label = el.down('span').innerHTML
|
681
|
-
var
|
682
|
-
option
|
683
|
+
var optgroup = element.down("optgroup[label="+label+"]")
|
684
|
+
var option = new Element("option", {value:optgroup.readAttribute("alt")})
|
685
|
+
option.innerHTML = optgroup.readAttribute("label")
|
686
|
+
optgroup.replace(option)
|
683
687
|
},
|
684
688
|
|
685
689
|
itemAdded: function(item, option) {
|
@@ -321,3 +321,7 @@ ul.input-many div.buttons {float:left; margin-left:10px;}
|
|
321
321
|
ul.check-many { list-style-type: none; margin-left: 0px;}
|
322
322
|
ul.check-many li input { vertical-align: -20%;}
|
323
323
|
|
324
|
+
/* rapid-summary */
|
325
|
+
table.app-summary { border: 1px solid; border-collapse: collapse; }
|
326
|
+
table.app-summary td { padding: 2px; border: 1px dotted #bbb; }
|
327
|
+
table.app-summary th { padding: 2px; border-bottom: 1px solid; background: #acd3e6; }
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Description:
|
2
|
+
|
3
|
+
Creates a subsite, a namespaced section of your application.
|
4
|
+
|
5
|
+
The subsite will use app/views/taglibs/<subsite_name>_site.dryml
|
6
|
+
instead of app/views/taglibs/appplication.dryml. This allows you
|
7
|
+
to easily set different themes and choose different CSS files for
|
8
|
+
the subsite.
|
9
|
+
|
10
|
+
Controllers for the subsite are created in
|
11
|
+
app/controllers/<subsite_name>/ and views are also in their own
|
12
|
+
subdirectory. This allows you to have two different controllers
|
13
|
+
and two different sets of views for the same model.
|
14
|
+
|
15
|
+
The difference between hobo_admin_site and hobo_subsite is that
|
16
|
+
hobo_admin_site limits the subsite to use by administrators only.
|
@@ -12,7 +12,7 @@ class <%= class_name %>Controller < ApplicationController
|
|
12
12
|
this.password = this.password_confirmation = nil # don't trigger password change validations
|
13
13
|
this.state = 'active'
|
14
14
|
this.save
|
15
|
-
flash[:notice] = "You are now the site administrator"
|
15
|
+
flash[:notice] = ht("hobo.messages.you_are_site_admin", :default=>"You are now the site administrator")
|
16
16
|
redirect_to home_page
|
17
17
|
end
|
18
18
|
end
|
@@ -21,7 +21,7 @@ class <%= class_name %>Controller < ApplicationController
|
|
21
21
|
def do_accept_invitation
|
22
22
|
do_transition_action :accept_invitation do
|
23
23
|
self.current_user = this
|
24
|
-
flash[:notice] = "You have signed up"
|
24
|
+
flash[:notice] = ht("hobo.messages.you_signed_up", :default=>"You have signed up")
|
25
25
|
end
|
26
26
|
end
|
27
27
|
<% end -%>
|
@@ -9,12 +9,17 @@ class <%= class_name %> < ActiveRecord::Base
|
|
9
9
|
timestamps
|
10
10
|
end
|
11
11
|
|
12
|
+
validates_presence_of :name
|
13
|
+
|
12
14
|
# This gives admin rights to the first sign-up.
|
13
15
|
# Just remove it if you don't want that
|
14
16
|
before_create { |user| user.administrator = true if !Rails.env.test? && count == 0 }
|
15
17
|
|
16
18
|
<% if invite_only? -%>
|
17
|
-
|
19
|
+
def new_password_required_with_invite_only?
|
20
|
+
new_password_required_without_invite_only? || User.count==0
|
21
|
+
end
|
22
|
+
alias_method_chain :new_password_required?, :invite_only
|
18
23
|
<% end -%>
|
19
24
|
|
20
25
|
# --- Signup lifecycle --- #
|
data/taglibs/rapid.dryml
CHANGED
data/taglibs/rapid_core.dryml
CHANGED
@@ -112,7 +112,7 @@ This will use `<input/>` as the tag in each table cell instead of `<view/>`
|
|
112
112
|
<td param="#{this_field.to_s.sub('?', '').gsub('.', '-')}-view"><call-tag tag="&field_tag"/></td>
|
113
113
|
</with-fields>
|
114
114
|
<td class="controls" param="controls" if="&all_parameters[:controls]">
|
115
|
-
<a param="edit-link" action="edit" if="&can_edit?">Edit</a>
|
115
|
+
<a param="edit-link" action="edit" if="&can_edit?"><ht key="hobo.action.edit">Edit</ht></a>
|
116
116
|
<delete-button param/>
|
117
117
|
</td>
|
118
118
|
</if>
|
@@ -517,11 +517,11 @@ The label can be customised using the `label` attribute, e.g.
|
|
517
517
|
c = this.try.to_int || this.try.total_entries || (this.try.loaded? && this.try.length) || this.try.count || this.try.length
|
518
518
|
|
519
519
|
label ||= if this.is_a?(Class)
|
520
|
-
this.
|
520
|
+
this.view_hints.model_name
|
521
521
|
elsif (attr = this.try.origin_attribute)
|
522
|
-
attr.
|
522
|
+
this.member_class.view_hints.field_name(attr).singularize
|
523
523
|
else
|
524
|
-
this.member_class.
|
524
|
+
this.member_class.view_hints.model_name
|
525
525
|
end.titleize
|
526
526
|
|
527
527
|
label = label.downcase if lowercase
|
data/taglibs/rapid_forms.dryml
CHANGED
@@ -32,7 +32,7 @@ Several of the tags in this taglib support the following set of ajax attributes:
|
|
32
32
|
The following attributes are also supported by all the ajax tags. Set them to fragments of javascript to have that script
|
33
33
|
executed at various points in the ajax request cycle:
|
34
34
|
|
35
|
-
- before: script to run
|
35
|
+
- before: script to run before the request
|
36
36
|
|
37
37
|
- success: script to run on successful completion of the request
|
38
38
|
|
@@ -183,7 +183,7 @@ AJAX based submission can be enabled by simply adding an `update` attribute. e.g
|
|
183
183
|
page_path = if (request.post? || request.put?) && params[:page_path]
|
184
184
|
params[:page_path]
|
185
185
|
else
|
186
|
-
view_name.sub(Hobo::Dryml::EMPTY_PAGE, params[:action])
|
186
|
+
view_name.sub(Hobo::Dryml::EMPTY_PAGE, params[:action] || '')
|
187
187
|
end
|
188
188
|
page_path_hidden = hidden_field_tag("page_path", page_path)
|
189
189
|
end
|
@@ -319,7 +319,7 @@ edit collections a `Category` model in your application:
|
|
319
319
|
<def tag="input" for="boolean" attrs="name">
|
320
320
|
<%= unless attributes[:disabled]
|
321
321
|
cb_tag = check_box_tag(name, '1', this, attributes)
|
322
|
-
cb_hidden_tag = hidden_field_tag(name, '0')
|
322
|
+
cb_hidden_tag = hidden_field_tag(name, '0', :id => nil)
|
323
323
|
HoboSupport::RAILS_AT_LEAST_23 ? cb_hidden_tag + cb_tag : cb_tag + cb_hidden_tag
|
324
324
|
end %>
|
325
325
|
</def>
|
@@ -380,8 +380,6 @@ The menus default to the current time if the current value is nil.
|
|
380
380
|
<% if ! order.nil?
|
381
381
|
order = comma_split(order).*.to_sym
|
382
382
|
attributes.merge!(:order => order)
|
383
|
-
require 'ruby-debug'
|
384
|
-
debugger
|
385
383
|
end -%>
|
386
384
|
<%= select_datetime(this || current_time, attributes.merge(:prefix => param_name_for_this)) %>
|
387
385
|
</def>
|
@@ -536,8 +534,8 @@ All the standard ajax attributes *except the callbacks* are supported (see the m
|
|
536
534
|
else
|
537
535
|
{ :type => "button" }
|
538
536
|
end)
|
539
|
-
label ||= "Remove"
|
540
|
-
confirm = "Are you sure?" if confirm.nil?
|
537
|
+
label ||= ht("hobo.actions.remove", :default=>"Remove")
|
538
|
+
confirm = ht("hobo.messages.confirm", :default=>"Are you sure?") if confirm.nil?
|
541
539
|
|
542
540
|
add_classes!(attributes,
|
543
541
|
image ? "image-button" : "button",
|
@@ -584,7 +582,7 @@ All of the standard ajax attributes are supported (see the main taglib documenti
|
|
584
582
|
new = class_or_assoc.new(fields)
|
585
583
|
new.set_creator(current_user)
|
586
584
|
if can_create?(new)
|
587
|
-
label ||= "New #{new.class.name.titleize}"
|
585
|
+
label ||= ht("#{new.class.name.pluralize.underscore}.actions.new", :default=>"New #{new.class.name.titleize}")
|
588
586
|
ajax_attributes = { :message => message }
|
589
587
|
class_name = new.class.name.underscore
|
590
588
|
ajax_attributes[:params] = { class_name => fields } unless fields.empty?
|
@@ -601,7 +599,7 @@ This is the default input that Rapid uses for `belongs_to` associations. The men
|
|
601
599
|
|
602
600
|
### Attributes
|
603
601
|
|
604
|
-
- `include-none` - whether to include a 'none' option (i.e. set the foreign key to null).
|
602
|
+
- `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.
|
605
603
|
- `blank-message` - the message for the 'none' option. Defaults to "(No `<model-name>`)", e.g. "(No Product)"
|
606
604
|
- `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`)
|
607
605
|
- `limit` - if `options` is not specified, this limits the number of records. Default: 100
|
@@ -615,7 +613,7 @@ For situations where there are too many target records to practically include in
|
|
615
613
|
<def tag="select-one" attrs="include-none, blank-message, options, sort, limit, text-method"><%
|
616
614
|
raise HoboError.new("Not allowed to edit #{this_field}") if !attributes[:disabled] && !can_edit?
|
617
615
|
|
618
|
-
blank_message ||= "(No #{this_type.
|
616
|
+
blank_message ||= ht("#{this_type.name.underscore}.message.no", :default=>"(No #{this_type.view_hints.model_name})")
|
619
617
|
limit ||= 100
|
620
618
|
|
621
619
|
options ||= begin
|
@@ -682,7 +680,7 @@ Here's a more complex example. This used to be a part of [agility](http://cookb
|
|
682
680
|
end
|
683
681
|
end
|
684
682
|
|
685
|
-
Note that this was added to the projects controller, rather than the users controller as in the first example. You can read this as: create an auto-complete action called
|
683
|
+
Note that this was added to the projects controller, rather than the users controller as in the first example. You can read this as: create an auto-complete action called �new_member_name� that finds users that are not already members of the project, and not the owner of the project, and completes the :name field.
|
686
684
|
|
687
685
|
<name-one:user complete-target="&@project" completer="new_member_name"/>
|
688
686
|
|
@@ -751,13 +749,14 @@ To use this tag, the model of the items the user is chosing *must* have unique n
|
|
751
749
|
name ||= param_name_for_this
|
752
750
|
|
753
751
|
values = this
|
752
|
+
remove_label ||= ht("hobo.actions.remove", :default=>'Remove')
|
754
753
|
-%>
|
755
754
|
<div class="input select-many" merge-attrs>
|
756
755
|
<div style="display:none" class="item-proto">
|
757
756
|
<div class="item" param="proto-item">
|
758
757
|
<span></span>
|
759
758
|
<input type="hidden" name="#{name}[]" param="proto-hidden"/>
|
760
|
-
<input type="button" class="remove-item" value="#{remove_label
|
759
|
+
<input type="button" class="remove-item" value="#{remove_label}" param="proto-remove-button"/>
|
761
760
|
</div>
|
762
761
|
</div>
|
763
762
|
<div class="items">
|
@@ -765,14 +764,20 @@ To use this tag, the model of the items the user is chosing *must* have unique n
|
|
765
764
|
<span><%= h this.to_s %></span>
|
766
765
|
<input type="hidden" name="#{name}[]" value="@#{h this.id}" disabled="&disabled"
|
767
766
|
param="hidden"/>
|
768
|
-
<input type="button" class="remove-item" value="#{remove_label
|
767
|
+
<input type="button" class="remove-item" value="#{remove_label}" disabled="&disabled"
|
769
768
|
param="remove-button"/>
|
770
769
|
</div>
|
771
770
|
</div>
|
772
771
|
<select merge-attrs="&{:disabled => disabled}">
|
773
772
|
<option value=""><prompt/></option>
|
774
|
-
<
|
775
|
-
|
773
|
+
<repeat with="&options">
|
774
|
+
<if test="&this.in?(values)">
|
775
|
+
<optgroup class="disabled-option" label="#{h this.to_s}" alt="@#{this.id}"> </optgroup>
|
776
|
+
</if>
|
777
|
+
<else>
|
778
|
+
<option value="@#{this.id}"><%= h this.to_s %></option>
|
779
|
+
</else>
|
780
|
+
</repeat>
|
776
781
|
</select>
|
777
782
|
</div>
|
778
783
|
</def>
|
@@ -814,7 +819,7 @@ Use the `uri` option to specify a redirect location:
|
|
814
819
|
|
815
820
|
<!-- A simple wrapper around the `<select>` tag and `options_for_select` helper
|
816
821
|
|
817
|
-
### Attributes
|
822
|
+
### Attributes
|
818
823
|
|
819
824
|
- `options` - an array of options suitable to be passed to the Rails `options_for_select` helper.
|
820
825
|
- `selected` - the value (from the `options` array) that should be initially selected. Defaults to `this`
|
@@ -867,7 +872,7 @@ Use the `uri` option to specify a redirect location:
|
|
867
872
|
|
868
873
|
This tag is very different from tags like `<select-many>` and `<check-many>` in that:
|
869
874
|
|
870
|
-
- Those tags are used to *chose existing records* to include in the
|
875
|
+
- Those tags are used to *chose existing records* to include in the association, while `<input-many>` is used to actually create or edit the records in the association.
|
871
876
|
|
872
877
|
### Example
|
873
878
|
|
@@ -880,9 +885,11 @@ The body of the tag will be repeated for each of the current records in the coll
|
|
880
885
|
### Attributes
|
881
886
|
|
882
887
|
- fields: If you do not specify any content for the input-many, a `<field-list>` is rendered. This attribute is passed through to the `<field-list>`
|
888
|
+
|
889
|
+
- skip: Passed through to the `<field-list>`. If not specified, it defaults to the parent association.
|
883
890
|
|
884
891
|
-->
|
885
|
-
<def tag="input-many" attrs="fields" polymorphic>
|
892
|
+
<def tag="input-many" attrs="fields,skip" polymorphic>
|
886
893
|
<set empty="&this.empty?"/>
|
887
894
|
<ul class="input-many #{this_field.dasherize} #{css_data :input_many_prefix, param_name_for_this}">
|
888
895
|
<li repeat class="#{'record-with-errors' unless this.errors.empty?}">
|
@@ -897,9 +904,10 @@ The body of the tag will be repeated for each of the current records in the coll
|
|
897
904
|
</div>
|
898
905
|
</li>
|
899
906
|
<li if="&empty">
|
907
|
+
<% skip ||= this.proxy_reflection.klass.reflect_on_all_associations.detect {|p| p.primary_key_name==this.proxy_reflection.primary_key_name}.try.name.to_s %>
|
900
908
|
<fake-field-context fake-field="0" context="&this.try.new_candidate || this.member_class.new">
|
901
909
|
<div class="input-many-item" param="default">
|
902
|
-
<field-list merge-attrs="fields"/>
|
910
|
+
<field-list merge-attrs="fields" skip="&skip"/>
|
903
911
|
</div>
|
904
912
|
</fake-field-context>
|
905
913
|
<div class="buttons">
|
@@ -928,8 +936,8 @@ The body of the tag will be repeated for each of the current records in the coll
|
|
928
936
|
<!-- Renders the common "or (Cancel)" for a form. Attributes are merged into the link (`<a>Cancel</a>`), making it easy to customise the destination of the cancel link. By default it will link to `this` or `this.class`.
|
929
937
|
-->
|
930
938
|
<def tag="or-cancel">
|
931
|
-
<if test="&linkable?">or <a merge-attrs>Cancel</a></if>
|
939
|
+
<if test="&linkable?"><ht key="hobo.support.or">or</ht> <a merge-attrs><ht key="hobo.actions.cancel">Cancel</ht></a></if>
|
932
940
|
<else>
|
933
|
-
<if test="&linkable?(this.class)">or <a to="&this.class" merge-attrs>Cancel</a></if>
|
941
|
+
<if test="&linkable?(this.class)"><ht key="hobo.support.or">or</ht> <a to="&this.class" merge-attrs><ht key="hobo.actions.cancel">Cancel</ht></a></if>
|
934
942
|
</else>
|
935
943
|
</def>
|
@@ -19,7 +19,9 @@
|
|
19
19
|
-->
|
20
20
|
<def tag="empty-collection-message">
|
21
21
|
<div class="empty-collection-message" style="#{'display:none' if !this.empty?}" param="default">
|
22
|
-
|
22
|
+
<ht key="#{type_name.downcase.sub(' ', '_').pluralize}.collection.empty_message">
|
23
|
+
No <collection-name lowercase/> to display
|
24
|
+
</ht>
|
23
25
|
</div>
|
24
26
|
</def>
|
25
27
|
|
@@ -10,15 +10,20 @@
|
|
10
10
|
|
11
11
|
All of the [standard ajax attributes](/api_taglibs/rapid_forms) are also supported.
|
12
12
|
-->
|
13
|
-
<def tag="transition-button" attrs="transition, update, label"><%=
|
14
|
-
|
13
|
+
<def tag="transition-button" attrs="transition, update, label"><%=
|
14
|
+
if transition.is_a?(String)
|
15
|
+
transition = this.lifecycle.find_transition(transition, current_user)
|
16
|
+
end
|
17
|
+
transition_name = transition.name
|
18
|
+
has_params = !transition.options[:params].blank?
|
15
19
|
ajax_attributes, html_attributes = attributes.partition_hash(Hobo::RapidHelper::AJAX_ATTRS)
|
16
20
|
|
17
|
-
html_attributes[:method]
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
html_attributes[:method] ||= has_params ? :get : :put
|
22
|
+
add_classes!(html_attributes, "transition-button #{transition_name}-button")
|
23
|
+
label ||= transition_name.to_s.titleize
|
24
|
+
url = object_url(this, transition_name, :method => html_attributes[:method])
|
25
|
+
|
26
|
+
if (update || !ajax_attributes.empty?) && !has_params
|
22
27
|
ajax_attributes[:message] ||= label
|
23
28
|
func = ajax_updater(url, update, ajax_attributes)
|
24
29
|
html_attributes.update(:onclick => "var e = this; " + func, :type =>'button', :value => label)
|
@@ -28,10 +33,10 @@ All of the [standard ajax attributes](/api_taglibs/rapid_forms) are also support
|
|
28
33
|
end
|
29
34
|
%>
|
30
35
|
</def>
|
31
|
-
|
36
|
+
|
32
37
|
|
33
38
|
<!-- Renders a div containing transition buttons for every transition available to the current user.
|
34
|
-
|
39
|
+
|
35
40
|
For example, you could use this on a `Friendship` card: the person invited to have friendship would automatically see 'Accept' and 'Decline' buttons, while the person initiating the invite would see 'Retract'.
|
36
41
|
-->
|
37
42
|
<def tag="transition-buttons">
|
@@ -85,5 +85,5 @@ This is a simple tag - just look at the source if you need to know more detail.
|
|
85
85
|
|
86
86
|
<!--- A simple wrapper around the `will_paginate` helper. All options to `will_paginate` are available as attributes -->
|
87
87
|
<def tag="page-nav">
|
88
|
-
<%= will_paginate this, attributes.symbolize_keys.reverse_merge(:inner_window => 2, :previous_label => "« Prev") %>
|
88
|
+
<%= will_paginate this, attributes.symbolize_keys.reverse_merge(:inner_window => 2, :previous_label => translate("hobo.actions.previous", :default=>"« Prev"), :next_label =>translate("hobo.actions.next", :default=>"Next »")) %>
|
89
89
|
</def>
|
data/taglibs/rapid_plus.dryml
CHANGED
@@ -103,6 +103,7 @@ This tag assumes the controller has a `reorder` action. This action is added aut
|
|
103
103
|
<h3 param="heading"><%= name.titleize %></h3>
|
104
104
|
<a param="more">More <type-name plural lowercase/>...</a>
|
105
105
|
<collection param/>
|
106
|
+
<a action="new" if="&can_create?(this.new)" param="new-link">New <%= this.member_class.view_hints.model_name %></a>
|
106
107
|
</section>
|
107
108
|
</def>
|
108
109
|
|
@@ -0,0 +1,300 @@
|
|
1
|
+
<!-- These are a collection of tags that allow a application outline or summary to be created -->
|
2
|
+
|
3
|
+
<!-- Rails.version -->
|
4
|
+
<def tag="rails-version">
|
5
|
+
<%= Rails.version -%>
|
6
|
+
</def>
|
7
|
+
|
8
|
+
<!-- returns "vendor" or "gem" -->
|
9
|
+
<def tag="rails-location">
|
10
|
+
<%= Rails.vendor_rails? ? "vendor" : "gem" -%>
|
11
|
+
</def>
|
12
|
+
|
13
|
+
<!-- `RAILS_ROOT` -->
|
14
|
+
<def tag="rails-root">
|
15
|
+
<%= RAILS_ROOT -%>
|
16
|
+
</def>
|
17
|
+
|
18
|
+
<!-- `RAILS_ENV` -->
|
19
|
+
<def tag="rails-env">
|
20
|
+
<%= RAILS_ENV -%>
|
21
|
+
</def>
|
22
|
+
|
23
|
+
<!-- Which change management system is in use: "git" "subversion" "other" -->
|
24
|
+
<def tag="cms-method">
|
25
|
+
<%= if File.exist?("#{RAILS_ROOT}/.git")
|
26
|
+
"git"
|
27
|
+
elsif File.exist?("#{RAILS_ROOT}/.svn")
|
28
|
+
"subversion"
|
29
|
+
else
|
30
|
+
"other"
|
31
|
+
end -%>
|
32
|
+
</def>
|
33
|
+
|
34
|
+
<!-- the git branch currently in use -->
|
35
|
+
<def tag="git-branch">
|
36
|
+
<%= File.basename(`git symbolic-ref HEAD`) -%>
|
37
|
+
</def>
|
38
|
+
|
39
|
+
<!-- the git version currently in use -->
|
40
|
+
<def tag="git-version" attrs="dir">
|
41
|
+
<% dir=RAILS_ROOT if dir.blank? -%>
|
42
|
+
<%= Dir.chdir(dir) {`git rev-list "HEAD^..HEAD" --abbrev-commit --abbrev=7`} -%>
|
43
|
+
</def>
|
44
|
+
|
45
|
+
<!-- returns 'clean' if there are no modified files, 'modified' otherwise. -->
|
46
|
+
<def tag="git-clean" attrs="dir">
|
47
|
+
<% dir=RAILS_ROOT if dir.blank? -%>
|
48
|
+
<%= Dir.chdir(dir) {`git ls-files -m`}.blank? ? "clean" : "modified" -%>
|
49
|
+
</def>
|
50
|
+
|
51
|
+
<!-- the time & date of the last commit -->
|
52
|
+
<def tag="git-last-commit-time">
|
53
|
+
<%= `git log "HEAD^..HEAD" --pretty=format:%cD` -%>
|
54
|
+
</def>
|
55
|
+
|
56
|
+
<!-- calls `git-clean` or `svn-clean` as appropriate. `svn-clean` not yet written. -->
|
57
|
+
<def tag="cms-clean">
|
58
|
+
<% method = cms_method.strip -%>
|
59
|
+
<git-clean if="&method=='git'"/>
|
60
|
+
</def>
|
61
|
+
|
62
|
+
<!-- calls `git-last-commit-time` or `svn-last-commit-time` as appropriate. `svn-last-commit-time` not yet written. -->
|
63
|
+
<def tag="cms-last-commit-time">
|
64
|
+
<% method = cms_method.strip -%>
|
65
|
+
<git-last-commit-time if="&method=='git'"/>
|
66
|
+
</def>
|
67
|
+
|
68
|
+
<!-- calls `git-version` or `svn-version` as appropriate. `svn-version` not yet written. -->
|
69
|
+
<def tag="cms-version">
|
70
|
+
<% method = cms_method.strip -%>
|
71
|
+
<git-version if="&method=='git'"/>
|
72
|
+
</def>
|
73
|
+
|
74
|
+
<!-- calls `git-branch` or `svn-branch` as appropriate. `svn-branch` not yet written. -->
|
75
|
+
<def tag="cms-branch">
|
76
|
+
<% method = cms_method.strip -%>
|
77
|
+
<git-branch if="&method=='git'"/>
|
78
|
+
</def>
|
79
|
+
|
80
|
+
<!-- Hobo::VERSION -->
|
81
|
+
<def tag="hobo-version">
|
82
|
+
<%= Hobo::VERSION -%>
|
83
|
+
</def>
|
84
|
+
|
85
|
+
<!-- repeats on Rails.configuration.gems, including dependent gems -->
|
86
|
+
<def tag="with-gems">
|
87
|
+
<% gems = ActiveSupport::OrderedHash.new -%>
|
88
|
+
<% Rails.configuration.gems.each do |gem|
|
89
|
+
gems[name] ||= gem
|
90
|
+
gem.dependencies.each do |dep|
|
91
|
+
gems[dep] ||= dep
|
92
|
+
end
|
93
|
+
end -%>
|
94
|
+
<repeat with="&gems">
|
95
|
+
<do param="default"/>
|
96
|
+
</repeat>
|
97
|
+
</def>
|
98
|
+
|
99
|
+
<!-- inside `<with-gems>`, returns the gem name -->
|
100
|
+
<def tag="gem-name">
|
101
|
+
<%= this.name -%>
|
102
|
+
</def>
|
103
|
+
|
104
|
+
<def tag="gem-version-requirement">
|
105
|
+
<%= this.requirements.map{|l| l.first+l.second.to_s}.join(",") -%>
|
106
|
+
</def>
|
107
|
+
|
108
|
+
<!-- inside `<with-gems>`, returns the version required -->
|
109
|
+
<def tag="gem-version-required">
|
110
|
+
<gem-version-requirement:version-requirements />
|
111
|
+
</def>
|
112
|
+
|
113
|
+
<!-- inside `<with-gems>`, returns the version -->
|
114
|
+
<def tag="gem-version">
|
115
|
+
<%= this.specification.version.to_s -%>
|
116
|
+
</def>
|
117
|
+
|
118
|
+
<!-- inside `<with-gems>`, returns 'frozen', 'installed' or 'missing' -->
|
119
|
+
<def tag="gem-frozen">
|
120
|
+
<%= this.frozen? ? "frozen" : (this.installed? ? "installed" : "missing") -%>
|
121
|
+
</def>
|
122
|
+
|
123
|
+
<!-- inside `<with-gems>`, returns the gem dependencies -->
|
124
|
+
<def tag="gem-dependencies">
|
125
|
+
<repeat with="&this.dependencies">
|
126
|
+
<%= this.name -%><gem-version-requirement:requirement />
|
127
|
+
</repeat>
|
128
|
+
</def>
|
129
|
+
|
130
|
+
<!-- repeats on the plugins used by the application -->
|
131
|
+
<def tag="with-plugins">
|
132
|
+
<% fi = Hobo::FakeInitializer.new(Rails.configuration)
|
133
|
+
plugins = Rails.configuration.plugin_loader.new(fi).plugins %>
|
134
|
+
<repeat with="&plugins">
|
135
|
+
<do param="default" />
|
136
|
+
</repeat>
|
137
|
+
</def>
|
138
|
+
|
139
|
+
<!-- within `<with-plugins>`, returns the plugin name -->
|
140
|
+
<def tag="plugin-name">
|
141
|
+
<%= this.name -%>
|
142
|
+
</def>
|
143
|
+
|
144
|
+
<!-- within `<with-plugins>`, returns the plugin location (directory) -->
|
145
|
+
<def tag="plugin-location">
|
146
|
+
<%= this.directory -%>
|
147
|
+
</def>
|
148
|
+
|
149
|
+
<def tag="plugin-git-clean">
|
150
|
+
<git-clean dir="&this.directory"/>
|
151
|
+
</def>
|
152
|
+
|
153
|
+
<def tag="plugin-git-version">
|
154
|
+
<git-version dir="&this.directory"/>
|
155
|
+
</def>
|
156
|
+
|
157
|
+
<!-- within `<with-plugins>`, try and determine the method that was used to install the plugin. Returns "braid", "symlink", "git-submodule" or "other" -->
|
158
|
+
<def tag="plugin-method">
|
159
|
+
<%=
|
160
|
+
braids = File.open("#{RAILS_ROOT}/.braids") {|f| YAML::load(f) } rescue {}
|
161
|
+
if !braids[this.directory.gsub(RAILS_ROOT+"/", "")].nil?
|
162
|
+
"braid"
|
163
|
+
elsif File.lstat(this.directory).symlink?
|
164
|
+
"symlink"
|
165
|
+
elsif File.exist?(this.directory+"/.git")
|
166
|
+
"git-submodule"
|
167
|
+
else
|
168
|
+
"other"
|
169
|
+
end
|
170
|
+
-%>
|
171
|
+
</def>
|
172
|
+
|
173
|
+
<!-- within `<with-plugins>`, determine if the plugin has been modified, returning "clean" or "modified". Returns a blank string if this information is not available. Uses `<plugin-git-clean>` or `<plugin-braid-clean>` to do the heavy lifting. -->
|
174
|
+
<def tag="plugin-clean">
|
175
|
+
<% method = plugin_method.strip -%>
|
176
|
+
<plugin-git-clean if="&method=='git-submodule'"/>
|
177
|
+
<plugin-braid-clean if="&method=='braid'"/>
|
178
|
+
</def>
|
179
|
+
|
180
|
+
<!-- within `<with-plugins>`, returns the plugin version. Returns a blank string if this information is not available. Uses `<plugin-git-version>` or `<plugin-braid-version>` to do the heavy lifting. -->
|
181
|
+
<def tag="plugin-version">
|
182
|
+
<% method = plugin_method.strip -%>
|
183
|
+
<plugin-git-version if="&method=='git-submodule'"/>
|
184
|
+
<plugin-braid-version if="&method=='braid'"/>
|
185
|
+
</def>
|
186
|
+
|
187
|
+
<def tag="plugin-braid-clean">
|
188
|
+
<%= diff=`braid diff #{this.directory.gsub(RAILS_ROOT+"/", "")}`
|
189
|
+
diff.strip.empty? ? "clean" : "modified" -%>
|
190
|
+
</def>
|
191
|
+
|
192
|
+
<def tag="plugin-braid-version">
|
193
|
+
<%= braids = File.open("#{RAILS_ROOT}/.braids") {|f| YAML::load(f) } rescue {}
|
194
|
+
b=braids[this.directory.gsub(RAILS_ROOT+"/", "")]
|
195
|
+
b['revision'][0...7] if b -%>
|
196
|
+
</def>
|
197
|
+
|
198
|
+
<!-- repeats on the available execution environments, which are usually 'development', 'test' and 'production' -->
|
199
|
+
<def tag="with-environments">
|
200
|
+
<repeat with="&Rails.configuration.database_configuration.keys">
|
201
|
+
<do param="default" />
|
202
|
+
</repeat>
|
203
|
+
</def>
|
204
|
+
|
205
|
+
<def tag="environment-name">
|
206
|
+
<%= this -%>
|
207
|
+
</def>
|
208
|
+
|
209
|
+
<!-- Given an environment name in the context, return the database adapter -->
|
210
|
+
<def tag="database-type">
|
211
|
+
<%= Rails.configuration.database_configuration[this]['adapter'] -%>
|
212
|
+
</def>
|
213
|
+
|
214
|
+
<!-- Given an environment name in the context, return the database name -->
|
215
|
+
<def tag="database-name">
|
216
|
+
<%= Rails.configuration.database_configuration[this]['database'] -%>
|
217
|
+
</def>
|
218
|
+
|
219
|
+
<!-- repeats on available models. Does not return models defined in libraries or plugins. -->
|
220
|
+
<def tag="with-models">
|
221
|
+
<% # stolen from railroad/model_diagram.rb
|
222
|
+
|
223
|
+
files = Dir.glob("app/models/**/*.rb")
|
224
|
+
models = files.map do |file|
|
225
|
+
model_name = (model_path = file.gsub(/^(app\/models\/)([\w_\/\\]+)\.rb/, '\2')).camelize
|
226
|
+
# Hack to skip all xxx_related.rb files
|
227
|
+
next if /_related/i =~ model_name
|
228
|
+
|
229
|
+
begin
|
230
|
+
model_name.constantize
|
231
|
+
rescue LoadError
|
232
|
+
oldlen = model_path.length
|
233
|
+
model_path.gsub!(/.*[\/\\]/, '')
|
234
|
+
model_name = model_path.camelize
|
235
|
+
if oldlen > model_path.length
|
236
|
+
retry
|
237
|
+
end
|
238
|
+
next
|
239
|
+
rescue NameError
|
240
|
+
next
|
241
|
+
end
|
242
|
+
end
|
243
|
+
-%>
|
244
|
+
<repeat with="&models.sort_by {|m| m.to_s}">
|
245
|
+
<do param="default" />
|
246
|
+
</repeat>
|
247
|
+
</def>
|
248
|
+
|
249
|
+
<def tag="model-name">
|
250
|
+
<%= this.to_s -%>
|
251
|
+
</def>
|
252
|
+
|
253
|
+
<!-- given a model, returns the table name -->
|
254
|
+
<def tag="model-table-name">
|
255
|
+
<%= this.try.table_name -%>
|
256
|
+
</def>
|
257
|
+
|
258
|
+
<!-- given a model, repeats on the database columns -->
|
259
|
+
<def tag="with-model-columns">
|
260
|
+
<repeat with="&this.try.content_columns">
|
261
|
+
<do param="default" />
|
262
|
+
</repeat>
|
263
|
+
</def>
|
264
|
+
|
265
|
+
<!-- given a column, returns the type -->
|
266
|
+
<def tag="model-column-type">
|
267
|
+
<%= this.type.to_s -%>
|
268
|
+
</def>
|
269
|
+
|
270
|
+
<!-- given a column, return the name -->
|
271
|
+
<def tag="model-column-name">
|
272
|
+
<%= this.name -%>
|
273
|
+
</def>
|
274
|
+
|
275
|
+
<!-- given a model, repeats on the associations -->
|
276
|
+
<def tag="with-model-associations">
|
277
|
+
<repeat with="&this.try.reflect_on_all_associations">
|
278
|
+
<do param="default" />
|
279
|
+
</repeat>
|
280
|
+
</def>
|
281
|
+
|
282
|
+
<!-- given an association, return the name -->
|
283
|
+
<def tag="model-association-name">
|
284
|
+
<%= this.name.to_s -%>
|
285
|
+
</def>
|
286
|
+
|
287
|
+
<!-- given an association, return the macro type (`has_many`, etc.) -->
|
288
|
+
<def tag="model-association-macro">
|
289
|
+
<%= if this.macro.to_s=='has_many' && this.options[:through]
|
290
|
+
'has_many :through'
|
291
|
+
else
|
292
|
+
this.macro.to_s
|
293
|
+
end -%>
|
294
|
+
</def>
|
295
|
+
|
296
|
+
<!-- given an association, return the name -->
|
297
|
+
<def tag="model-association-class-name">
|
298
|
+
<%= (this.class_name.try.respond_to? 'underscore') ? this.class_name.underscore.singularize.camelize : this.try.class_name -%>
|
299
|
+
</def>
|
300
|
+
|