Topic: How to analyze a request?

Consider this:

class Task < ARB
  belongs_to :project
  belongs_to :user
  def change_status(state)
    update_attribute(:status, state)
  end
end

class TaskController < AC
  def change_status
    @posted_task = Task.find(params[:id])
    @posted_task.change_status(params[:status])
  end
end


I can do one of two things w/ a Task object: display tasks for a particular project, or display tasks for a particular user. In either case, tasks are grouped into pending tasks and completed tasks. I provide the ability to change the task status from pending to complete via a check box click that triggers an Ajax call like this:
# update the status of task with id 10 to ongoing
http://localhost:9002/task/change_status/10?status=ongoing

I am using an rjs template (change_status.rjs) to update the page once a user has changed the status of a task. Something like this works fine for updating the page when you're looking at the tasks for a user:
page[:pending_task_list].replace_html :partial => 'pending_task', :collection => @task.user.pending_tasks
page[:completed_task_list].replace_html :partial => 'completed_task', :collection => @task.user.completed_tasks

Here's the rub though: in an effort to keep things DRY, I want to use the same .rjs file to update the page for both the user task list view and project task list view. So, the question becomes, how can I dynamically determine the collection to use within the RJS file? i was thinking something like this:
# task controller
def change_status
  @posted_task = Task.find(params[:id])
  @posted_task.change_status(params[:status])
  if coming from /task/user/
    @pending_collection = @task.user.pending_tasks
    @completed_collection = @task.user.completed_tasks
  else #coming from /task/project/
    @pending_collection = @task.project.pending_tasks
    @completed_collection = @task.project.completed_tasks
  end
end

Then I would modify the RJS file like so:
page[:pending_task_list].replace_html :partial => 'pending_task', :collection => @pending_collection
page[:completed_task_list].replace_html :partial => 'completed_task', :collection => @completed_collection

So, to end this novel, in the change_status action of the task controller, how can I analyze the request to see where the request is coming from? Or, is there a better way to do this?

Last edited by gmacgregor (2007-01-29 00:03:55)

Re: How to analyze a request?

You'll need to pass a parameter when calling the change_status action. You can then look at the parameter to determine the tasks to redisplay.

def change_status
  @posted_task = Task.find(params[:id])
  @posted_task.change_status(params[:status])
  if params[:from] == "user"
    @pending_collection = @task.user.pending_tasks
    @completed_collection = @task.user.completed_tasks
  else
    @pending_collection = @task.project.pending_tasks
    @completed_collection = @task.project.completed_tasks
  end
end

I wish there was a more elegant way, but I can't think of one at the moment.

Railscasts - Free Ruby on Rails Screencasts

Re: How to analyze a request?

Funny... I thought of the exact same thing not seconds after posting! I even decided to use the same param that you have in your example -- "from"!

Here's a weird one for you though. My change_status.rjs file looks like this now:

page[:pending_task_list].replace_html :partial => 'pending_task', :collection => @pending_collection
page[:completed_task_list].replace_html :partial => 'completed_task', :collection =>@completed_collection
page.visual_effect :highlight, "task_#{@posted_task.id}", :duration => '0.5', :endcolor => "\'#262626\'"

I can change the status of tasks but the RJS never seems to execute -- in other words, the partials never update and the task is never highlighted. If I remove change_status.rjs and modify my controller like this:
 def change_status
    @posted_task = Task.find(params[:id])
    @posted_task.change_status(params[:status])
    if params[:from] == "user"
      @pending_collection = @posted_task.user.pending_tasks
      @completed_collection = @posted_task.user.completed_tasks
    else
      @pending_collection = @posted_task.project.pending_tasks
      @completed_collection = @posted_task.project.completed_tasks
    end
    render :update do |page|
      page[:pending_task_list].replace_html :partial => 'pending_task', :collection => @pending_collection
      page[:completed_task_list].replace_html :partial => 'completed_task', :collection =>@completed_collection
      page.visual_effect :highlight, "task_#{@posted_task.id}", :duration => '0.5', :endcolor => "\'#262626\'"
    end
  end

... render executes everything correctly (partials are replaced and the task is highlighted). Very strange. Is there any reason for this? Can't I use instance variables in RJS files? If so, why doesn't it execute when "outside" of my controller?

Last edited by gmacgregor (2007-01-29 01:03:05)

Re: How to analyze a request?

Look in the development.log, do you see any error messages when using the change_status.rjs file? Where is this file exactly? It should be where the .rhtml views are stored.

Railscasts - Free Ruby on Rails Screencasts