hobo 0.9.0 → 0.9.100

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.
Files changed (47) hide show
  1. data/CHANGES.txt +132 -0
  2. data/Rakefile +18 -22
  3. data/bin/hobo +14 -13
  4. data/doctest/scopes.rdoctest +1 -0
  5. data/dryml_generators/rapid/forms.dryml.erb +1 -1
  6. data/dryml_generators/rapid/pages.dryml.erb +24 -24
  7. data/lib/hobo.rb +3 -3
  8. data/lib/hobo/accessible_associations.rb +10 -3
  9. data/lib/hobo/controller.rb +2 -1
  10. data/lib/hobo/dryml.rb +7 -2
  11. data/lib/hobo/dryml/dryml_builder.rb +1 -4
  12. data/lib/hobo/dryml/dryml_generator.rb +5 -3
  13. data/lib/hobo/dryml/taglib.rb +3 -8
  14. data/lib/hobo/dryml/template.rb +3 -10
  15. data/lib/hobo/dryml/template_handler.rb +3 -2
  16. data/lib/hobo/hobo_helper.rb +5 -83
  17. data/lib/hobo/lifecycles.rb +9 -5
  18. data/lib/hobo/lifecycles/actions.rb +5 -5
  19. data/lib/hobo/lifecycles/lifecycle.rb +6 -2
  20. data/lib/hobo/model.rb +14 -36
  21. data/lib/hobo/model_controller.rb +28 -15
  22. data/lib/hobo/model_router.rb +1 -1
  23. data/lib/hobo/permissions.rb +55 -5
  24. data/lib/hobo/permissions/associations.rb +13 -5
  25. data/lib/hobo/rapid_helper.rb +4 -10
  26. data/lib/hobo/scopes/automatic_scopes.rb +9 -1
  27. data/lib/hobo/translations.rb +88 -0
  28. data/lib/hobo/user.rb +1 -2
  29. data/lib/hobo/user_controller.rb +31 -9
  30. data/lib/hobo/view_hints.rb +38 -6
  31. data/rails_generators/hobo_model/templates/hints.rb +4 -1
  32. data/rails_generators/hobo_model_controller/hobo_model_controller_generator.rb +1 -1
  33. data/rails_generators/hobo_rapid/hobo_rapid_generator.rb +2 -1
  34. data/rails_generators/hobo_rapid/templates/hobo-rapid.js +9 -0
  35. data/rails_generators/hobo_rapid/templates/ie7-recalc.js +166 -2
  36. data/rails_generators/hobo_user_model/templates/model.rb +1 -3
  37. data/taglibs/rapid.dryml +2 -1
  38. data/taglibs/rapid_core.dryml +7 -5
  39. data/taglibs/rapid_editing.dryml +14 -10
  40. data/taglibs/rapid_forms.dryml +7 -5
  41. data/taglibs/rapid_generics.dryml +1 -1
  42. data/taglibs/rapid_lifecycles.dryml +3 -2
  43. data/taglibs/rapid_pages.dryml +1 -1
  44. data/taglibs/rapid_support.dryml +1 -1
  45. data/tasks/hobo_tasks.rake +10 -0
  46. metadata +7 -7
  47. data/lib/hobo/bundle.rb +0 -330
@@ -28,7 +28,8 @@ This area of Hobo has had less attention that the non-ajax forms of late, so it'
28
28
 
29
29
  <!-- Not implemented - you just get links to the items in the collection -->
30
30
  <def tag="has-many-editor">
31
- <% #TODO: Implement %>
31
+ <% #TODO: Implement
32
+ %>
32
33
  <a merge-attrs/>
33
34
  </def>
34
35
 
@@ -36,30 +37,33 @@ This area of Hobo has had less attention that the non-ajax forms of late, so it'
36
37
  <def tag="belongs-to-editor" polymorphic><%= select_one_editor(attributes) %></def>
37
38
 
38
39
  <!-- Provides a simple Scriptaculous in-place-editor that uses an `<input type='text'>` -->
39
- <def tag="editor" for="string"><%= in_place_editor attributes %></def>
40
+ <def tag="editor" for="string"><%= in_place_editor(attributes, this) %></def>
40
41
 
41
42
  <!-- Provides a simple Scriptaculous in-place-editor that uses a `<textarea>` -->
42
- <def tag="editor" for="text"><%= in_place_editor attributes %></def>
43
+ <def tag="editor" for="text"><%= in_place_editor(attributes, this) %></def>
43
44
 
44
45
  <!-- Provides a simple Scriptaculous in-place-editor that uses a `<textarea>`.
45
46
  A JavaScript hook is available in order to replace the simple textarea with a rich-text editor.
46
- For an example, see the [hoboyui](http://github.com/tablatom/hoboyui) plugin -->
47
- <def tag="editor" for="html"><%= in_place_editor attributes %></def>
47
+ For an example, see the [hoboyui](http://github.com/tablatom/hoboyui) plugin
48
+
49
+ This tag does not sanitize HTML; this is provided by HtmlString before saving to the database.
50
+ -->
51
+ <def tag="editor" for="html"><%= in_place_editor(attributes, this) %></def>
48
52
 
49
53
  <!-- Provides a simple Scriptaculous in-place-editor that uses an `<input type='text'>` -->
50
- <def tag="editor" for="datetime"><%= in_place_editor attributes %></def>
54
+ <def tag="editor" for="datetime"><%= in_place_editor(attributes, this) %></def>
51
55
 
52
56
  <!-- Provides a simple Scriptaculous in-place-editor that uses an `<input type='text'>` -->
53
- <def tag="editor" for="date"><%= in_place_editor attributes %></def>
57
+ <def tag="editor" for="date"><%= in_place_editor(attributes, this) %></def>
54
58
 
55
59
  <!-- Provides a simple Scriptaculous in-place-editor that uses an `<input type='integer'>` -->
56
- <def tag="editor" for="integer"><%= in_place_editor attributes %></def>
60
+ <def tag="editor" for="integer"><%= in_place_editor(attributes, this) %></def>
57
61
 
58
62
  <!-- Provides a simple Scriptaculous in-place-editor that uses an `<input type='BigDecimal'>` -->
59
- <def tag="editor" for="BigDecimal"><%= in_place_editor attributes %></def>
63
+ <def tag="editor" for="BigDecimal"><%= in_place_editor(attributes, this) %></def>
60
64
 
61
65
  <!-- Provides a simple Scriptaculous in-place-editor that uses an `<input type='text'>` -->
62
- <def tag="editor" for="float"><%= in_place_editor attributes %></def>
66
+ <def tag="editor" for="float"><%= in_place_editor(attributes, this) %></def>
63
67
 
64
68
  <!-- Raises an error - passwords cannot be edited in place -->
65
69
  <def tag="editor" for="password"><% raise HoboError, "passwords cannot be edited in place" %></def>
@@ -417,8 +417,9 @@ The menus default to the current time if the current value is nil.
417
417
  -->
418
418
  <def tag="input" for="HoboFields::EnumString" attrs="labels, titleize, first-option, first-value"><%
419
419
  labels ||= {}
420
+ labels = HashWithIndifferentAccess.new(labels)
420
421
  titleize = true if titleize.nil?
421
- options = this_type.values.map {|v| [labels.fetch(v.to_sym, titleize ? v.titleize : v), v] }
422
+ options = this_type.values.map {|v| [labels.fetch(v, titleize ? this_type.translated_values[v].titleize : this_type.translated_values[v]), v] }
422
423
  %>
423
424
  <select name="#{param_name_for_this}" merge-attrs>
424
425
  <option value="#{first_value}" unless="&first_option.nil?"><first-option/></option>
@@ -680,7 +681,7 @@ Here's a more complex example. This used to be a part of [agility](http://cookb
680
681
  end
681
682
  end
682
683
 
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.
684
+ 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.
684
685
 
685
686
  <name-one:user complete-target="&@project" completer="new_member_name"/>
686
687
 
@@ -853,7 +854,8 @@ Use the `uri` option to specify a redirect location:
853
854
  end
854
855
  -%>
855
856
  <ul class="check-many" param="default" merge-attrs>
856
- <input type="hidden" name="#{param_name}[]" value=""/><% # ensure all items are removed when nothing checked %>
857
+ <input type="hidden" name="#{param_name}[]" value=""/><% # ensure all items are removed when nothing checked
858
+ %>
857
859
  <li repeat="&options" param>
858
860
  <input type="checkbox" name="#{param_name}[]" value="@#{this.id}" checked="&this.in?(collection)" disabled="&disabled"/>
859
861
  <name param/>
@@ -891,12 +893,13 @@ The body of the tag will be repeated for each of the current records in the coll
891
893
  -->
892
894
  <def tag="input-many" attrs="fields,skip" polymorphic>
893
895
  <set empty="&this.empty?"/>
896
+ <% 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 if this.respond_to? :proxy_reflection %>
894
897
  <ul class="input-many #{this_field.dasherize} #{css_data :input_many_prefix, param_name_for_this}">
895
898
  <li repeat class="#{'record-with-errors' unless this.errors.empty?}">
896
899
  <error-messages without-heading class="sub-record"/>
897
900
  <hidden-id-field/>
898
901
  <div class="input-many-item" param="default">
899
- <field-list merge-attrs="fields" />
902
+ <field-list merge-attrs="fields" skip="&skip"/>
900
903
  </div>
901
904
  <div class="buttons">
902
905
  <button type="button" class="remove-item" merge-attrs="disabled" param="remove-item">-</button>
@@ -904,7 +907,6 @@ The body of the tag will be repeated for each of the current records in the coll
904
907
  </div>
905
908
  </li>
906
909
  <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 %>
908
910
  <fake-field-context fake-field="0" context="&this.try.new_candidate || this.member_class.new">
909
911
  <div class="input-many-item" param="default">
910
912
  <field-list merge-attrs="fields" skip="&skip"/>
@@ -19,7 +19,7 @@
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
- <ht key="#{type_name.downcase.sub(' ', '_').pluralize}.collection.empty_message">
22
+ <ht key="#{this.member_class.name.tableize}.collection.empty_message">
23
23
  No <collection-name lowercase/> to display
24
24
  </ht>
25
25
  </div>
@@ -20,11 +20,12 @@ All of the [standard ajax attributes](/api_taglibs/rapid_forms) are also support
20
20
 
21
21
  html_attributes[:method] ||= has_params ? :get : :put
22
22
  add_classes!(html_attributes, "transition-button #{transition_name}-button")
23
- label ||= transition_name.to_s.titleize
23
+ label = ht("#{this.class.name.tableize}.actions.#{transition_name}", :default => (label || transition_name.to_s.titleize))
24
24
  url = object_url(this, transition_name, :method => html_attributes[:method])
25
25
 
26
26
  if (update || !ajax_attributes.empty?) && !has_params
27
27
  ajax_attributes[:message] ||= label
28
+ ajax_attributes[:method] = html_attributes[:method]
28
29
  func = ajax_updater(url, update, ajax_attributes)
29
30
  html_attributes.update(:onclick => "var e = this; " + func, :type =>'button', :value => label)
30
31
  element(:input, html_attributes, nil, true, true)
@@ -41,7 +42,7 @@ For example, you could use this on a `Friendship` card: the person invited to ha
41
42
  -->
42
43
  <def tag="transition-buttons">
43
44
  <div merge-attrs class="transitions">
44
- <% this.lifecycle.available_transitions_for(current_user).each do |t| %>
45
+ <% this.lifecycle.publishable_transitions_for(current_user).each do |t| %>
45
46
  <transition-button transition="&t"/>
46
47
  <% end %>
47
48
  </div>
@@ -245,7 +245,7 @@ The flash is output in a `<div class="flash notice">`, where `notice` is the `ty
245
245
  <def tag="flash-messages" attrs="names"><%=
246
246
  scope.flash_rendered = true
247
247
  names = names.nil? ? flash.keys : comma_split(names)
248
- names.map { |name| flash_message :type => name }
248
+ names.map { |name| flash_message :type => name }.join
249
249
  %></def>
250
250
 
251
251
  <!-- Renders `<div id="ajax-progress"><div><span id="ajax-progress-text"></span></div></div>`. The theme will style this as an ajax progress 'spinner' -->
@@ -93,7 +93,7 @@ This tag is in need of a review - it's a bit funky.
93
93
  scope.field_name = n == "this" ? this.member_class.try.name : n.to_s.gsub("." , "_")
94
94
  scope.field_path = n
95
95
  parameters.default
96
- end
96
+ end.join
97
97
  end
98
98
  %>
99
99
  </def>
@@ -44,5 +44,15 @@ namespace :hobo do
44
44
  END
45
45
  end
46
46
 
47
+ desc "Run the standard generators that the hobo command runs with the --invite-only option."
48
+ task :run_invite_only_generators do
49
+ exec <<-END
50
+ ruby script/generate hobo --add-routes && \
51
+ ruby script/generate hobo_rapid --import-tags --invite-only && \
52
+ ruby script/generate hobo_user_model user --invite-only && \
53
+ ruby script/generate hobo_user_controller user --invite-only && \
54
+ ruby script/generate hobo_front_controller front --delete-index --add-routes --invite-only
55
+ END
56
+ end
47
57
  end
48
58
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hobo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.100
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Locke
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-17 00:00:00 +00:00
12
+ date: 2009-12-01 00:00:00 +00:00
13
13
  default_executable: hobo
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -23,14 +23,14 @@ dependencies:
23
23
  version: 2.2.2
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
- name: mislav-will_paginate
26
+ name: will_paginate
27
27
  type: :runtime
28
28
  version_requirement:
29
29
  version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 2.2.1
33
+ version: 2.3.11
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: hobosupport
@@ -40,7 +40,7 @@ dependencies:
40
40
  requirements:
41
41
  - - "="
42
42
  - !ruby/object:Gem::Version
43
- version: 0.9.0
43
+ version: 0.9.100
44
44
  version:
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: hobofields
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - "="
52
52
  - !ruby/object:Gem::Version
53
- version: 0.9.0
53
+ version: 0.9.100
54
54
  version:
55
55
  description:
56
56
  email: tom@tomlocke.com
@@ -82,7 +82,6 @@ files:
82
82
  - lib/hobo.rb
83
83
  - lib/hobo/accessible_associations.rb
84
84
  - lib/hobo/authentication_support.rb
85
- - lib/hobo/bundle.rb
86
85
  - lib/hobo/controller.rb
87
86
  - lib/hobo/dev_controller.rb
88
87
  - lib/hobo/dryml.rb
@@ -131,6 +130,7 @@ files:
131
130
  - lib/hobo/scopes/named_scope_extensions.rb
132
131
  - lib/hobo/static_tags
133
132
  - lib/hobo/tasks/rails.rb
133
+ - lib/hobo/translations.rb
134
134
  - lib/hobo/undefined.rb
135
135
  - lib/hobo/undefined_access_error.rb
136
136
  - lib/hobo/user.rb
@@ -1,330 +0,0 @@
1
- module ::Hobo
2
-
3
- class Bundle
4
-
5
- @bundles = HashWithIndifferentAccess.new
6
-
7
- class << self
8
-
9
- # Hobo::Bundle.bundles is a hash of all instantiated bundles by name
10
- attr_accessor :bundles
11
-
12
- # Used by subclasses, e.g MyBundle.plugin is the name of the
13
- # plugin the bundle came from
14
- attr_reader :plugin
15
-
16
- attr_reader :model_declarations, :controller_declarations
17
-
18
- attr_accessor :dirname
19
-
20
- def inherited(base)
21
- filename = caller[0].match(/^(.*):\d+/)[1]
22
- base.dirname = filename.match(%r(^.*/plugins/[^/]+))[0]
23
- end
24
-
25
-
26
- def load_models_and_controllers
27
- return if models_and_controllers_loaded?
28
-
29
- @plugin = File.basename(dirname)
30
-
31
- @model_declarations = []
32
- @controller_declarations = []
33
-
34
- class_eval do
35
- eval_ruby_files("#{dirname}/models", @models)
36
- eval_ruby_files("#{dirname}/controllers", @controllers)
37
- end
38
- end
39
-
40
- def [](bundle_name)
41
- bundles[bundle_name]
42
- end
43
-
44
-
45
- private
46
-
47
- def bundle_model(name, &block)
48
- @model_declarations << [name, block]
49
- end
50
-
51
-
52
- def bundle_model_controller(model_name, &block)
53
- @controller_declarations << [model_name, block]
54
- end
55
-
56
-
57
- def models_and_controllers_loaded?
58
- @model_declarations
59
- end
60
-
61
-
62
-
63
- def eval_ruby_files(dir, filenames)
64
- files = if filenames == [:none]
65
- []
66
- elsif filenames.blank? || filenames == [:all]
67
- Dir["#{dir}/*.rb"]
68
- else
69
- filenames.map { |f| "#{dir}/#{f}.rb" }
70
- end
71
-
72
- files.each { |f| instance_eval(File.read(f), f, 1) }
73
- end
74
-
75
-
76
- # Declarations
77
-
78
- def models(*models)
79
- @models = models
80
- end
81
-
82
- def controllers(*controllers)
83
- @controllers = controllers.map {|c| case c.to_s
84
- when /controller$/, "all", "none" then c
85
- else "#{c.to_s.pluralize}_controller"
86
- end }
87
- end
88
-
89
- end
90
-
91
- def initialize(*args)
92
- caller_options = args.extract_options!
93
-
94
- self.class.load_models_and_controllers
95
- self.name = args.first || self.class.name.match(/[^:]+$/)[0].underscore
96
- Bundle.bundles[name] = self
97
-
98
- options = defaults(caller_options).with_indifferent_access
99
- options.recursive_update(caller_options)
100
-
101
- @renames, @options = separate_renames(options)
102
-
103
- includes
104
-
105
- create_models
106
- create_controllers
107
-
108
- init
109
- end
110
-
111
- attr_accessor :renames, :options, :name
112
-
113
- # optionally overridden by the bundle subclass
114
- def includes; end
115
- def init; end
116
- def defaults(options); {}; end
117
-
118
-
119
- def plugin
120
- self.class.plugin
121
- end
122
-
123
-
124
- def create_models
125
- self.class.model_declarations.each do |name, block|
126
- klass = make_class(new_name_for(name), ActiveRecord::Base)
127
-
128
- klass.meta_def :belongs_to_with_optional_polymorphism do |*args|
129
- opts = args.extract_options!
130
-
131
- if opts[:polymorphic] == :optional
132
- if bundle.options["polymorphic_#{name}"]
133
- opts[:polymorphic] = true
134
- opts.delete(:class_name)
135
- else
136
- opts.delete(:polymorphic)
137
- end
138
- end
139
- belongs_to_without_optional_polymorphism(name, opts)
140
- end
141
- klass.meta_eval { alias_method_chain :belongs_to, :optional_polymorphism }
142
-
143
- klass.class_eval { hobo_model }
144
-
145
- # FIXME this extension breaks passing a block to belongs_to
146
- klass.meta_def :belongs_to_with_alias do |*args|
147
- opts = args.extract_options!
148
- name = args.first.to_sym
149
-
150
- alias_name = opts.delete(:alias)
151
-
152
- belongs_to_without_alias(name, opts)
153
-
154
- if alias_name && name != alias_name
155
- klass.send(:alias_method, alias_name, name)
156
- # make the aliased name available in the classes metadata
157
- klass.reflections[alias_name] = klass.reflections[name]
158
- end
159
-
160
- end
161
- klass.meta_eval { alias_method_chain :belongs_to, :alias }
162
-
163
- klass.class_eval(&block)
164
- end
165
- end
166
-
167
-
168
- def create_controllers
169
- bundle = self
170
- self.class.controller_declarations.each do |model_name, block|
171
- klass = make_class("#{new_name_for(model_name).to_s.pluralize}Controller", ::ApplicationController) do
172
- hobo_model_controller
173
- end
174
- klass.class_eval(&block)
175
- end
176
- end
177
-
178
-
179
- def make_class(name, base_class, &b)
180
- bundle = self
181
- klass = Class.new(base_class) do
182
- # Nasty hack because blocks can't take blocks
183
- # Roll on Ruby 1.9
184
- def self.feature(name, &block)
185
- _feature(name, block)
186
- end
187
-
188
- def method_missing(name, *args)
189
- if name.to_s =~ /^_.*_$/
190
- self.class.bundle.magic_option(name)
191
- else
192
- super
193
- end
194
- end
195
- end
196
-
197
- klass.meta_def(:bundle) do
198
- bundle
199
- end
200
-
201
- klass.meta_def(:_feature) do |feature, block|
202
- has_feature = bundle.options[feature]
203
- if has_feature
204
- define_method("features_#{feature}?") { true }
205
- meta_def("features_#{feature}?") { true }
206
- block.call if block
207
- else
208
- define_method("features_#{feature}?") { false }
209
- meta_def("features_#{feature}?") { false }
210
- end
211
- end
212
- silence_warnings { Object.const_set(name, klass) }
213
-
214
- klass.meta_def :method_missing do |name, *args|
215
- if name.to_s =~ /^_.*_$/
216
- bundle.magic_option(name)
217
- else
218
- super
219
- end
220
- end
221
-
222
- klass.class_eval(&b) if b
223
-
224
- klass
225
- end
226
-
227
-
228
- def new_name_for(name)
229
- name = name.to_s
230
- underscore = name =~ /^[a-z]/
231
- name = name.camelize if underscore
232
-
233
- plural = !renames.has_key?(name) && (sing = name.singularize) && renames.has_key?(sing)
234
- name = sing if plural
235
-
236
- # Keep a track of names we've seen to avoid cycles
237
- seen = [ name ]
238
-
239
- name = name.gsub(/_.*?_/) { |s| new_name_for(s[1..-2]) }
240
- while (newname = renames[name])
241
- name = newname
242
- name = name.gsub(/_.*?_/) { |s| new_name_for(s[1..-2]) }
243
-
244
- break if name.in?(seen)
245
- seen << name
246
- end
247
-
248
- name = name.underscore if underscore
249
- name = name.pluralize if plural
250
- name = name.to_sym if underscore || plural
251
- name
252
- end
253
-
254
-
255
- def separate_renames(options)
256
- simple_options, renames = HashWithIndifferentAccess.new, HashWithIndifferentAccess.new
257
- options.each do |k, v|
258
- if k.to_s =~ /^[A-Z]/
259
- renames[k] = v.to_s
260
- else
261
- simple_options[k] = v
262
- end
263
- end
264
- [renames, simple_options]
265
- end
266
-
267
-
268
- def customize(name, &block)
269
- new_name_for(name).to_s.constantize.class_eval(&block)
270
- end
271
-
272
-
273
- def method_missing(name, *args)
274
- if name.to_s =~ /^_.*_$/
275
- magic_option(name)
276
- else
277
- super
278
- end
279
- end
280
-
281
-
282
- # Returns the option value or renamed class name from a 'magic'
283
- # name like _foo_ or _MyFoo_
284
- def magic_option(name)
285
- option_name = name.to_s[1..-2]
286
- if option_name == "bundle"
287
- self.name
288
- elsif options.has_key?(option_name)
289
- options[option_name]
290
- else
291
- new_name_for(option_name)
292
- end
293
- end
294
-
295
-
296
- def optional_bundle(*args)
297
- local_options = args.extract_options!
298
- class_name, option_name = args
299
- option_name ||= class_name.to_s.underscore
300
- _include_bundle(class_name, option_name, local_options) if self.options[option_name]
301
- end
302
-
303
-
304
- def include_bundle(*args)
305
- local_options = args.extract_options!
306
- class_name, option_name = args
307
- option_name ||= class_name.to_s.underscore
308
- _include_bundle(class_name, option_name, local_options)
309
- end
310
-
311
-
312
- def _include_bundle(class_name, option_name, local_options)
313
- external_options = self.options[option_name]
314
- external_options = {} if external_options.nil? || external_options == true
315
- name = "#{self.name}_#{option_name}"
316
-
317
- sub_bundle_options = external_options.merge(local_options).merge(renames)
318
- sub_bundle = class_name.to_s.constantize.new(name, sub_bundle_options)
319
-
320
- conflicting_renames = (renames.keys & sub_bundle.renames.keys).select { |k| renames[k] != sub_bundle.renames[k] }
321
- unless conflicting_renames.empty?
322
- raise ArgumentError, "Conflicting renames in included bundle '#{name}' of '#{self.name}': #{conflicting_renames * ', '}"
323
- end
324
- renames.update(sub_bundle.renames)
325
- self.options["#{option_name}_bundle"] = name
326
- end
327
-
328
- end
329
-
330
- end