UnknownFormat Error When Doing an AJAX Search - ruby-on-rails

I wish to have a little search box, which will allow the user to search other users by name, with the results showing in the box in a sort of list. Much like how, on a site like amazon, you can type a search into the bar and it will have a dropdown, except on mine I am not doing "autocomplete" (at least not yet)
At the moment, however, when I try to search, it says "ActionController::UnknownFormat in ChatRoomsController#search_users", with an explanation:
ChatRoomsController#search_users is missing a template for this request
format and variant. request.formats: ["text/html"] request.variant: []
NOTE! For XHR/Ajax or API requests, this action would normally respond
with 204 No Content: an empty white screen. Since you're loading it in a
web browser, we assume that you expected to actually render a template,
not nothing, so we're showing an error to be extra-clear. If you expect
204 No Content, carry on. That's what you'll get from an XHR or API
request. Give it a shot.
So it seems to be saying that this isn't an AJAX request, but I have have pretty much copied my code from the RailsCast on AJAX searching (just removed some pagination bits), so this confuses me.
Here are the relevant parts of my code:
# chat_rooms/show.html.erb
<%= form_tag search_path, :id => "search", :method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search for User", :name => nil, class: "button-butt" %>
<% end %>
<% for result in #users_results %>
<%= result.name %>
<% end %>
and the controller:
# chat_rooms_controller.rb
def search_users
#users_results = User.search(params[:search])
end
the model's search method:
# user.rb
def self.search(term)
where('name LIKE ?', "%#{term}%")
end
I think my routing is OK, but just in case it isn't:
# routes.rb
get '/search_users', to: 'chat_rooms#search_users', as: 'search'
and finally, the javascript:
#application.js
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
$("#search input").keyup(function() {
$.get($("#search").attr("action"), $("#search").serialize(), null, "script");
return false;
});
Any help would be appreciated.

# routes.rb
get '/search_users', to: 'chat_rooms#search_users', as: 'search'
Since your routes.rb specifies that you will have a search_users action in ChatRoomsController and it(action) seems to be present.
When request arrived from the form, it landed on that action but, since the template named search_users.html.erb is missing, its displaying this error.
Solution
Either handle the request and respond with a template mentioned in the error message; or, rename and redesign the routes and controller.
Edit: 1
I just want to send the search request, and have the results pop into the list below the searchbar if you see what I mean.
If so, do following:
# chat_rooms_controller.rb
def search_users
#users_results = User.search(params[:search])
render :show
end
Plz comment, if its not helping.

Related

404 error when making an ajax call to controller from view in rails for dynamic drop down select

I am trying to dynamically populate a select list and I am getting a 404 error when I make my ajax call to my controller. I have looked around but cannot find out why I am getting this error.
My controller where the method I want to call is.
class UsersController < ApplicationController
def index
##users = User.all
myList = [["A",1],["B"],2]
#classList = myList
render "index.html.erb"
end
.
.
.
def changeclasses
#classlist = [["B",2]]
end
end
And this is my view
<%= form_for UnoClass.new do |f| %>
Department: <%= select_tag(:city_id, options_for_select([['Accounting', 'ACCT'], 2),
{ id: 'departSelect'}) %>
<br />
Course : <%= select_tag(:course, options_for_select(#classList)) %>
<br />
Section : <%= f.text_area :section %>
<br />
<%= f.text_area :sessionId, value: request.session_options[:id], style: "display:none;" %>
<%= f.submit %>
<% end %>
<script>
$(document).ready(function() {
$('#departSelect').change(function() {
$.ajax({
url : "/changeclasses"
});
});
});
</script>
and my routes.rb
Rails.application.routes.draw do
resources :uno_classes
resources :users
root :to => 'users#index'
get '/changeclasses' => "users#changeclasses"
This is the error that I grab from the developer tools on chrome.
GET http://localhost:3000/changeclasses 404 (Not Found)
So, when I make a change to the upper select box departSelect, it makes a call to changeclasses but it cannot find it.
Also when I do rake routes the correct route shows up.
changeclasses GET /changeclasses(.:format) users#changeclasses
I have not implemented the method yet but it should change the #classList and therefore change the contents of the course select box and it never gets called because of the 404 error.
Any help would be appreciated because I cannot figure out why there is a problem here.
Here's some ideas on things you can try to get it working.
First. Create a view called "changeclasses.js.erb" in your Users views folder which is what Rails will by default look to load unless you tell it otherwise since its a js request. You can/should also put the js that you want to run with this particular method in that file (changeclasses.js.erb).
Second. Try updating the ajax call's datatype to "script" so that it will be processed by your controller as js.
$.ajax({
url : "/changeclasses",
dataType: "script"
});
Third. If all that doesn't fix it, I would add the below code to your controller to make it sure it is responding to js requests.
class UsersController < ApplicationController
respond_to :js
Hope one of those helps!

rails search form that works on all pages of application

I have a search form which appears on all pages because I want someone to be able to search and be redirected to search results regardless of where they are on the site. To achieve this i placed the form in a partial which i included in the application layout. It looks like this
<form class="form-search center">
<%=form_tag search_url, method: :get do%>
<%=text_field_tag :query, params[:query] ,{:class=>"input-xxlarge search-query"}%>
<button type="submit" class="btn">Search</button>
<%end%>
</form>
I have created a controller called SearchResults with an index action to display the results.
The named route looks like this
match '/search', to: 'search_results#index'
The search works perfectly fine on the search page, but cannot work anywhere else.My index action looks like this
class SearchResultsController < ApplicationController
def index
#restaurants = Restaurant.text_search(params[:query]).page(params[:page]).per_page(3)
end
end
I want to be able to redirect to this action whenever i carry out a search regardless of where i am in the application.The text_search method is defined in the restaurant model like so
def self.text_search(query)
if query.present?
where("restaurant_name ilike :q or description ilike :q", q: "%#{query}%")
else
scoped
end
It doesn't work in that nothing happens when i search but if i go to the search page it returns the results.
I have noticed something interesting. When I search from the home page for a term like eats. The url looks like this localhost:3000/?utf8=✓&query=eats and when I search from the real search page which works perfectly it looks like this localhost:3000/search?utf8=✓&query=eats. How can i get it point to the latter url regardless of where am searching from?
Its because you have a nested form.
<form class="form-search center">
<%=form_tag search_path do%>
Get rid of the form you have in raw HTML and just let Rails generate it via the helper in the 2nd line.
Why don't you do a proper routing entry for your search controller?
resources :search_results, :only => :index
And then in your search form you let it POST to searches_path. Then you don't have to fiddle around with this :match routing.
Edit
I also noticed that you GET your form. Technically it doesn't really matter, but it's not very clean. So maybe, you could do something like this:
resources :searches_results do
post :query
end
And then in your controller you simply have the query function.
Edit 2
And I think the real problem here is that you are having is that you have a form tag in a form tag. The first form tag gets evaluated and it probably points to /. Therefore it works in the controller itself, but not anywhere else.
for my case i use somethig like this: in view
<%= form_tag url_for(:controller => '/searchresults', :action => 'index') , :method => 'get' do %>
<%= text_field_tag :query, params[:query] ,{:class=>"input-xxlarge search-query"} %>
<%= submit_tag 'search' %>
<% end %>
and in model
q = "%#{params[:query]}%"
where("restaurant_name LIKE ? or description LIKE ?", q, q)

using Bootstrap Navbar Search with form_tag to redirect to resource index with search params

I'm trying to put a quick keyword search in my navbar, using Bootstrap's Navbar Search component. Currently this is using a form_tag as follows
<form class="navbar-search pull-left">
<%= form_tag(recipes_path, :method => :get) do %>
<%= text_field_tag :keywords, nil,
{:class => "search-query", :placeholder => "recipes quick search"} %>
<%= hidden_field_tag :use_keywords, "true" %>
<%= hidden_field_tag :wide_search, "true" %>
<% end %>
</form>
This is for a recipe lookup. I'm using the form to (try to) get keywords, which will be passed as params to the search, which resides in the recipes index action.
def index
if params[:wide_search].present?
#search = Search.new
#search.use_keywords = params[:use_keywords]
#search.keywords = params[:keywords]
... (more params for other search types)
if params[:wide_search] == "true"
#recipes = #search.wide_search
elsif params[:wide_search] == "false"
#recipes = #search.narrow_search
end
#recipes = #recipes.paginate(:page => params[:page])
else # no params, just index all
#recipes = Recipe.paginate(:page => params[:page])
end
end
Note that "Search" is a ruby class. I was thinking of making it into a full-blown resource so I could create and view old searches (maybe they could be looked at to offer suggested searches based on past history, etc), but decided against it. I still dunno if that was a good idea or not. If it was an actual resource, it could have RESTful actions and maybe save some problems. This is not my actual problem, but does anyone have suggestions for this?
Sorry, back to the actual problem -- From the root page or wherever, I would like to be able to type in keywords, press the enter key (within the search bar) and have it redirect to the Recipe Index with the params needed so it can run the search and display the results.
Right now, if I go to the index page and do this, it works fine. BUT, if I'm in any other page (like the root page, or wherever) and try to type keywords and press enter, it just reloads the current page, although I do see the params in the URL. So it's not redirecting to Recipe Index. I must be missing something, but I'm not sure what. I'm kind of suspicious of the form_tag since there's no actual submit button. But then it works when I'm in the index page, so I dunno. Any suggestions appreciated!

Rails 3: AJAX call not refreshing div with link_to

I'm using Rails version 3.0.9 and jquery.
The problem is that when you click on the link, the div is not updated.
There are two actions: "show" and "time". Initial position - show.
Controller code was (ajax_controller.rb):
class AjaxController < ApplicationController
respond_to :html, :js
def show
end
def time
end
end
By clicking on the link in the div should be loaded time.
Next code (show.html.erb):
<h1>Ajax show</h1>
Click this link to show the current
<%= link_to "time", :url=>{:action => "time"}, :remote => true%>.<br/>
<div id='time_div'>
</div>
Also, there are files time.html.erb and time.js.erb.
Follow code (time.js.erb):
$('#time_div').html('<%= escape_javascript(render :text => "The current time is #{Time.now.to_s}") %>');
But nothing happens. jquery connected.
In what may be the problem?
You can have issues with routes. Do you have something like this in your routes.rb?
RAILS_ROOT/config/routes.rb
get '/time', :to => 'ajax_controller#time', :as => :ajax_time
and then you should call the url with rails helper like this
<%= link_to "time", ajax_time_path, :remote => true %>
You can look at your log to see if time.js.erb is indeed rendered. It is possible that the HTML version is rendered instead. If that's the case, remove the HTML version.

Get url for current page, but with a different format

Using rails 2. I want a link to the current page (whatever it is) that keeps all of the params the same but changes the format to 'csv'. (setting the format can be done by having format=csv in the params or by putting .csv at the end of the path). Eg
posts/1
=> posts/1.csv OR posts/1?format=csv
posts?name=jim
=> posts.csv?name=jim OR posts?name=jim&format=csv
I tried this as a hacky attempt
request.url+"&format=csv"
and that works fine if there are params in the current url (case 2 above) but breaks if there aren't (case 1). I could come up with more hacky stuff along these lines, eg testing if the request has params, but i'm thinking there must be a nicer way.
cheers, max
EDIT - btw, it's not guaranteed that the current page could have a named route associated with it, in case that's relevant: we could have got there via the generic "/:controller/:action/:id" route.
<%= link_to "This page in CSV", {:format => :csv } %>
<%= link_to "This page in PDF", {:format => :pdf } %>
<%= link_to "This page in JPEG", {:format => :jpeg } %>
EDIT
Add helper
def current_url(new_params)
url_for :params => params.merge(new_params)
end
then use this
<%= link_to "This page in CSV", current_url(:format => :csv ) %>
EDIT 2
Or improve your hack:
def current_url(new_params)
params.merge!(new_params)
string = params.map{ |k,v| "#{k}=#{v}" }.join("&")
request.uri.split("?")[0] + "?" + string
end
EDIT
IMPORTANT! #floor - your approach above has a serious problem - it directly modifies params, so if you've got anything after a call to this method which uses params (such as will_paginate links for example) then that will get the modified version which you used to build your link. I changed it to call .dup on params and then modify the duplicated object rather than modifying params directly. – #Max Williams
You can use:
link_to "text of link", your_controller_path(format:'csv',params: request.query_parameters)
#floor's answer was great, I found it very useful.
Although the method can be improved by using the to_params method rather than contructing your own, like so:
def current_url(new_params)
params.merge!(new_params)
"#{request.uri}#{params.to_params}"
end

Resources