will_paginate on array only displays first page of items - ruby-on-rails

I need to paginate an array. When I click the other pages, I see the same 25 items as displayed on the first page. The URL is http://localhost:3000/?page=2 but it's the same 25 items. There are about 100 total.
Here's my controller method:
def index
#items = Array.new
API.items.all! do |i|
#items << i
end
#paginated_items = #items.paginate(per_page: 25)
end
Here is my html file:
<%= will_paginate #paginated_items %>
<ul class="items">
<% #paginated_items.each do |i| %>
<li>Subject: <%= i.subject %>, ID: <%= i.id %></li>
<% end %>
</ul>
<%= will_paginate #paginated_items %>
I also added require 'will_paginate/array' to an initializer.

I think you missing page: params[:page] in index controller, this is how will_paginate know what page you currently now
def index
#items = Array.new
API.items.all! do |i|
#items << i
end
#paginated_items = #items.paginate(page:params[:page],per_page:25)
end

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

Ruby array only storing last value, not all values

I have a Ruby app with Products and Categories.
I would like to have a category index page that displays 1 product photo for each category.
Right now, it shows the last product photo for all categories. (So, with 16 categories, it shows the product photo for category 16 on every category.)
I think I need to fix how I store or call the Products array. How do I do that?
Code --
in categories_controller.rb
def index
#categories = Category.all.order('name ASC')
#products = []
#categories.each do |category|
#products = Product.where(category_id: category.id).take(1)
end
end
in categories/index.html.erb
<% #categories.each do |category| %>
<% #products.each do |product| %>
<%= link_to image_tag(product.image), category %>
<% end %>
<%= link_to category.name, category %>
<%= category.description %>
In your index action, change the line:
#products = Product.where(category_id: category.id).take(1)
To:
#products << Product.where(category_id: category.id).take(1)
UPDATE:
Since take(1) will return an object in array, you need to simply change it to:
#products << Product.where(category_id: category.id).take

Using search function in rails to retrieve a result and display it first in the index page

I am trying to implement search functionality in my rails app where I search and display a particular search result first on my index.html.erb view. At the moment I have a search function working and it returns the particular item on its own on the index page.
Ideally I would like to have this item displayed first and then all the other items to display below.
My code is as follows:
brand.rb
def self.search(query)
where("author like ?", "%#{query}%")
end
brand_controller.rb
def index
if params[:search]
#brand = Brand.search(params[:search]).order("created_at DESC")
else
#brand = Brand.all.order(':date')
end
end
I know the where method returns the value as an array so I could probably use array.first to output this result first but is there an easier way to output my desired view. Thanks!
So turned out to be a pretty simple solution, I blame mondays.
All I had to do was create another variable for my search and iterate that result first, then iterate through the rest of the items.
in my controller
def index
#brand = Brand.order('created_at DESC')
if params[:search]
#brand = Brand.search(params[:search]).order("author DESC")
#other = Brand.search_all(params[:search]).order("author DESC")
else
#brand = Brand.all.order('author DESC')
end
end
In my model
def self.search(query)
where("author like ?", "%#{query}%")
end
def self.search_all(query)
where("author not like ?", "%#{query}%")
end
and finally in my view
<% if #brand.any? %>
<% #brand.in_groups_of(2) do |group| %>
<% group.each do |brand| %>
<% if brand %>
<h4> <%= brand.author %></h4>
<a href="<%=brand_path(brand)%>">
<%=image_tag brand.brand_logo, class: 'img-rounded', :"data-uid" => brand.uid %> </a>
<% end %>
<% end %>
<% end %>
<% end %>
<% if #other %>
<% #other.in_groups_of(2) do |group| %>
<% group.each do |other| %>
<% if other %>
<h4> <%= other.author%></h4>
<a href="<%=brand_path(other)%>">
<%=image_tag other.brand_logo %> </a>
<% end %>
<% end %>
<% end %>
<% end %>

Why does my search show all results with searching?

I setup a search on my Products index page with PgSearch and Will-Paginate like this:
ProductsController
def index
#products = Product.text_search(params[:query]).page(params[:page]).per_page(5)
end
Products Model
include PgSearch
pg_search_scope :search,
def self.text_search(query)
if query.present?
search(query)
else
scoped
end
end
Product index page
<%= form_tag products_path, method: :get do %>
<%= text_field_tag :query, params[:query] %>
<%= submit_tag "Search", name: nil %>
<% end %>
<% if #products.blank? %>
No Results
<% else %>
<% #products.each do |product| %>
<%= product.name %>
<% end %>
<% end %>
But the problem I'm having now is that when I go to the Product index page, it shows all of the products when I want it to show nothing until a search is done. If the search is blank, return No Results but when you first hit the page it should show nothing. How would this be done?
You probably want to only run a text_search when a search parameter is present. You can put this logic into the view, the controller, or in the model.
In the view
<% if params[:query].present? %>
<% if #products.blank? %>
No Results
<% else %>
<% #products.each do |product| %>
<%= product.name %>
<% end %>
<% end %>
<% end %>
In the controller
def index
if params[:query].present?
#products = Product.text_search(params[:query]).page(params[:page]).per_page(5)
else
#products = Product.none # NOTE: Rails 4 only
end
end
In the model
# create a new method to encapsulate this search logic then use it in the controller
def self.search(value)
if value.present?
Product.text_search(value)
else
Product.none # NOTE: Rails 4 only
end
end
The old saying goes "fat model, skinny controller" so you might want to opt for the model method which will keep your controller and views simpler.
Put your display logic inside an if statement:
<% if params[:query].present? %>
<% if #products.blank? %>
No Results
<% else %>
<% #products.each do |product| %>
<%= product.name %>
<% end %>
<% end %>
<% end %>
Although I'm not familiar with how pg search works, you could do something like this in your method.
It's a nice refactoring as well as it avoids checking for existence and making decisions on params (code smell)
def self.text_search(query = "")
search(query)
end
As I said, not sure how pg_search works. Maybe when you browse for nothing, it returns all records. If that's the case, you can just have it return an empty array. Something like this would do
def self.text_search(query)
return [] if query.nil?
search(query)
end

Cannot reverse order because of pagination

I want to order users by descending. However, when I add .reverse it reverses the users a page at a time, not all together.
show_followers:
<%= render #users.reverse %>
<%= will_paginate %>
Users/_user:
<%= link_to user.name, user %>
<% unless #user.nil? %>
<% if request.path == "/users/#{#user.id}/listening_to" %>
<br/>
<span id="member_since"><%= "Listening Since" %> <%= #user.relationships.find_by_followed_id(user.id).created_at.strftime("%b. %d, %Y") %></span>
<% end %>
<% if request.path == "/users/#{#user.id}/listeners" %>
<br/>
<span id="member_since"><%= "Listener Since" %> <%= user.relationships.find_by_followed_id(#user.id).created_at.strftime("%b. %d, %Y") %></span>
<% end %>
<% end %>
Controller:
#users = #user.followed_users.paginate(page: params[:page])
It seems Rails intelligently orders by the relationships_create like I wanted but it's in ascending order. I want the most recent follower to show up on the top of the list.
In the controller action, you probably have some code that looks something like this: #users = User.paginate(:page => params[:page]).
You need to put the reverse in that statement, so it looks like this: #users = User.paginate(:page => params[:page]).order('id DESC') (perhaps with id replaced by created_at).
#users = #user.followed_users.reverse.paginate(page: params[:page])
Reverse at the controller level prior to pagination

Resources