Search query not showing up in URL in simple search app - ruby-on-rails

I'm trying to build an app that searches twitter for images. Before I get there, I need to jump over the intimidating hurdle of constructing a working search field that feeds a value into a function.
In my index.html.erb file that's controlled by the Pages controller, I have this code:
<%= form_tag root_path ({:controller => "pages", :action => "search", :method => "get", :class => "grabTweets" }) do %>
<%= text_field_tag :tweets, params[:tweets] %>
<% end %>
In my Pages controller I have:
def search
def grabTweets
#tweet = Twitter.search(params[:tweets] + "[pic] "+" path.com/p/", :rpp => 3, :result_type => "recent").map do |status|
#tweet = "#{status.text}" #class = string
#urls = URI::extract(#tweet, "http") #returns an array of strings
end
end
end
Two problems:
My search query isn't being passed into the grabTweets function as proven by the URL after the search is performed:
http://localhost:3000/?action=search&class=grabTweets&method=get (the search query was the word "bridge"
What's wrong with my code that the search query isn't performing correctly.
Should my code that's in the controller be placed in def home or def search, given that I want the search results to show up in the root_path and don't intend to change pages?
Thanks in advance for the help! I'm thoroughly stumped.

I think you need to read a book introducting Rails, as there seem to be many fundamentals you are missing.
You have an action for the page you are on (which you seem to call 'home') and an action for the search results. Your form needs to call the url for the search action. That would look like this:
<%= form_tag({:controller => "pages", :action => "search"}, {:method => "get", :class => "grabTweets"}) do %>
...
(See the API for more details on the form_tag method)
In that state, it will call the search action (which should not have another method called grabTweets nested inside it - that makes no sense) which will then render search.html.erb (presumably a page of search results).
In your routes file, you need a route for both home and search.
If you want the page to update without refreshing the page, then you need to use :remote => true on the form and handle the response using AJAX.
If you want the two pages to be the same, but with one containing results, then either move the search functionality into the home action and only call it if params[:tweets] is populated, or just have both actions render the same template.
I would recommend reading through the Rendering Guide and the Controllers Guide to learn more.

Related

Rails 4 - link back to form without reloading

Rails newbie here...please be kind...
I have an app that generates a unique paragraph of text (sampled from arrays and made unique based on criteria entered in _form.html.erb, rendered from the criteria/new page). On the criteria/show page, I have 2 links, one to generate a new unique paragraph using the same criteria, and one to return to the form and edit the criteria.
For the second link, I want to retain the criteria previously entered, as the user may want to only change one entry and not have to re-enter all of it. I've found plenty of information regarding ajax calls, respond_to, remote: true, but haven't found this exact answer or if I have, my brain is TIRED and failed to comprehend.
I've seen the suggestion in a similar question (How to come back to form without reset the values?) which talks about repopulating the data: "Just add the parameters (/myForm?param1=1&param2=2&param3=3) to the button url that leads back to the search form. Then populate the fields using the parameters. No need to use session variables." Sadly, I'm unclear about how to do implement this.
Would someone please be so kind as to walk me through either (preferably the simplest!) way of doing this?
Current links on show page (commented things are those that I tried unsuccessfully:
<%= link_to 'Generate Another!', criteria_path %> #regenerates text with current criteria
<%= link_to 'Enter New Information', new_criterium_path %> #this is the link I'm trying to change
<%#= link_to 'Enter New Information', new_criterium_path, :remote => true %>
<%#= link_to 'Enter New Information', { :controller => 'Criteria', :action => "new" } :remote => true %>
Controller new action (commented until I can make it work):
def new
#criterium = Criterium.new
#testing ajax stuff
# respond_to do |format|
# format.html
# format.json
# end
end
There's lots of talk about needing a new.js.erb file (or would that be show.js.erb?) and a div tag in my show(?) page but again, brain TIRED. I've attempted some of these things, then deleted from the code so as not to gak things up too much and be unable to remember what I did.
Please tell me what else you need from me in order to answer. Many thanks in advance!
Looks like you need to pass back params to your 'new' action, and then use them when instantiating Criterium:
<%= link_to 'Enter New Information', new_criterium_path(criteria: params[:criteria]) %>
def new
#criterium = Criterium.new(criteria: params[:criteria])
end

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!

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

Predetermining redirect_to for awesome navigation

I have a slightly complex navigational system with numerous landing pages, multipage forms, and multiple ways of accessing the standard CRUD functions.
Objective: To maintain a variable such as (params[:target]) throughout the system such that each controller knows where to redirect a user based on the location and circumstances of the link_to.
How to implement this the best way?
Is there a better way to store navigation markers so any controller and method can access them for the current_user?
If using params[:target] is a good way to go (combined with if or case statements in the controller for the redirect), how do I add the target params to the form when adding or editing a record? For example, view says:
# customers/account.html.erb
<%= link_to "edit", :controller => "customers", :action => "edit", :id => #customer.id, :target => "account" %>
# customers/edit.html.erb
<%= submit_tag "Update", :class => "submit" %>
# how to send params[:target] along with this submit_tag so the update method knows where to redirect_to?
Thank you very much.
I think you could get the same result by setting a session[:target] each time is necessary. so you'll always know where to redirect from controllers without changing link_to params and leaving clean URLs.
hope this helps,
a.

Resources