hobo 0.9.0 → 0.9.100

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