fortitude 0.0.7-java → 0.0.9-java

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +73 -0
  3. data/CONTRIBUTORS.md +17 -0
  4. data/ext/com/fortituderuby/ext/fortitude/FortitudeNativeLibrary.java +23 -7
  5. data/ext/fortitude_native_ext/fortitude_native_ext.c +91 -54
  6. data/lib/fortitude/doctypes/html4.rb +4 -0
  7. data/lib/fortitude/doctypes/html5.rb +4 -0
  8. data/lib/fortitude/doctypes/unknown_doctype.rb +4 -0
  9. data/lib/fortitude/doctypes/xhtml10.rb +4 -0
  10. data/lib/fortitude/doctypes/xhtml11.rb +4 -0
  11. data/lib/fortitude/erector.rb +1 -0
  12. data/lib/fortitude/errors.rb +16 -0
  13. data/lib/fortitude/extensions/fortitude_ruby_ext.rb +27 -12
  14. data/lib/fortitude/method_templates/assign_locals_from_template.rb.smpl +2 -0
  15. data/lib/fortitude/method_templates/need_assignment_template.rb.smpl +2 -2
  16. data/lib/fortitude/method_templates/simple_compiled_template.rb +94 -0
  17. data/lib/fortitude/method_templates/tag_method_template.rb.smpl +4 -4
  18. data/lib/fortitude/method_templates/text_method_template.rb.smpl +2 -2
  19. data/lib/fortitude/rails/railtie.rb +5 -1
  20. data/lib/fortitude/rails/rendering_methods.rb +66 -47
  21. data/lib/fortitude/rails/template_handler.rb +0 -1
  22. data/lib/fortitude/rendering_context.rb +2 -2
  23. data/lib/fortitude/tags/tag.rb +4 -3
  24. data/lib/fortitude/version.rb +1 -1
  25. data/lib/fortitude/widget.rb +1 -1
  26. data/lib/fortitude/widget/content.rb +1 -1
  27. data/lib/fortitude/widget/integration.rb +12 -3
  28. data/lib/fortitude/widget/localization.rb +1 -37
  29. data/lib/fortitude/widget/needs.rb +41 -12
  30. data/lib/fortitude/widget/rendering.rb +25 -7
  31. data/lib/fortitude/widget/start_and_end_comments.rb +1 -0
  32. data/lib/fortitude/widget/tags.rb +2 -1
  33. data/lib/fortitude/widget/widget_class_inheritable_attributes.rb +1 -0
  34. data/lib/fortitude_jruby_native_ext.jar +0 -0
  35. data/spec/helpers/system_helpers.rb +4 -0
  36. data/spec/rails/class_loading_system_spec.rb +10 -2
  37. data/spec/rails/development_mode_system_spec.rb +91 -0
  38. data/spec/rails/erector_coexistence_system_spec.rb +16 -0
  39. data/spec/rails/layouts_system_spec.rb +8 -3
  40. data/spec/rails/rendering_system_spec.rb +24 -2
  41. data/spec/rails/templates/class_loading_system_spec/app/controllers/class_loading_system_spec_controller.rb +6 -2
  42. data/spec/rails/templates/class_loading_system_spec/app/views/class_loading_system_spec/_foo.rb +5 -0
  43. data/spec/rails/templates/class_loading_system_spec/app/views/class_loading_system_spec/bar.html.rb +5 -0
  44. data/spec/rails/templates/class_loading_system_spec/app/views/class_loading_system_spec/bar.rb +5 -0
  45. data/spec/rails/templates/class_loading_system_spec/app/views/class_loading_system_spec/foo.rb +5 -0
  46. data/spec/rails/templates/development_mode_system_spec/app/controllers/development_mode_system_spec_controller.rb +4 -0
  47. data/spec/rails/templates/development_mode_system_spec/app/views/base.rb +5 -0
  48. data/spec/rails/templates/development_mode_system_spec/app/views/development_mode_system_spec/form.rb +11 -0
  49. data/spec/rails/templates/erector_coexistence_system_spec/app/controllers/erector_coexistence_system_spec_controller.rb +16 -0
  50. data/spec/rails/templates/erector_coexistence_system_spec/app/views/erector_widget.rb +5 -0
  51. data/spec/rails/templates/erector_coexistence_system_spec/app/views/fortitude_widget.rb +5 -0
  52. data/spec/rails/templates/localization_system_spec/app/views/localization_system_spec/content_method.rb +2 -0
  53. data/spec/rails/templates/rendering_system_spec/app/controllers/rendering_system_spec_controller.rb +14 -1
  54. data/spec/rails/templates/rendering_system_spec/app/helpers/application_helper.rb +5 -0
  55. data/spec/rails/templates/rendering_system_spec/app/views/widget_to_render_class_only.rb +5 -0
  56. data/spec/rails/templates/rendering_system_spec/app/views/widget_to_render_with_helper.rb +5 -0
  57. data/spec/system/doctypes_system_spec.rb +30 -8
  58. data/spec/system/erector_compatibility_system_spec.rb +27 -0
  59. data/spec/system/localization_system_spec.rb +4 -0
  60. data/spec/system/needs_system_spec.rb +31 -0
  61. data/spec/system/rebuild_notifications_system_spec.rb +180 -85
  62. data/spec/system/setting_inheritance_system_spec.rb +47 -0
  63. data/spec/system/static_method_system_spec.rb +2 -0
  64. data/spec/system/tag_rendering_system_spec.rb +41 -0
  65. data/spec/system/void_tags_system_spec.rb +1 -0
  66. data/spec/system/yield_system_spec.rb +188 -0
  67. metadata +27 -5
  68. data/lib/fortitude/method_templates/simple_template.rb +0 -50
  69. data/spec/rails/templates/class_loading_system_spec/app/views/class_loading_system_spec/_underscore_widget.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8d58342fff5dde4206e5085e5111c2bd10275d60
4
- data.tar.gz: fe414b50a1d86fbb7504fa0dc5b45820e4c05780
3
+ metadata.gz: bfef6b124f74ca790f7b374119f5f1a2b88851d3
4
+ data.tar.gz: d74465173f9aeb5008fe0ad11f13187cd02ab7a5
5
5
  SHA512:
6
- metadata.gz: 019c7e138f27db207dc8ce479a393c1ed027f2ef2fb79523224ec0e88bf1a0245bc44fcdb23a7b9677cc4dbd8ca79bd2daaf7df083a5d60ef83c322383869cc1
7
- data.tar.gz: 9137c4f333b5b477e488e6f6f8538901205f838f00b203d3c8c08f98bdf32c442895b31174de2a56204bcf23ee57529dabdf7182fc2a55d7e0935f7735272534
6
+ metadata.gz: bb2840406f5ad37c7aae1c710cc916d43067afa793c0c797c90f4c336d77b7ed4002ced4de37282ce71f414fdebfa56398c8412c6f65512b84d5f0a1d7589049
7
+ data.tar.gz: a37f299d18af00808f3382cc4adc5ac2c91d4f08f4862fdab6f81f6190b11248d64b01fbd6fbccf047b7d28872a08f65901c81c0b0f3964b15b66cdaf3deaceb
data/CHANGES.md CHANGED
@@ -1,5 +1,78 @@
1
1
  # Fortitude Releases
2
2
 
3
+ ## 0.0.9, 20 November 2014
4
+
5
+ * Fortitude now supports passing blocks to widgets (above and beyond support for Rails' standard layouts and their
6
+ usage using `yield`). You can now do the following:
7
+
8
+ ```ruby
9
+ class Views::Foo < Views::Base
10
+ def content
11
+ p "something here"
12
+ widget Views::Bar, :name => 'Yoko' { text "hello" }
13
+ p "something else"
14
+ end
15
+ end
16
+
17
+ class Views::Bar < Views::Base
18
+ def content
19
+ p "more content"
20
+ yield
21
+ p "even more content"
22
+ end
23
+ end
24
+ ```
25
+
26
+ This will do as expected and cause `Views::Bar`'s `yield` call to call the block passed to it. Furthermore, because
27
+ it's often very useful to break a widget down into methods, and you might not want to explicitly pass the block all
28
+ over, you can call `yield_from_widget` from _any_ widget method and it will behave correctly. (This has actually
29
+ always been true in Fortitude for yielding to layouts; it just now will also yield to blocks passed into the widget
30
+ directly, too).
31
+
32
+ Fortitude first prefers a block passed in to `#widget`; it then looks for a block passed to the constructor of a
33
+ widget, and, finally, it will delegate to the layout (if any) if no other block is found. If there isn't even a
34
+ layout, you will receive an error.
35
+
36
+ Unlike Erector, Fortitude passes any arguments you give `yield` through to the widget, whether using `yield` or
37
+ `yield_from_widget`; it also passes, as the first argument, the widget instance being yielded from, too. This allows
38
+ a more elegant solution to the fact that the block is evaluated in the scope of the caller, not the wiget, and thus
39
+ may not have access to Fortitude methods (like `p`, `text`, and so on) if the caller is not itself a widget; you can
40
+ simply call those methods on the passed-in widget instance.
41
+
42
+ Thank you to [Leaf](https://github.com/leafo) for bringing up this issue!
43
+
44
+ * The exact interpretation of attribute values has changed. Along with
45
+ [considerable discussion](https://github.com/ageweke/fortitude/issues/12), it became clear that the most desirable
46
+ behavior was the following: attributes with a value of `false` or `nil` simply are not output at all (thus making
47
+ behavior like `input(:type => :checkbox, :checked => some_boolean_variable)` work properly); attributes with a
48
+ value of `true` are output as the key only (so the previous example becomes `<input type="checkbox" checked>` if
49
+ `some_boolean_variable` is `true`) &mdash; except in XHTML document types, where that would be illegal, so they
50
+ become (_e.g._) `<input type="checkbox" checked="checked">`; and attributes mapped to the empty string are output
51
+ with a value of the empty string. Many thanks to [Leaf](https://github.com/leafo) and
52
+ [Adam Becker](https://github.com/ajb) for all the discussion and validation around this!
53
+
54
+ * Multiple huge performance increases in Fortitude's class-loading time for widgets. Fortitude internally uses
55
+ dynamic compilation of many methods to achieve the very highest runtime performance; however, the system that did
56
+ this compilation could cause slow startup times if you had a very large number of widgets. Fortitude now lazy-
57
+ compiles some methods and caches its own internal trivial template language in order to make startup much faster
58
+ without slowing down critical runtime performance. Many thanks to [Leaf](https://github.com/leafo) for reporting this
59
+ issue and testing a number of fixes for it as they were made!
60
+
61
+ * Fixed a number of bugs in Fortitude's support for `render :widget => ...`, including use of helpers, coexistence
62
+ with Erector, and being able to pass a widget class rather than an already-instantiated widget. Many thanks to
63
+ [Leaf](https://github.com/leafo) for the detailed bug report, suggestions for fixes, and pointers to new methods that
64
+ made the implementation much more robust.
65
+
66
+ ## 0.0.8, 13 November 2014
67
+
68
+ * Fixed an issue where repeated reloading of a view in development mode in Rails could cause an error of the form
69
+ `superclass mismatch for class MyView`. (The issue was that Fortitude was calling `require_dependency` on the view
70
+ `.rb` file in the template handler, which caused it to get loaded outside of the scope where Rails is watching for
71
+ loaded constants, so that it can unload them before the next request. This caused view classes to hang around
72
+ forever, but not necessarily their superclasses, causing a very confusing `superclass mismatch` error.) Many thanks
73
+ again to [Jacob Maine](https://github.com/mainej) for the very detailed bug report and collaboration to fix the
74
+ issue.
75
+
3
76
  ## 0.0.7, 11 November 2014
4
77
 
5
78
  * Fortitude 0.0.6 introduced a regression, where referring to an autoloaded view class by partially-qualified namespace
@@ -6,3 +6,20 @@ Fortitude is written by [Andrew Geweke](https://github.com/ageweke), with contri
6
6
  `gem install fortitude` works properly no matter which platform you're on.
7
7
  * [Roman Heinrich](https://github.com/mindreframer): reporting a bug where trying to use Fortitude as a Tilt
8
8
  engine to render would fail if the locals passed in were `nil`.
9
+ * [Jacob Maine](https://github.com/mainej):
10
+ * Reporting the lack of `ActionMailer` support for Fortitude, and offering a patch to add it;
11
+ * Reporting a bug where view classes ending in `.html.rb` would encounter classloading issues
12
+ (resulting in `uninitialized constant` or `superclass mismatch` errors) in development mode.
13
+ * [Leaf](https://github.com/leafo) for:
14
+ * Reporting slow widget classloading in very large systems due to eager, not lazy, complication of `needs`-related
15
+ methods, and significant work helping determine that widget localization support was a major source of slowness
16
+ here.
17
+ * Reporting the need for support for passing blocks to `widget`, and thus being able to `yield` from one widget
18
+ to another.
19
+ * Discussion and details around exactly what `:attribute => true`, `:attribute => false`, and so on should render
20
+ from Fortitude.
21
+ * Reporting multiple bugs in support for `render :widget => ...`, and many useful pointers to possible fixes and
22
+ additional methods to make the implementation a lot more robust.
23
+ * [Adam Becker](https://github.com/ajb) for:
24
+ * Discussion and details around exactly what `:attribute => true`, `:attribute => false`, and so on should render
25
+ from Fortitude.
@@ -3,6 +3,7 @@ package com.fortituderuby.ext.fortitude;
3
3
  import java.io.IOException;
4
4
  import org.jruby.Ruby;
5
5
  import org.jruby.RubyBasicObject;
6
+ import org.jruby.RubyBoolean;
6
7
  import org.jruby.RubyArray;
7
8
  import org.jruby.RubyClass;
8
9
  import org.jruby.RubyFixnum;
@@ -159,13 +160,15 @@ public class FortitudeNativeLibrary implements Library {
159
160
  public final ThreadContext threadContext;
160
161
  public final RubyString prefix;
161
162
  public final RubyString output;
163
+ public final RubyBoolean allowsBareAttributes;
162
164
 
163
165
  public static final byte[] EQUALS_QUOTE = new byte[] { (byte) '=', (byte) '"' };
164
166
 
165
- public AppendKeyAndValueVisitor(ThreadContext threadContext, RubyString prefix, RubyString output) {
167
+ public AppendKeyAndValueVisitor(ThreadContext threadContext, RubyString prefix, RubyString output, RubyBoolean allowsBareAttributes) {
166
168
  this.threadContext = threadContext;
167
169
  this.prefix = prefix;
168
170
  this.output = output;
171
+ this.allowsBareAttributes = allowsBareAttributes;
169
172
  }
170
173
 
171
174
  public void visit(IRubyObject key, IRubyObject value) {
@@ -181,7 +184,9 @@ public class FortitudeNativeLibrary implements Library {
181
184
  }
182
185
 
183
186
  newPrefix.cat('-');
184
- fortitude_append_as_attributes(threadContext, value, output, newPrefix);
187
+ fortitude_append_as_attributes(threadContext, value, output, newPrefix, this.allowsBareAttributes);
188
+ } else if ((value instanceof RubyNil) || ((value instanceof RubyBoolean) && (! value.isTrue()))) {
189
+ // nothing here
185
190
  } else {
186
191
  output.cat(' ');
187
192
 
@@ -192,15 +197,26 @@ public class FortitudeNativeLibrary implements Library {
192
197
  }
193
198
 
194
199
  fortitude_append_to(key, output);
195
- output.cat(EQUALS_QUOTE);
196
- fortitude_append_to(value, output);
197
- output.cat('"');
200
+
201
+ if ((value instanceof RubyBoolean) && (value.isTrue())) {
202
+ if (this.allowsBareAttributes.isTrue()) {
203
+ // ok, nothing here
204
+ } else {
205
+ output.cat(EQUALS_QUOTE);
206
+ fortitude_append_to(key, output);
207
+ output.cat('"');
208
+ }
209
+ } else {
210
+ output.cat(EQUALS_QUOTE);
211
+ fortitude_append_to(value, output);
212
+ output.cat('"');
213
+ }
198
214
  }
199
215
  }
200
216
  }
201
217
 
202
218
  @JRubyMethod(name = "fortitude_append_as_attributes")
203
- public static IRubyObject fortitude_append_as_attributes(ThreadContext context, IRubyObject self, IRubyObject output, IRubyObject prefix) {
219
+ public static IRubyObject fortitude_append_as_attributes(ThreadContext context, IRubyObject self, IRubyObject output, IRubyObject prefix, IRubyObject allowsBareAttributes) {
204
220
  if (! (output instanceof RubyString)) {
205
221
  RaiseException exception = runtime.newArgumentError("You can only append to a String (this is a native (Java) method)");
206
222
  throw exception;
@@ -213,7 +229,7 @@ public class FortitudeNativeLibrary implements Library {
213
229
  throw exception;
214
230
  }
215
231
 
216
- AppendKeyAndValueVisitor visitor = new AppendKeyAndValueVisitor(context, (RubyString) prefix, (RubyString) output);
232
+ AppendKeyAndValueVisitor visitor = new AppendKeyAndValueVisitor(context, (RubyString) prefix, (RubyString) output, (RubyBoolean) allowsBareAttributes);
217
233
 
218
234
  ((RubyHash) self).visitAll(visitor);
219
235
 
@@ -3,7 +3,7 @@
3
3
  void Init_fortitude_native_ext();
4
4
 
5
5
  VALUE method_append_escaped_string(VALUE self, VALUE rb_output);
6
- VALUE method_append_as_attributes(VALUE self, VALUE rb_output, VALUE prefix);
6
+ VALUE method_append_as_attributes(VALUE self, VALUE rb_output, VALUE prefix, VALUE allows_bare_attributes);
7
7
 
8
8
  void Init_fortitude_native_ext() {
9
9
  VALUE string_class, hash_class;
@@ -12,7 +12,7 @@ void Init_fortitude_native_ext() {
12
12
  rb_define_method(string_class, "fortitude_append_escaped_string", method_append_escaped_string, 1);
13
13
 
14
14
  hash_class = rb_const_get(rb_cObject, rb_intern("Hash"));
15
- rb_define_method(hash_class, "fortitude_append_as_attributes", method_append_as_attributes, 2);
15
+ rb_define_method(hash_class, "fortitude_append_as_attributes", method_append_as_attributes, 3);
16
16
  }
17
17
 
18
18
  #define BUF_SIZE 256
@@ -145,85 +145,122 @@ void fortitude_append_to(VALUE object, VALUE rb_output) {
145
145
  }
146
146
  }
147
147
 
148
- struct fortitude_prefix_and_output {
148
+ struct fortitude_append_key_and_value_data {
149
149
  VALUE prefix;
150
150
  VALUE rb_output;
151
+ VALUE allows_bare_attributes;
151
152
  };
152
153
 
153
- int fortitude_append_key_and_value(VALUE key, VALUE value, VALUE prefix_and_output_value) {
154
- struct fortitude_prefix_and_output * prefix_and_output = (struct fortitude_prefix_and_output *)prefix_and_output_value;
154
+ int fortitude_append_key_and_value(VALUE key, VALUE value, VALUE key_and_value_data_param) {
155
+ struct fortitude_append_key_and_value_data * key_and_value_data = (struct fortitude_append_key_and_value_data *)key_and_value_data_param;
155
156
 
156
- VALUE prefix = prefix_and_output->prefix;
157
- VALUE rb_output = prefix_and_output->rb_output;
157
+ VALUE prefix = key_and_value_data->prefix;
158
+ VALUE rb_output = key_and_value_data->rb_output;
159
+ VALUE allows_bare_attributes = key_and_value_data->allows_bare_attributes;
158
160
 
159
- if (TYPE(value) == T_HASH) {
160
- VALUE new_prefix_as_string;
161
- ID dup;
162
- ID to_s;
161
+ VALUE new_prefix_as_string;
162
+ ID dup;
163
+ ID to_s;
163
164
 
164
- #ifdef CONST_ID
165
- CONST_ID(dup, "dup");
166
- CONST_ID(to_s, "to_s");
167
- #else
168
- dup = rb_intern("dup");
169
- to_s = rb_intern("to_s");
170
- #endif
165
+ switch(TYPE(value)) {
166
+ case T_HASH:
167
+ #ifdef CONST_ID
168
+ CONST_ID(dup, "dup");
169
+ CONST_ID(to_s, "to_s");
170
+ #else
171
+ dup = rb_intern("dup");
172
+ to_s = rb_intern("to_s");
173
+ #endif
174
+
175
+ switch (TYPE(prefix)) {
176
+ case T_STRING:
177
+ new_prefix_as_string = rb_funcall(prefix, dup, 0);
178
+ fortitude_append_to(key, new_prefix_as_string);
179
+ break;
180
+
181
+ case T_NIL:
182
+ new_prefix_as_string = rb_str_new("", 0);
183
+ fortitude_append_to(key, new_prefix_as_string);
184
+ break;
185
+
186
+ default:
187
+ rb_raise(rb_eArgError, "You can only use a String as a prefix (this is a native (C) method)");
188
+ break;
189
+ }
171
190
 
172
- switch (TYPE(prefix)) {
173
- case T_STRING:
174
- new_prefix_as_string = rb_funcall(prefix, dup, 0);
175
- fortitude_append_to(key, new_prefix_as_string);
176
- break;
191
+ rb_str_cat2(new_prefix_as_string, "-");
192
+ method_append_as_attributes(value, rb_output, new_prefix_as_string, allows_bare_attributes);
193
+ break;
177
194
 
178
- case T_NIL:
179
- new_prefix_as_string = rb_str_new("", 0);
180
- fortitude_append_to(key, new_prefix_as_string);
181
- break;
195
+ case T_NIL:
196
+ case T_FALSE:
197
+ break;
182
198
 
183
- default:
184
- rb_raise(rb_eArgError, "You can only use a String as a prefix (this is a native (C) method)");
185
- break;
186
- }
199
+ case T_TRUE:
200
+ rb_str_cat2(rb_output, " ");
187
201
 
188
- rb_str_cat2(new_prefix_as_string, "-");
189
- method_append_as_attributes(value, rb_output, new_prefix_as_string);
190
- } else {
191
- rb_str_cat2(rb_output, " ");
202
+ switch (TYPE(prefix)) {
203
+ case T_STRING:
204
+ rb_str_append(rb_output, prefix);
205
+ break;
192
206
 
193
- switch (TYPE(prefix)) {
194
- case T_STRING:
195
- rb_str_append(rb_output, prefix);
196
- break;
207
+ case T_NIL:
208
+ break;
197
209
 
198
- case T_NIL:
199
- break;
210
+ default:
211
+ rb_raise(rb_eArgError, "You can only use a String as a prefix (this is a native (C) method)");
212
+ break;
213
+ }
200
214
 
201
- default:
202
- rb_raise(rb_eArgError, "You can only use a String as a prefix (this is a native (C) method)");
203
- break;
204
- }
215
+ fortitude_append_to(key, rb_output);
216
+ if (TYPE(allows_bare_attributes) == T_TRUE) {
217
+ /* ok */
218
+ } else {
219
+ rb_str_cat2(rb_output, "=\"");
220
+ fortitude_append_to(key, rb_output);
221
+ rb_str_cat2(rb_output, "\"");
222
+ }
223
+ break;
205
224
 
206
- fortitude_append_to(key, rb_output);
207
- rb_str_cat2(rb_output, "=\"");
208
- fortitude_append_to(value, rb_output);
209
- rb_str_cat2(rb_output, "\"");
225
+ default:
226
+ rb_str_cat2(rb_output, " ");
227
+
228
+ switch (TYPE(prefix)) {
229
+ case T_STRING:
230
+ rb_str_append(rb_output, prefix);
231
+ break;
232
+
233
+ case T_NIL:
234
+ break;
235
+
236
+ default:
237
+ rb_raise(rb_eArgError, "You can only use a String as a prefix (this is a native (C) method)");
238
+ break;
239
+ }
240
+
241
+ fortitude_append_to(key, rb_output);
242
+ rb_str_cat2(rb_output, "=\"");
243
+ fortitude_append_to(value, rb_output);
244
+ rb_str_cat2(rb_output, "\"");
245
+ break;
210
246
  }
211
247
 
212
248
  return 0;
213
249
  }
214
250
 
215
251
 
216
- VALUE method_append_as_attributes(VALUE self, VALUE rb_output, VALUE prefix) {
217
- struct fortitude_prefix_and_output prefix_and_output;
252
+ VALUE method_append_as_attributes(VALUE self, VALUE rb_output, VALUE prefix, VALUE allows_bare_attributes) {
253
+ struct fortitude_append_key_and_value_data key_and_value_data;
218
254
 
219
255
  if (TYPE(rb_output) != T_STRING) {
220
256
  rb_raise(rb_eArgError, "You can only append to a String (this is a native (C) method)");
221
257
  }
222
258
 
223
- prefix_and_output.prefix = prefix;
224
- prefix_and_output.rb_output = rb_output;
259
+ key_and_value_data.prefix = prefix;
260
+ key_and_value_data.rb_output = rb_output;
261
+ key_and_value_data.allows_bare_attributes = allows_bare_attributes;
225
262
 
226
- rb_hash_foreach(self, fortitude_append_key_and_value, (VALUE) &prefix_and_output);
263
+ rb_hash_foreach(self, fortitude_append_key_and_value, (VALUE) &key_and_value_data);
227
264
  return Qnil;
228
265
  }
229
266
 
@@ -13,6 +13,10 @@ module Fortitude
13
13
  false
14
14
  end
15
15
 
16
+ def allows_bare_attributes?
17
+ true
18
+ end
19
+
16
20
  def close_void_tags_must_be
17
21
  false
18
22
  end
@@ -16,6 +16,10 @@ module Fortitude
16
16
  false
17
17
  end
18
18
 
19
+ def allows_bare_attributes?
20
+ true
21
+ end
22
+
19
23
  def close_void_tags_must_be
20
24
  nil
21
25
  end
@@ -15,6 +15,10 @@ module Fortitude
15
15
  def needs_cdata_in_javascript_tag?
16
16
  false
17
17
  end
18
+
19
+ def allows_bare_attributes?
20
+ true
21
+ end
18
22
  end
19
23
  end
20
24
  end
@@ -12,6 +12,10 @@ module Fortitude
12
12
  true
13
13
  end
14
14
 
15
+ def allows_bare_attributes?
16
+ false
17
+ end
18
+
15
19
  def close_void_tags_must_be
16
20
  true
17
21
  end
@@ -16,6 +16,10 @@ module Fortitude
16
16
  true
17
17
  end
18
18
 
19
+ def allows_bare_attributes?
20
+ false
21
+ end
22
+
19
23
  def close_void_tags_must_be
20
24
  true
21
25
  end
@@ -23,6 +23,7 @@ module Fortitude
23
23
 
24
24
  def is_erector_widget_class?(widget_class)
25
25
  return false unless is_erector_available?
26
+ return false unless widget_class.kind_of?(::Class)
26
27
  return true if widget_class == ::Erector::Widget
27
28
  return false if widget_class == ::Object
28
29
  return is_erector_widget_class?(widget_class.superclass)
@@ -149,5 +149,21 @@ you simply need to convert these to "p :class => :some_class" or
149
149
  @tag_name = tag_name
150
150
  end
151
151
  end
152
+
153
+ class NoBlockToYieldTo < Base
154
+ attr_reader :widget
155
+
156
+ def initialize(widget)
157
+ super(%{You're trying to call 'yield' (or 'yield_from_widget', or the Erector-compatibility method 'call_block')
158
+ from the widget #{widget}; however, there is nothing to yield to. Fortitude
159
+ looks for something to yield to in this order:
160
+ 1. A block passed to a yield at render time directly (usually via the 'widget' call);
161
+ 2. A block passed to the constructor of the widget;
162
+ 3. The layout the widget is being rendered in.
163
+ None of these exist here, and so calling 'yield', 'yield_from_widget', or 'call_block' is an
164
+ undefined operation.})
165
+ @widget = widget
166
+ end
167
+ end
152
168
  end
153
169
  end