Rails 3 taking a long time to load the results - ruby-on-rails

My rails application has to query through a database which has lacks of rows and display the matching results. My code is working perfectly but its dead slow ,its taking a very long time to show the results.I am using ruby 1.9.3 and rails 3.2.13 and "Webrick" server.I am sure there is some problem . Is there any way I can resolve this .I have two tables called coordinates and tweets.
My code for the controller
require 'will_paginate/array'
class TweetsController<ApplicationController
def index
city = params[:show]
search_term = params[:text]
search_term.gsub!(/\s/, '%')
city_coordinates = Coordinates.where('city=?', city)
if (city_coordinates.count == 1 && city_coordinates.first.valid_location?)
#tweets = ((Tweets.for_coordinates(city_coordinates.first) & Tweets.where("tweet_text LIKE?" , "%#{search_term}%"))).paginate(page: params[:page], per_page:5)
elsif(city_coordinates.count!=1)
#tweets = ((Tweets.for_user_location(city) & Tweets.where("tweet_text LIKE?" , "%#{search_term}%"))).paginate(page: params[:page], per_page: 5)
else
Tweets.where("tweet_text LIKE? ", "%#{search_term}%").paginate(page: params[:page], per_page: 5)
end
end
end
My code for the model
class Tweets<ActiveRecord::Base
attr_accessible :id, :tweet_created_at, :tweet_id, :tweet_text, :tweet_source, :user_id, :user_name, :user_sc_name, :user_loc, :user_img, :longitude, :latitude, :place, :country
def self.for_coordinates(coordinates)
bbox = { min_lat: coordinates.latitude - 1.0, max_lat: coordinates.latitude + 1.0,
min_lng: coordinates.longitude - 1.0, max_lng: coordinates.longitude + 1.0
}
Tweets.where("(longitude BETWEEN ? and ?) AND (latitude BETWEEN ? and ?) OR (user_loc LIKE ?) " ,
bbox[:min_lng], bbox[:max_lng], bbox[:min_lat], bbox[:max_lat], "%#{coordinates.city}%" )
end
def self.for_user_location(city)
#tweets= Tweets.where("user_loc LIKE ?", "%#{city}%")
end
end
My code for the view
<%= will_paginate #tweets %>
<% #tweets.each do |tweets| %>
<ul>
<li><%= tweets.id %></li>
<li><%= tweets.tweet_created_at %></li>
<li><%= tweets.tweet_source %></li>
<li><%= tweets.tweet_text %></li>
<li><%= tweets.user_id %></li>
<li><%= tweets.user_name %></li>
<li><%= tweets.user_sc_name %></li>
<li><%= tweets.user_loc %></li>
<li><%= tweets.user_img %></li>
<li><%= tweets.longitude %></li>
<li><%= tweets.latitude %></li>
<li><%= tweets.place %></li>
<li><%= tweets.country %></li>
<% end %>
</ul>
It has two search boxes ,one for the tweet query and another for the city,It has to display tweets for a particular city.But its very slow .I am not able to find the reason if it is due to inefficient coding or wrong choice of server or some other reasons .It uses Mysql database.

Your issue is with the union of two queries:
#tweets = (
(
Tweets.for_coordinates(city_coordinates.first) &
Tweets.where("tweet_text LIKE?" , "%#{search_term}%")
)
).paginate(page: params[:page], per_page:5)
What this does is:
Retrieve all tweets for the city coordinates into an in-memory array
Retrieve all tweets where the text matches the search term into an in-memory array
Concatenates the arrays from 1. and 2.
Paginates these results
What you want to do instead is:
Filter for tweets that match the city coordinates AND the search term
Paginate the results
Retrieve the paginated results
You'll want something more like this:
#tweets = Tweets.for_coordinates(city_coordinates.first).
where('tweet_text like ?', "%#{search_term}%").
paginate(page:params[:page], per_page:5)

Related

Print pg_search params to Rails 5 template page

I have a products page that is filterable with pg_search gem. What I would like to do is create a breadcrumb that lists the search params onto the page.
If my search url looks like http://127.0.0.1:3000/products?utf8=%E2%9C%93&query=modern&query=stone&query=limestone&commit=Search I would like to print modern stone limestone to the page.
products_controller.rb
def index
#products = if params[:query]
#albums = Album.where(name: params[:query])
Product.search_for(params[:query])
else
#albums = Album.where(name: 'products')
Product.order(:name)
end
end
index.html.erb
This is what I tried, but realized that it lists ALL the tags, which I only need the tags that are part of the search params
<ul class="product-index-breadcrumb">
<% #products.each do |p| %>
<% p.tags.each do |t| %>
<li><%= t.name %></li>
<% end %>
<% end %>
</ul>
You need to modify your URL e.g array string adding [] if you keep this then it only without [] then it takes only last value like limestone,
after modification URL then it will look like this http://http://127.0.0.1:3000/products?utf8=%E2%9C%93&query[]=modern&query[]=stone&query[]=limestone
then if you write like
<%= params[:query] %>
it will return
["modern", "stone", "limestone"]
now you can run a loop like
<ul>
<% params[:query].each do |query_params| %>
<li><%= query_params %></li>
<% end %>
</ul>
then output is
modern
stone
limestone

Rails - Unique Array in View

Having a Bit of trouble displaying unique results from my database. I have a database called "Activities". Each Activity has an associated Sport through sport_id. There may be many activities with the same sport_id.
I want to display a list of all sports linked to the activities database without displaying (for example "Football") twice.
FYI : Venues have many Facilities and Facilities have many Activities.
Controller:
#sports = Sport.all
#activities = Activity.paginate(page: params[:page])
#facilities = Facility.where(venue_id: #venue.id)
View:
<% #facilities.each do |f| %>
<% #activities.find(:all, :conditions => "facility_id == #{f.id} ").each do |a| %>
<li><%= Sport.find(a.sport_id).name %>, (<%= a.facility_id %>)</li>
<% end %>
<% end %>
This shows:
Football, (2)
Hockey, (2)
Hockey, (2)
Football, (5)
I would like to display just:
Football
Hockey
Any ideas?
A simple solution would be to reduce your array with ruby in the view using: uniq!
<% #facilities.each do |f| %>
<% #activities.find(:all, :conditions => "facility_id == #{f.id} ").uniq! { |a| a.sport_id }.each do |a| %>
<li><%= link_to Sport.find(a.sport_id).name, Sport.find(a.sport_id) %></li>
<% end %>
<% end %>
Another way may be to perform a single query on your DB since Sport what you want to narrow down
In controller:
#sports = Sport.joins(activities: [facility: :venue]).where(facilities: { venue_id: #venue.id }).distinct
In view:
<% #sports.each do |sport| %>
<li><%= link_to sport.name, sport %></li>
<% end %>
I am not sure about your DB schema so I went with what I thought you would have done, but it might needs some tweakings.
I hope I helped you.
try to use reject before each
<% #facilities.reject{your condition here}.each do |f| %>

Pagination in rails 3

In my rails application I need to display the matching tweets .lets say for example the matching results has 50 records, I need to display 10 records per page.I am getting the output which has all results but when I use pagination its showing link to different pages , but when I click the link to next page it says "string not matched". I tried different combinations like 5 per page ,but when I click the link to the next page it says "string not matched", but when I try without pagination it shows all the results
My code for the controller
class TweetsController<ApplicationController
def index
city = params[:show]
search_term = params[:text]
search_term[" "] = "%"
#tweets = Tweets.where("tweet_text LIKE? ", "%#{search_term}%").paginate( page: params[:page], per_page: 3)
My code for the view
<%= will_paginate #tweets %>
<% #tweets.each do |tweets| %>
<ul>
<li><%= tweets.id %></li>
<li><%= tweets.tweet_created_at %></li>
<li><%= tweets.tweet_source %></li>
<li><%= tweets.tweet_text %></li>
<li><%= tweets.user_id %></li>
<li><%= tweets.user_name %></li>
<li><%= tweets.user_sc_name %></li>
<li><%= tweets.user_loc %></li>
<li><%= tweets.user_img %></li>
<li><%= tweets.longitude %></li>
<li><%= tweets.latitude %></li>
<li><%= tweets.place %></li>
<li><%= tweets.country %></li>
<% end %>
</ul>
Anyone please help me with this
You have an error in
search_term[" "] = "%"
line. If it should replace whitespace with "%", it should be:
search_term.gsub!(/\s/, '%')

ruby on rails routing error routing to the wrong page

coordinates GET /coordinates(.:format) coordinates#index
POST /coordinates(.:format) coordinates#create
new_coordinate GET /coordinates/new(.:format) coordinates#new
edit_coordinate GET /coordinates/:id/edit(.:format) coordinates#edit
coordinate GET /coordinates/:id(.:format) coordinates#show
PUT /coordinates/:id(.:format) coordinates#update
DELETE /coordinates/:id(.:format) coordinates#destroy
tweets_search GET /tweets/search(.:format) tweets#search
tweets_index GET /tweets/index(.:format) tweets#index
class TweetsController<ApplicationController
def index
#include 'coordinates_controller.rb'
include SearchHelper
include ParamasHelper
#sql=a.search
#tweets=Tweets.paginate_by_sql(sql, :#page, :per_page => #per_page ).all
end
end
In my Rails app, I have two tables named Coordinates and Tweets. I have four actions to be rendered.
My routes.rb file
Tweetsblog2::Application.routes.draw do
resources :tweets, :coordinates
get "tweets/show"
get "tweets/index"
match "/tweets/show" => "tweets#show"
match "/tweets/index" => "tweets#index"
Whenever I navigate to http://localhost:3000/tweets, it's showing tweets/index instead of tweets/show and the same error I am getting with different names.
When I navigate to http://localhost:3000/tweets/show, it's giving ArgumentError in TweetsController#show.
When I navigate to http://localhost:3000/tweets/index its giving ArgumentError in TweetsController#show same thing
My code for show.html.erb:
<%= form_tag({controller: "tweets", action:"index" }, method: "get") do %>
<%= label_tag(:search, "search for:") %>
<%= text_field_tag(:show) %>
<%= text_field_tag(:search) %>
<%= submit_tag("get results ") %>
<% end %>
My code for index.html.erb:
<%= will_paginate #tweets %>
<% #tweets.each do |tweets| %>
<ul>
<li><%= tweets.id %></li>
<li><%= tweets.tweet_created_at %></li>
<li><%= tweets.tweet_id %></li>
<li><%= tweets.tweet_source %></li>
<li><%= tweets.tweet_text %></li>
<li><%= tweets.user_id %></li>
<li><%= tweets.user_name %></li>
<li><%= tweets.user_sc_name %></li>
<li><%= tweets.user_loc %></li>
<li><%= tweets.user_img %></li>
<li><%= tweets.longitude %></li>
<li><%= tweets.latitude %></li>
<li><%= tweets.place %></li>
<li><%= tweets.country %></li>
<% end %>
</ul>
It's not routing to the proper page. Please help me, I am stuck with this.
you have to write
resources :tweets, except: [:index,:show]
because you declared you resource first, so rails is trying to match its default routing instead of your custom action:
get "tweets/index"
-updating per comment-
Tweetsblog2::Application.routes.draw do
resources :coordinates
get "tweets/show" => "tweets#show"
get "tweets/index" => "tweets#index"
Removing the resources :tweets should fix your issue and allow you to use just call the 2 options. The initial resources :tweets tells rails that you wanted resourceful routes (index shows all of the resource, show a specify one, etc..). So just building out the 2 non-resourceful routes as above sounds like what you want. The way I normally do something like this is to just include the search form in in the index page and if there are no search params then show all tweets.)

Create object from a block of search results Ruby on Rails

I'm building a Rails application that allows the user to create a Book object based on search results from the Google Books api. I have a controller that handles searching the api, using the GoogleBooks gem and displays the results in a list. I'm struggling to figure out a way to pass book information from a single search result into my Create action in the Books controller.
My search controller takes params from my search form and creates a variable, #results, that I'm calling in a 'search' view. Here is my search controller:
class SearchController < ApplicationController
def search
#results = GoogleBooks.search(params[:search])
end
end
My view looks like this:
<h1>Search Results</h1>
<% #results.each do |result| %>
<ul>
<li><%= result %></li>
<li><%= result.title %></li>
<li><%= result.authors %></li>
<li><%= result.isbn %></li>
<li><%= result.description %></li>
</ul>
<% end %>
The problem that I'm having is that I'm not sure how to pass individual result data on to my Book controller's 'create' action to generate a new book in the database. I don't think I can pass 'result.title' or 'result.author' to the Book controller for example because they aren't instance variables and there is also no way to distinguish between each result.
My page source for search results looks like this, if that is any help.
<h1>Search Results</h1>
<ul>
<li>#<GoogleBooks::Item:0x007ff75d2bd138></li>
<li>Kansha: Celebrating Japan's Vegan and Vegetarian Traditions</li>
<li>Elizabeth Andoh</li>
<li>9781607743965</li>
<li>The celebration of Japan’s... </li>
</ul>
<ul>
<li>#<GoogleBooks::Item:0x007ff75d2bc148></li>
<li>Advanced Energy Saving and Its Applications in Industry</li>
<li>Kazuo. Matsuda, Yasuki. Kansha, Chihiro. Fushimi</li>
<li>9781447142072</li>
<li>The conventional approach for... </li>
</ul>
I would like to use a button to allow a user to 'select' the book and then pass on the book's information to the create action. I'm thinking I need to do something like this with button_to:
<%= button_to 'Create Book', book_path, :method => :post %>
But how do I get the a single book's data to the create action?
Depending on your overall layout, I suggest start by building an in-line form for each Book result. You can do this with hidden fields. As mentioned by gregates, it's hard to provide the complete answer, but this might get you going in the right direction.
In your SearchController:
def search
#results = GoogleBooks.search(params[:search])
#books = []
#results.each do |result|
#books << Book.new
end
end
In your View:
<% #results.each_with_index do |result, index| %>
<%= form_for(#books[index]) do |f| %>
<ul>
<li><%= result.title %></li>
<li><%= result.authors %></li>
<li><%= result.isbn %></li>
<li><%= result.description %></li>
</ul>
<%= f.hidden_field :title, value: result.title %>
<%= f.hidden_field :authors, value: result.authors %>
<%= f.hidden_field :isbn, value: result.isbm %>
<%= f.hidden_field :description, value: result.description %>
<%= button_to 'Create Book', controller: 'books', action: 'create' %>
<% end %>
<% end %>
Again, depending on your overall design, there's probably a more elegant approach but hopefully this will provide some inspiration.
Good luck!

Resources