Rails Views, Getting In Context
In the view, you need to set the context parameter. If you’re using link_to_remote, just set it manually. If you’re using a form, you can use the context_tag helper. Here’s examples of both in action:
<%= link_to_remote "Complete", :url => {:controller => 'items', :action => 'update', :id => item, :params =>{:complete=>true,:_context => "Workflow One"}} %>
<% remote_form_for :item, item, :url => {:controller => 'items', :action => 'update', :id => item} do |f| %>
<%= context_tag "Workflow Two" %>
<%= check_box_tag :complete, true %>
<!-- Other Stuff Here -->
<% end %>
Both of these hit one action, update. In it, we can use in_context to wrap our separate renders (mixing with respondto).
def update
# Update stuff here
respond_to do |format|
format.html
format.js do
render :update do |page|
# Stuff at this point happens regardless of context
in_context do |context|
context.nil? do
# This happens if no context is passed
end
context.workflow_one do
# For the link
end
context.workflow_two do
# For the form
end
end
end
end
end
end
If this looks like something that might help out, feel free to get it at http://svn.codefluency.com/rails/plugins/context. I’ll put it up on the Plugins page for installation via script/plugin install once the page editing is working again (it’s giving me a 500 error at the moment).
As usual, you can drop me a line if you have questions, suggestions, or comments.
So, here’s the problem. Let’s say that, in our application, we have different types of users that need to be able to do the same thing from different places. Their workflows are different– maybe one manages a list of items that need to be completed (they sit on that page, all day long, doing just that), and another visits each item’s page separately (in the process of managing more of the item’s information) and may complete items individually from that interface.
We need to support both ways of completing items– or maybe even more, and we want completion to occur via AJAX. Support for multiple workflows is a natural feature of complex products; the messy truth is that, sometimes, there’s no One Interface to Rule Them All. The land of picky users with long- established workflows, sadly, is not a minimalist Utopia.
Of course, if all our workflows are hitting the same controller action, the action needs to be aware of the context– different javascript may need to be returned for each workflow (we might reload a div in one case, and remove the item from a list in another, for example). We could just have a different action to support each interface– but that’s a bad kludge I won’t even address. I support the single-action, selective-render approach for the same reason I use respond_to instead of having separate actions for HTML and JS requests– sure, it might be verbose, but at least it’s DRY.
So, how do we let our action know the context from which it’s being called? There’s really not a clean option, since relying on referer is a bad idea (not to mention not enough information), but one approach– the one I use– is to pass along a parameter in requests, and have the action check for it, rendering the correct response. Since this can be a bit tedious (not to mention ugly) in practice, I’ve put together a little plugin called context to help out. Here’s how to use it.






