Hi I am trying to display last two(few) values in my index page How to do that in rails?
Here is my _index.html.erb file (rendering in new)
<table class="table table-hover">
<% PriceLog.order(price_date: :desc).each_with_index do |price_dated,index| %> // problem is here in looping
<tr>
<% #products.each do |product| %>
<td>
<%= PriceLog.where({product_id: product.id, price_date: price_dated.price_date}).last.price_date.strftime('%d-%B-%Y') %>
</td>
<td>
<%= PriceLog.where({product_id: product.id, price_date: price_dated.price_date}).last.price %>
</td>
<% end %>
</tr>
<% end %>
</table>
and in my controller
def new
#pricelog = PriceLog.new
#products = Product.all
#price = PriceLog.all
end
Updated
Here is the output I am getting like this I have three different products like Product1,Product2,Product3 and respected date and price for that
Here my values are duplicating 3 times(every time i hit submitting in form values it showing 3 times but storing once ) How should i stop duplicating and display only last few values
Any help must appreciated
Thanks
Have you tried something along the lines Model.last(2)?
You're running a loop within a loop. Your PriceLog.each_with_index loops over all your PriceLogs, and then within it your #products.each (which you have defined in the controller) loops over all your products. So each Product gets repeated once for every PriceLog.
Outside of that, you have a lot of logic in your view. It's generally frowned upon to call the model from there; that should happen either in the controller, a helper, or some custom presenter object.
In your controller instead of
#products = Product.all
change it to
#products = Product.all.order("id DESC").limit(2)
Related
Background
In my website, I'm trying to display 2 tables with data that I have scraped from another website and have place into an object called Product. The Product object has 2 categories which are stored as enums, registered and unregistered.
Problem
The problem comes when I apply pagination with Kaminari. Below are some images to demonstrate the problem.
Before the problem:
When I click '2' on the Registered Products table, the Unregistered Products table also goes to '2'
Problem:
I'm guessing it's because the data from both tables come from the same object? Anyway below are the relevant files.
My Model
class Product < ApplicationRecord
enum product_type: [:registered, :unregistered, :cosmetic]
paginates_per 8
end
My Controller
class HomeController < ApplicationController
def index
#registered_products = Product.where(product_type: 0).page params[:page]
#unregistered_products = Product.where(product_type: 1).page params[:page]
end
end
My partial for registered products
<table>
<thead>
<tr>
<th scope='col'>Name</th>
<th scope='col'>Chemical</th>
</tr>
</thead>
<tbody>
<% #registered_products.each do |product| %>
<tr>
<td><%= product.product_name %></td>
<td><%= product.chemical %></td>
</tr>
<% end %>
</tbody>
</table>
<%= paginate #registered_products %>
My partial for unregistered products is the same, replace #registered_products with #unregistered products.
index.html.erb
<h2>Registered Products</h2>
<%= render partial: "registered" %>
<h2>Unregistered Products</h2>
<%= render partial: "unregistered" %>
What I tried
I was looking through the Kaminari documentation and noticed that arrays can be paginated. So I tried that. Below are the modified files.
Controller
class HomeController < ApplicationController
def index
registered_products = Product.where(product_type: 0).to_a
unregistered_products = Product.where(product_type: 1).to_a
#registered_products_array = Kaminari.paginate_array(registered_products).page(params[:page]).per(10)
#unregistered_products_array = Kaminari.paginate_array(unregistered_products).page(params[:page]).per(10)
end
end
Every other relevant file is the same just substitute with the new global variables created. The problem still persists.
So my questions is how do I fix this problem and is it the problem occurring because I'm paginating the same object multiple times in the same page?
The reason why this problem is happening is because you are using the same params[:page] attribute to navigate through the pages. This results in the same number being passed to both the queries for your Product model. You will need to do this instead to get it working.
Partial for registered page:
...
<%= paginate #registered_products, param_name: :registered_page_no %>
And in the unregistered page partial, you will have to do the same, but with a unique name like unregistered_page_no
In your controller, all you need to do is this:
class HomeController < ApplicationController
def index
#registered_products = Product.where(product_type: 0).page params[:registered_page_no]
#unregistered_products = Product.where(product_type: 1).page params[:unregistered_page_no]
end
end
To know more about param_name, read the docs: https://github.com/kaminari/kaminari#changing-the-parameter-name-param_name-for-the-links
This is how my CategoriesController looks like:
class CategoriesController < ApplicationController
def index
#categories = Category.all
end
def show
#category = Category.find(params[:id])
end
end
inside my show.html.erb I wrote this to display the category name:
<h2><%= #category.name %></h2>
I also have a PagesController which I made relations with the Category
I have few Pages assigned to Category (for example category_id: 1)
When I click on the category link from my homepage:
<%= link_to "category", category_path(cat) %>
It goes to the show page which is great
How can I display on the show.html.erb all the Pages that belongs to this category that I've clicked on?
You should call the pages assosication with the category model as,
<%= #category.name %>
<h1> PAGES </h1>
<table>
<tr>
<% #category.pages.each do |page| %>
<td> <%= page.title %> </td>
<td> <%= page.content %> </td>
<% end %>
</tr>
</table>
This will do for you.
You should use includes for enhanced performance of your application. It will return all expected records from pages also and that's without firing database query again. #category.pages in ERB will not make database query. Hence, you will have efficient code.
In your show action:
def show
#category = Category.find(params[:id]).includes(:pages)
end
In show.html.erb:
<%= "Category: #{#category.name}" %>
<h1> POSTS </h1>
<table>
<tr>
<% #category.pages.each do |page| %>
<td> <%= page.field1 %> </td>
<td> <%= page.field2 %> </td>
<% end %>
</tr>
</table>
Rich Peck edit
Normally, ActiveRecord does something called lazy loading, which means that it will only execute a DB query when it needs to. This is normally highly efficient; unfortunately causes a problem when you call associative data.
When calling #category.pages, you get the n+1 issue, which means that each time you call the Category.find query, an extra query will be used to load the pages:
The above code will execute just 2 queries, as opposed to 11 queries in the previous case:
SELECT * FROM clients LIMIT 10
SELECT addresses.* FROM addresses
WHERE (addresses.client_id IN (1,2,3,4,5,6,7,8,9,10))
So using .includes essentially appends all the pages to your #category, making it much more efficient than letting it load lazily.
Well mostly it depends on how you made your relationships between category and page. With what i can see from your code, you can do something like this.
#pages = Page.where(:category_id => 1)
Update
As per to your relationships
#pages = #category.pages
I am creating a rails web app which basically just aggregates a list of users posts and allows them to vote and comment.
I was implementing endless scrolling by following the Railscast 114 - Endless Scrolling
post, although I have run into an issue that I am unsure if it is related to the endless scrolling, or just happened at the same time.
I am using the will_paginate gem. When the page is loaded it loads "n" number of posts the will_paginate call, but then those posts are displayed n times over.
For example:
#item.order(params[:sort]).page(params[:page]).per_page(3)
Would result in the following being displayed
item1
item2
item3
item1
item2
item3
item1
item2
item3
I have the following in my index action
#items = Item.order(sort_column + ' ' + sort_direction).page(params[:page]).per_page(5)
this is my _item partial
<% #items.each do |t| %>
<div id="Post1" class="shadow">
<table>
<tr>
<td>
t.stuff....
</td>
</tr>
</table>
</div>
And this is the render call in my index
<div id='items'>
<%= render #items %>
</div>
It feels like its something simple, but I just cannot find it. Any suggestions on where to look would be much appreciated
From my comment: change
<div id='items'>
<%= render #items %>
</div>
to
<div id='items'>
<%= render 'item' %>
</div>
Former version renders item partial for each object in #items collection (where you're iterating again over each element), that's why you get n*n items.
I think it should be
Item.paginate... not Item.order... , see the will paginate guide here
I am building a simple app and in many views I am displaying all of the objects associated with a certain model (many-to-one relationship). For example, I have a house model and an Item model where House has many Items. On the Show view for house I have the following code:
<% #house.items.each do |item| %>
<% if item.needed == true%>
<p>
<%= item.description %>
</p>
<% end %>
<% end %>
and this displays all the items along with one blank item. If I delete all the items, leaving an empty array there is still one empty item remaining. I can hack this using the code:
<% #house.items[0..-2].each do |item| %>
<% if item.needed == true%>
<p>
<%= item.description %>
</p>
<% end %>
<% end %>
This is probably a really simple question, but I would like to avoid using the latter code, and would like to understand why this is happening. Thanks.
The issue you are seeing is data related. This is to say, you need to figure out what is being returned by #house.items. Perhaps you have an item that has needed == true and a blank description? To trouble shoot this verify what is being returned by the house object in question by opening up the rails console, loading the house object in question and checking what is returned by house.items.
When using #house.items.new to set up a new Item object, it will alter the #house.items array, even though the new item is not yet persisted to the database. Example:
items = #house.items
items.length
# => 3
item = #house.items.new
items.length
# => 4
You could either add a check inside your loop for something like if item.persisted? or unless item.new_record?. Or, you could build the new item this way instead, which won't include it in #house.items until it's actually saved to the database:
item = Item.new(house_id: #house.id, needed: true)
I'm starting to develop a small application in Ruby On Rails. I have a short form (within a view) in which the number of fields is variable and created with the code snippet below:
<% for item in #event.items %>
<tr>
<td><%= item.name %></td>
<td><input type="number" name="quantity" /></td>
</tr>
<% end %>
I want to after click 'submit', run a controller's method that access to the data included in each of the fields in the form and perform insertions on the database. In the end, I want the page to be refreshed.
How do I customize the action of the submit button to perform a controller's function? And how do I access inside this function to the form fields (whose number is variable as mentioned).
Thanks in advance for your help.
You can use nested attributes. Then it should looks something like this (sorry for HAML):
= form_for #event do |f|
= f.fields_for :items do |item|
= item.object.name #displays item name
= item.number :quantity
And in your event model:
accepts_nested_attributes_for :items
I would suggest to use in this case the nested_form gem https://github.com/ryanb/nested_form.