0

My client has asked for a single url to complete a workflow in their application: example.org/task/:token. Where :token is a unique id for that task.

Within the TaskController in the index action :token is used to query the task object and the view is rendered based upon the Task's current state:

def index
  @task = Task.where(token: params[:token])
  render @task.state.to_s
end

Every state has a view and the logic for rendering the view is in the view itself (UGLY!!).

I'd like to refactor this so that Task state is used to determine which controller action to render. I can do that with render template: '#{state}/action'. But this doesn't execute the controller action logic. Meaning I'm still stuck with controller logic in the view!

I've found this solution that works, but it's a bit ugly and breaks some of rails "magic" (have to explicitly render the view.)

My questions is, is there a better way to accomplish this within Rails while still maintaining the single url and not redirecting to a new url?

Community
  • 1
  • 1
Gavin Miller
  • 43,168
  • 21
  • 122
  • 188

2 Answers2

1

You linked to an answer that wasn't accepted, and I would recommend the accepted answer in that link (https://stackoverflow.com/a/6051812/1461068)

Specifically this part:

def your_action
  ...
  render :action => :index
end

Which you could handle like so:

def index
  @task = Task.where(token: params[:token]).first
  render :action => get_action_for_state(@task.state.to_s)
end

private

def get_action_for_state(state)
    //logic to figure out which action to call
end
Community
  • 1
  • 1
awbergs
  • 942
  • 4
  • 15
  • I do like this, in that I can bring the view logic into the controller. The ideal case would be moving the actions to different controllers so that I don't have to have 14 different actions in a single controller! :D – Gavin Miller Mar 20 '13 at 18:26
  • What's wrong with that? They are all related, no? There is no rule that says you can't have 14 actions in a controller. Also would it really be better to have 14 different files? – awbergs Mar 20 '13 at 18:36
  • Ya that's an interesting thought... What I'm thinking to provide a bit of a cleaner implementation is to group some of the actions into "sub" controllers and include those in. That would allow me to skip 14 different files, yet still organize tasks a bit better. What do you think? – Gavin Miller Mar 20 '13 at 18:40
  • I honestly think 14 actions in one controller isn't crazy, and you can definitely extract the action logic into separate files from there to cut down the noise. – awbergs Mar 20 '13 at 18:53
0

Take a look at this: http://railscasts.com/episodes/217-multistep-forms I think ryanb has some good ideas there. Basically you'd have your task.html.erb render the appropriate partial depending on what state your task is in:

  <%= render "#{@task.state}_state", :f => f %>
rainkinz
  • 10,082
  • 5
  • 45
  • 73
  • I'm still watching the video, but it seems like this is the same as my current solution, but instead of rendering in the view, I render in the controller. – Gavin Miller Mar 20 '13 at 18:30