# Fortitude Releases ## 0.0.10, 25 November 2014 * Fixed an issue where `#capture` was not working properly if you rendered a widget using `render :widget =>` in a controller. The fix further simplifies Fortitude's support for that feature and integrates even more correctly with Rails in that way. (Thanks to [Leaf](https://github.com/leafo) for the bug report!) * Fixed an issue where, if you overrode a "needs" method in a class, subclasses of that class would not use the overridden method, but instead access the "needs" method directly. (Thanks to [Leaf](https://github.com/leafo) for the bug report!) * Fixed a simple mistake that meant the module Fortitude uses to declare `needs` methods was not given a name at all, and instead the module it uses to declare helpers was given two names, one of them incorrect. (Thanks to [Leaf](https://github.com/leafo) for catching this.) * When you're invoking a widget from another widget using the `#widget` method, and you pass a block, that block is evaluated in the context of the parent widget. (This has always been true.) However, this meant that something like the following was impossible, where you're effectively defining new DSL on a widget-by-widget basis: ```ruby class Views::ModalDialog < Views::Base needs :title def content h3 "Modal: #{title}" yield button "Submit" end def modal_header(name) h5 "Modal header: #{name}" hr end end class Views::MyView < Views::Base needs :username def content h1 "User #{username}" widget Views::ModalDialog, :title => "User Settings" do modal_header "Settings for #{username}" input :type => :text, :name => :email ... end end end ``` The problem arises because, within the block in `Views::MyView#content`, you want to be able to access methods from two contexts: the parent widget (for `#username`), and the child widget (for `#modal_header`). Ruby provides no single, simple way to do this, but, without it, it's very difficult to come up with a truly elegant DSL for cases like this. Fortitude now supports this via a small bit of `method_missing` magic: the block passed to a widget is still evaluated in the context of the parent, but, if a method is called that is not present, Fortitude looks for that method in the child widget and invokes it there, if present. This allows the above situation, which is important for writing libraries that "feel right" to a Ruby programmer. (The fact that the block is evaluated primarily in the context of the parent widget, like all other Ruby blocks, preserves important standard Ruby semantics, and also means that the onus is on the author of a feature like `Views::ModalDialog` to present method names that are unlikely to conflict with those in use in parent widgets — which seems correct.) * You can now render Erector widgets from Fortitude widgets using just `widget MyErectorWidget`, and vice-versa, using either the class-and-assigns or instantiated-widget calling conventions. Note that this integration is not 100% perfect; in particular, passing a block from a Fortitude widget to an Erector widget, or vice-versa, is likely to fail or produce incorrect output due to the way Erector manipulates output buffers. However, the simple case of invoking a widget from another works fine, and can be very useful to those migrating to Fortitude. (Thanks to [Adam Becker](https://github.com/ajb) for the bug report!) * Fixed an issue where Fortitude could write the close tag of an element to the wrong output buffer if the output buffer was changed inside the element (as can happen with, among other things, Rails' `cache` method). This could cause the output HTML to be structured improperly. (Thanks to [Leaf](https://github.com/leafo) for the bug report,tracking down the exact cause, and providing the fix!) ## 0.0.9, 20 November 2014 * Fortitude now supports passing blocks to widgets (above and beyond support for Rails' standard layouts and their usage using `yield`). You can now do the following: ```ruby class Views::Foo < Views::Base def content p "something here" widget Views::Bar, :name => 'Yoko' { text "hello" } p "something else" end end class Views::Bar < Views::Base def content p "more content" yield p "even more content" end end ``` This will do as expected and cause `Views::Bar`'s `yield` call to call the block passed to it. Furthermore, because it's often very useful to break a widget down into methods, and you might not want to explicitly pass the block all over, you can call `yield_from_widget` from _any_ widget method and it will behave correctly. (This has actually always been true in Fortitude for yielding to layouts; it just now will also yield to blocks passed into the widget directly, too). Fortitude first prefers a block passed in to `#widget`; it then looks for a block passed to the constructor of a widget, and, finally, it will delegate to the layout (if any) if no other block is found. If there isn't even a layout, you will receive an error. Unlike Erector, Fortitude passes any arguments you give `yield` through to the widget, whether using `yield` or `yield_from_widget`; it also passes, as the first argument, the widget instance being yielded from, too. This allows a more elegant solution to the fact that the block is evaluated in the scope of the caller, not the wiget, and thus may not have access to Fortitude methods (like `p`, `text`, and so on) if the caller is not itself a widget; you can simply call those methods on the passed-in widget instance. Thank you to [Leaf](https://github.com/leafo) for bringing up this issue! * The exact interpretation of attribute values has changed. Along with [considerable discussion](https://github.com/ageweke/fortitude/issues/12), it became clear that the most desirable behavior was the following: attributes with a value of `false` or `nil` simply are not output at all (thus making behavior like `input(:type => :checkbox, :checked => some_boolean_variable)` work properly); attributes with a value of `true` are output as the key only (so the previous example becomes `` if `some_boolean_variable` is `true`) — except in XHTML document types, where that would be illegal, so they become (_e.g._) ``; and attributes mapped to the empty string are output with a value of the empty string. Many thanks to [Leaf](https://github.com/leafo) and [Adam Becker](https://github.com/ajb) for all the discussion and validation around this! * Multiple huge performance increases in Fortitude's class-loading time for widgets. Fortitude internally uses dynamic compilation of many methods to achieve the very highest runtime performance; however, the system that did this compilation could cause slow startup times if you had a very large number of widgets. Fortitude now lazy- compiles some methods and caches its own internal trivial template language in order to make startup much faster without slowing down critical runtime performance. Many thanks to [Leaf](https://github.com/leafo) for reporting this issue and testing a number of fixes for it as they were made! * Fixed a number of bugs in Fortitude's support for `render :widget => ...`, including use of helpers, coexistence with Erector, and being able to pass a widget class rather than an already-instantiated widget. Many thanks to [Leaf](https://github.com/leafo) for the detailed bug report, suggestions for fixes, and pointers to new methods that made the implementation much more robust. ## 0.0.8, 13 November 2014 * Fixed an issue where repeated reloading of a view in development mode in Rails could cause an error of the form `superclass mismatch for class MyView`. (The issue was that Fortitude was calling `require_dependency` on the view `.rb` file in the template handler, which caused it to get loaded outside of the scope where Rails is watching for loaded constants, so that it can unload them before the next request. This caused view classes to hang around forever, but not necessarily their superclasses, causing a very confusing `superclass mismatch` error.) Many thanks again to [Jacob Maine](https://github.com/mainej) for the very detailed bug report and collaboration to fix the issue. ## 0.0.7, 11 November 2014 * Fortitude 0.0.6 introduced a regression, where referring to an autoloaded view class by partially-qualified namespace path could cause an `Errno::ENOENT` exception indicating that a particular directory wasn't found. ## 0.0.6, 11 November 2014 * Fixed an issue where naming a widget with an `.html.rb` extension (for example) at the end would work at first, but cause really irritating errors (like `uninitialized constant Views::Foo::Bar` apparently _in_ the very file that defines `Views::Foo::Bar` correctly in `app/views/foo/bar.html.rb`) when editing code in development mode. (Thanks to [Jacob Maine](https://github.com/mainej) for the very detailed bug report!) * Fixed an issue where trying to use Fortitude as a Tilt engine, but passing `nil` for the `locals`, would cause an exception. (Thanks to [Roman Heinrich](https://github.com/mindreframer) for reporting the bug!) * Using Fortitude as a template engine for mailers (`ActionMailer::Base` subclasses) now works. (Believe it or not, this was almost completely an issue of forgetting to support this, rather than it being undone — the code was complete, and it was just a matter of applying it to `ActionMailer::Base` as well as `ActionController::Base`.) (Thanks to [Jacob Maine](https://github.com/mainej) for the bug report and pull request!) * The various on-the-fly modules that Fortitude creates and mixes in to widgets (and define helpers, tag methods, and `needs` methods) now all have actual names, which makes them much easier to identify in debugging printouts. * The code in `spec/` that knew how to reliably create, maintain, shut down, and otherwise manipulate an external `rails server` process has now been pulled out into its own gem, `oop_rails_server`; this is so I can also use it with a new, closely-related upcoming project, and because reuse is good. ;) * Updated the Travis configuration to the very latest Ruby and Rails versions. ## 0.0.5, 22 September 2014 * You can now load both Fortitude and Erector at the same time into a project, and it will "just work": Erector widgets will render using Erector, and Fortitude widgets will render using Fortitude. (Fortitude takes over the actual template engine registration for `.rb` files, and uses a trick to keep Erector from displacing it; it then looks at the widget class being rendered, and delegates all Erector rendering directly to Erector.) * When inside a widget, you can now render a sub-widget using `widget MyWidget.new(...)` — _i.e._, passing an actual widget instance — or using `widget MyWidget, { :param1 => value1 }` — _i.e._, passing a widget class and a `Hash` of assignments (which can be omitted if the widget doesn't have any `need`s). * Fixed an issue where, _e.g._, calling `#render_to_string` on a Fortitude widget within a Rails controller, and then also rendering a Fortitude widget as the template for that action, would cause a method to be called on `nil`. * Added `Fortitude::RenderingContext#parent_widget`, which returns the parent widget of the current widget during rendering at runtime. (In other words, this is not the superclass of the current widget, but the widget that caused this widget to get rendered, using either `Fortitude::Widget#widget` or `render :partial => ...`.) This can, of course, be `nil` if there is no current parent widget. * Added `Fortitude::Widget.all_fortitude_superclasses`, which returns an `Array` of all superclasses of a widget up to, but not including, `Fortitude::Widget` itself. * Added `Fortitude::Widget.widget_class_from_file`, which accepts the path to a file and an array of "root" directories to look under (_i.e._, assuming you're using something like Rails' autoloading mechanism), and returns the `Class` object for the widget that's contained in that file. This uses a series of mechansims to try to detect the class that's present in the file: a "magic comment" that can be present in the file, an array of class names to try that you can pass in, the position of the class in the file hierarchy, and scanning the source text itself. * Added a `record_tag_emission` class-level setting that tells a widget to call `#emitting_tag!` on the `Fortitude::RenderingContext` when emitting a tag; you can use this to build various systems that need to know where in the hierarchy of tags we are at the moment. * The object being returned from Fortitude tag methods — which, in general, you should never use — now inherits from `Object`, not `BasicObject`, so that some built-in methods like `#is_a?` can be safely called on it. This is for use in some users' environments doing funny things with the Ruby runtime that end up calling methods like that on the return values of widget `#content` methods, which very often just end up being the tag return value object. ## 0.0.4, 24 June 2014 * Added support for building a JRuby-specific gem to the gemspec, so that things work smoothly for JRuby users. (Thanks, [Ahto Jussila](https://github.com/ahto)!) * Added preliminary support for inline widget classes: if you call `.inline_subclass` on any subclass of `Fortitude::Widget` and pass a block, you'll get back a new subclass of whatever class you called it on, with a `content` method defined as per the block you passed. For example: my_widget_class = Fortitude::Widgets::Html5.inline_subclass do p "hello, world!" end my_widget_class.new.to_html # => '
hello, world!
' * And, similarly, if you call `.inline_html` on any subclass of `Fortitude::Widget` and pass a block, you'll get back the HTML rendered by the new subclass of that class. For example: html = Fortitude::Widgets::Html5.inline_html do p "hello, world!" end html # => 'hello, world!
' * Note that this will not work on `Fortitude::Widget`, because `Fortitude::Widget` has no `doctype` declared, and therefore has no HTML tags available. You can either use one of the pre-made classes in `Fortitude::Widgets`, or, better yet, declare your own base widget class and then use `.inline_subclass` and `.inline_html` on that. (Using that mechanism, you can also set things like `format_output`, `start_and_end_comments`, and even things like `needs`, mixing in or defining helper methods, and so on, and it will all work just fine.) ## 0.0.3, 23 June 2014 * Changed `Fortitude::Widget#to_html` to return the generated HTML. If you pass a `Fortitude::RenderingContext` into this method that has previously been used to render other HTML, you'll get all HTML (old and new) both, because we always append to a single output buffer — but that should be a corner case at most. ## 0.0.2, 21 June 2014 * Void tags (those that can't take content, ever, like `