Konstantin
Konstantin

Reputation: 1280

The right way to do remote (ajax) calls in Ruby on Rails

I'm making a Single Page Application with Ruby on Rails (it's my first ruby project ever so I'm definitely missing a lot of stuff yet). So I have a side menu with some links and the right part of the page is supposed to hold a container which is meant to be filled with some content of partial pages. The typical menu link I have now looks this way:

 <%= link_to t('my-groups'), :controller => 'dashboard', :action => 'mygroups', :remote => true %>

I have a dashboard controller, here's the simplified version of it

 class DashboardController < ApplicationController
   def mygroups
    respond_to do |format|
      format.js
   end
  end

I have a dashboard template with the container div in it

<div class="right_col" role="main">
    <h2>This is the default content of center page</h2>
</div>

And here's the routes.rb path for it:

get 'dashboard/mygroups' => 'dashboard#mygroups'

I also have one partial page alogside with my dashboard template and it's called _mygroups.html.erb and a javascript file mygroups.js.erb which is called as my controller action look at the screenshot of the structure enter image description here

The contents of this js.erb file are:

$('.right_col').html("<%= escape_javascript(render(:partial => 'mygroups')) %>");

It all works and the partial contents appear inside the container on link click just fine. But there are still 2 problems I couldn't google the answer for

The questions part:

1) It works with Ajax call but if I simply put this http://localhost:3000/dashboard/mygroups to my browser's navigation line and hit enter, it will give me this error

ActionController::UnknownFormat in DashboardController#mygroups ActionController::UnknownFormat

Extracted source (around line #70):

def mygroups respond_to do |format| format.js end end

How can I avoid this and just redirect to index in this case? I understand that ajax uses POST, but I tried to use post instead of get in routes.rb for this action, and it didn't work at all

2) What if I have a lot of actions for different partial pages, do I have to create a new js.erb file for each action? Can't it be done in some simplier way with just one file?

3) Is it possible to not specify controller and action on this link explicitly?

<%= link_to t('my-groups'), :controller => 'dashboard', :action => 'mygroups', :remote => true %> 

I mean since it's supposed to be a POST ajax request, how come I need to display the url like this http://localhost:3000/dashboard/mygroups to a user?

Upvotes: 0

Views: 1277

Answers (2)

puneet18
puneet18

Reputation: 4427

Add format.html in controller like:

 class DashboardController < ApplicationController
   def mygroups
    if request.xhr?
      respond_to do |format|
        format.js
       end
    else 
      redirect_to root_url
    end
  end

you can add url in link_to tag like:

<%= link_to t('my-groups'), '/dashboard/mygroups', :remote => true %>

Upvotes: 3

Amit Patel
Amit Patel

Reputation: 15985

Answers to you questions

  1. When you hit the URL in browser, it sends vanilla HTTP get request(non-ajax) which your controller action is not configured to handle it. You need to add format.html and template named groups.html.erb where generally you will list all the groups, I guess.

respond_to do |format| format.html format.js end

  1. Ideally you have to create separate file for each action but if you can take something common out of different action then you can move common template code to a partial and render it either in a separate template having something special or from the controller action directly.

  2. Yes. The rails way is to use routes helper. Run rake routes to list all available routes in your app and find relevant helpers.

I would strongly suggest to read the rails guide to understand how everything works.

Upvotes: 0

Related Questions