fortitude 0.0.7-java → 0.0.9-java

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