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