A. Request to /foo/index or /foo/moreinfo always returns HTML, which
is wrapped in the layout 'page'.
B. Request to /foo/dostuff/15 does stuff, sets a 'flash' style value
(message: "I did it!") and renders /foo/index (wrapped in layout
'page').
C. Request to /foo/dostuff/15?ajax=very_yes does stuff, and returns
the message string ("I did it!") as the response in text/plain, not
wrapped in any layout.
I have requirement A working. (Go me!)
Requirement B seems straightforward enough given the Flash helper,
even though I've not tried. (Note in the "moar docs!" vein: this class
could really use a simple example showing how to set the flash value
(do you just fetch the hash and modify it?) and how to actually use
the flashbox in a template (does calling the method with no parameters
return the populated flashbox string?).)
As for requirement C, I cannot figure out how to get the response for
an action not wrapped in the layout. Things I was looking for:
* Instead of "layout 'page'", I thought I'd try something like
"layout{ 'page' unless AJAX_ACTIONS.include?( current_action ) }".
Except I can't figure out how to get information about the current
action in the layout block.
Question 1: How do I do deny_layout-like functionality on a per-action
basis?
* Set the layout to nil, and then ask specific actions to wrap
themselves in the layout. I can't see how I would put code in an
action to tell the app to wrap the action in that code when done.
Question 2: Can you, on a per-action basis other than the layout()
block, cause an action to wrap its resulting view in a layout?
* Maybe try using "provides" to somehow switch the rendering? This
would work if I hacked a file extension at the end instead of
"ajax=very_yes" on the query string. I'm not a big fan of this, since
I'm using a generic JS library that substitutes AJAX fetching when
possible, with a (hopefully harmless) extra query string parameter.
Modifying the library to inject a file extension somewhere in the URL
seems like a bad idea. Two more comments on provides:
***The file innate/example/provides.rb says:
# Since there will always be an `html` representation (the
default), you have
# to take care of it. If you simply want to return an empty page,
use following.
...which I thought meant that if you used the provide mechanism, you
must explicitly handle :html yourself. Important to note, I think,
that you do not have to do this for Ramaze apps. I'm glad that you
don't.
*** I'm rather surprised that:
def my_action( some_param )
requires a URL like "my_action/12.yaml" for provides to work, instead
of "my_action.yaml/12". (I guess that's weird, too.) I suppose in my
mind the better way to handle provides + actions with params would be
via a query string mechanism, like "my_action/12?format=yaml". Not a
big deal.
Sorry, I wandered off topic there sharing some new-user-on-an-airplane-
with-only-access-to-rdocs experience trying to figure out this
feature. Let's end with the most important question for those who skim
and don't read:
Question 3: What is a way to support all of requirements A, B and C
above?
There are several ways to do this using the layout method:
Given that your JS library does AJAX requests, it will set a header that
indicates that, so we can check for that:
layout(:page){ !request.xhr? }
Another way, using your query parameter:
layout(:page){ request[:ajax] != 'very_yes' }
But not enough with that, since we also pass parameters into the block:
layout(:page){|name, wish| !AJAX_ACTIONS.include?(name) }
I hope that answers that question :)
As usually, the code in this mail is fully untested, but might just
work.
--
^ manveru