Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern to render multiple coffee

I have a task model which is related to the user and project models.

When I create/update a task, I need to do an update in the view async, not only for the task change/addition, but to the project and user info (because some of that data might change too).

I have this in the controller:

def create
  @task = Task.new(params[:task])
  @project = Project.find(params[:project_id])

  respond_to do |format|
    if @task.save
      format.html { redirect_to @task, notice: 'Task was successfully created.' }
      format.json { render json: @task, status: :created, location: @task }
    else
      format.html { render action: "new" }
      format.json { render json: @task.errors, status: :unprocessable_entity }
    end
  end
end

And my tasks/create.js.coffee

# Update task table
$('#mytable').append("<%= j render(partial: 'tasks/task', locals: { t: @task }) %>")

# Update user data
$('.user-data').html("<%= j render(partial: 'users/user_widget', locals: { u: current_user }) %>")

# Update project data
$('.project-data').html("<%= j render(partial: 'projects/project_widget', locals: { p: @project }) %>")

And it works great. I see 2 issues:

  • In every render of .js.coffee I add, I am repeating the code too much. I duplicate exactly the same code for updating project and user data, on tasks update, tasks destroy, and I would do the same for a new model which might affect the user and the project

  • It seems weird to handle project and user data in tasks/create.js.coffee

Therefore, I am looking for a better pattern to handle this stuff, any ideas?

EDIT (to clarify): I think achieving something like this would be better:

tasks/create.js.coffee

# Update task table
$('#mytable').append("<%= j render(partial: 'tasks/task', locals: { t: @task }) %>")

UserData.refresh()
ProjectData.refresh()

However, I can't do that because I need to render the partial each time, so I would have to do something weird like passing the html partial to those refresh() functions, and it would be pretty the same as the previous way. This is just a way that came to my mind, but I would like to hear your ideas if any.

like image 824
ascherman Avatar asked Dec 20 '16 14:12

ascherman


1 Answers

You could render a template/action that belongs to a different controller. So you could keep the tasks/create.js.coffee file and for all the other controller actions (like users and projects) that use the same code, in your respond_to block you would use:

format.json { render 'tasks/create' }

You could even render a specific file:

format.json { render file: "path/to/specific/file" }

Here is a link with more information on rendering in rails: http://guides.rubyonrails.org/layouts_and_rendering.html#rendering-an-action-s-template-from-another-controller

like image 57
farrows76 Avatar answered Sep 22 '22 05:09

farrows76