Iterate id from the controller rails - ruby-on-rails

How can I iterate in the controller, I want to replace the view and create object an for #reserve = Reserve.where(:user_id=>user.id), how can I get each user.id from #user_list = User.where.not(id: 1) and output the view as
<% #reserve.each do |a| %>
<td><%= a.date %></td>
<td><%= a.time %></td>
<% end %>
Model
class Reserve < ApplicationRecord
belongs_to :user, optional: true
end
View
<% #user_list.each do |user| %>
<td><%= user.name %></td>
<% Reserve.where(:user_id=>user.id).each do |a| %>
<td><%= a.date %></td>
<td><%= a.time %></td>
<% end %>
Controller
#user_list = User.where.not(id: 1)
The reason why I want to do it this way is because I am using a gem for sorting
and I want to place the sort on their respective model instead of using User for both reserve and user which would cause an error.
when /^created_at_/
order("user.created_at #{ direction }")

If I understand your question (which I'm not sure I do), in your controller, do something like:
#user_list.each do |user|
#user = user
#reserve = Reserve.where(user: user) # <= do some sorting around here
render partial: 'user_list'
end
Now, you'll have #user and #reserve available in a partial, something like:
# _user_list.html.erb
<td><%= #user.name %></td>
<% #reserve.each do |a| %>
<td><%= a.date %></td>
<td><%= a.time %></td>
<% end %>

Related

erb:how to filter on resource attribute

How can I filter the results based on the resource attribute in .erb file. For example, I would like to display product which price is lower than 50 dollars. The following is current .erb file. The price tag is a string, need to be converted to number.
<% #products.each do |product| %>
<tr>
<td><%= product.title %></td>
<td><%= product.price %></td>
<td><%= product.count %></td>
</tr>
<% end %>
Can I use this in the view? I have undefined method "filter" error.
<% #products.filter { |p| p.price < 50 }.each %>
<tr>
<td><%= product.title %></td>
<td><%= product.price %></td>
<td><%= product.count %></td>
</tr>
<% end %>
The short answer: you can either use select to only select products with a price less than 50 dollars or even partition to split the list into those below and above that price.
Ideally you'd do this outside of the view, though, for example inside your controller or even the model.
Basic filtering (inside view):
#products.select { |p| p.price < 50 }.each do |product|
Or with a scope in the model:
scope :below_price, ->(price) { where("price < ?", price) }
You can use it in the controller:
PRICE_THRESHOLD = 50
def index
#products = Product.below_price(PRICE_THRESHOLD)
end

if statement in ruby loop editing properties

I have two database tables, user and product
When the user creates a product the user.id is placed into the product table under product.user_id
I'm writing a loop to displays all products "belonging" to the currently signed in user, it looks like this so far.
<% #product.each do |p| %>
<% if product.user_id = user.id %>
<tr>
<td><%= user.id %></td>
<td><%= product.user_id %></td>
<td><%= product.id %></td>
<td><%= product.name %></td>
</tr>
<% end %>
<% end %>
If the currently signed in user is user 2 for example, instead of filtering all products that don't have a user.id of 2 it just changes the product.user_id for every product to 2 so that the returned table looks like so.
2 2 1
2 2 2
2 2 3
2 2 4
Without the if statement it returns the full product listing with all the correct properties.
You should use == not =:
<% if product.user_id == user.id %>
Here is your complete solution
<% #product.each do |p| %>
<% if p.user_id == user.id %>
<tr>
<td><%= user.id %></td>
<td><%= p.user_id %></td>
<td><%= p.id %></td>
<td><%= p.name %></td>
</tr>
<% end %>
<% end %>
However I don't know what is going on in your controller but you could probably save a lot of effort by filtering out on the current user's products in the controller prior to serving that #product instance variable to the view. Maybe try a query like this:
user_id = current_user.id #assuming you have access to a method like this
#product = Product.where(user_id: user_id)
EDIT
philomor is correct. You should add a has many relationship on user see below.
#app/models/user.rb
class User < ActiveRecord::Base
has_many :products
end
#app/models/product.rb
class Product < ActiveRecord::Base
belongs_to :user
end
However not that you have this relationship you want to be carful that when you call it you don cause an N+1 query. To avoid this do the following when fetching all of a user’s products
#products = User.find(params[:user_id]).includes(:products).products
Use a comparison operator == and your if statement should be something like
<% if p.user_id = user.id %>

Gracefully jumping to next record - ActiveRecord

Rails 3.2
I have the following in my view:
<% #organizations.each do |o| %>
<% organization = Organization.find(o.organization_id) %>
<% if organization == nil %>
<% next %>
<% end %>
<tr>
<td><%= o.org_name %></td>
<td><%= number_to_currency(o.revenue, :precision => 0) %></td>
<td><%= o.rank %></td>
</tr>
<% end %>
I was under the impression that if organization is not found, execution would jump to the next record. Instead, I am getting the "something went wrong".
Looking through the log file, one of the organization_id is not found in the organizations table, and that's what's triggering the error.
Why isn't execution jumping to the next record?
Temporary Solution: I changed
<% organization = Organization.find(o.organization_id) %>
To:
<% organization = Organization.find_by_id(o.organization_id) %>
and that gives me a nil when it does not find anything. If it's nil, the execution skips to the next record
According to http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find, Organization.find(o.organization_id) will raise an ActiveRecord::RecordNotFound for the id that does not exist in the table.
Addendum:
Try something like the following:
<% ids = #organizations.map(&:organization_id) %>
<% organizations = Organization.where(id: ids) %>
<% organizations.each do |o| %>
<tr>
<td><%= o.org_name %></td>
<td><%= number_to_currency(o.revenue, :precision => 0) %></td>
<td><%= o.rank %></td>
</tr>
<% end %>
With this method, you'll fetch all the organizations with 1 query from the DB as opposed to 1 for every organization.

Show attribute value using its id

In my application, I am grouping my objects by an ID. At the moment, I can only display the ID, but I would like to display the attribute value.
A Fixture belongs_to a tournament and a tournament has_many fixtures.
Controller
def index
#fixtures = Fixture.all
#tournament_fixture = #fixtures.group_by {|f| f.tournament_id}
end
View
<% #tournament_fixture.sort.each do |tourn_name, fixture| %>
<%= tourn_name %>
<% fixture.each do |f| %>
<td><%= f.home_team %></td>
<td><%= f.away_team %></td>
<td><%= f.kickoff_time %></td>
</tr>
<% end %>
<% end %>
How can I get
<%= tourn_name %>
to display its corresponding value that is in its :name column?
At the moment in my view for example i get this returned
<tbody>
2
<tr>
<td>Tournament Name</td>
<td>Team 1</td>
<td>Team 2</td>
<td>2000-01-01 14:00:00 UTC</td>
<td><a class="btn btn-success" href="/fixtures/1">view</a></td>
</tr>
</tbody>
The 2 needs to be the value in the :name column
I'd recommend grouping by tournament instead:
#tournament_fixture = #fixtures.group_by(&:tournament)
And then iterate using:
<% #tournament_fixture.sort.each do |tournament, fixture| %>
<%= tournament.name %>
...
<% end %>
You can access the whole object much like you can get the id like this:
def index
#fixtures = Fixture.includes(:tournaments).all
#tournament_fixture = #fixtures.group_by {|f| f.tournament.name}
end
The id is still available as either f.tournament_id or f.tournament.id, should you still need it but I just figured you'd rather group by its name directly. I simply added an includes statement to also load the referenced Tournament objects with your fixtures in one go. Otherwise, Rails would load the tournaments only when you access them one by one.
As an alternative, you could load the Tournaments, including all their the fixtures instead and iterate over the tournaments like this:
Controller
def index
#tournaments = Tournament.includes(:fixtures).all
end
View
<% #tournaments.each do |tournament| %>
<%= tournament.name %>
<% tournament.fixtures.each do |f| %>
<td><%= f.home_team %></td>
<td><%= f.away_team %></td>
<td><%= f.kickoff_time %></td>
</tr>
<% end %>
<% end %>
It seems a bit more natural to me and you don't need to iterate over all fixtures to map them by their tournament.
You can load the fixtures in the right order. There is no need to group then in memory. Remember to include the tournaments to avoid N+1 queries.
# controller
def index
#fixtures = Fixture.order(:tournament_id).includes(:tournaments).all
end
Loading in the right order in the controller makes the view simpler. For the tournament's name just use the association between Fixture and Tournament.
# view
<% #fixtures.each do |fixture| %>
<tr>
<td><%= fixture.tournament.name %></td>
<td><%= fixture.home_team %></td>
<td><%= fixture.away_team %></td>
<td><%= fixture.kickoff_time %></td>
</tr>
<% end %>

Rails 3 , Simple search form problem

Code in my product model (product.rb):
def self.search(search)
if search
find(:all)
else
find(:all)
end
end
Code in my search controller (search_controller.rb):
def index
#products = Product.search("Apple")
end
Code in my view (index.html.erb):
<h1>Products</h1>
<% form_tag client_search_path , :method => :get do %>
<p>
<%= search_field_tag :term, params[:term], :class=> "auto_search_complete"%>
<%= submit_tag "Search", :name => nil, :class => 'button', :id => "search_bn" %>
</p>
<% end %>
<table border="1px">
<tr>
<th>Name</th>
<th>Brand</th>
<th>Quantity available</th>
<th>Category</th>
<th>Shopcenter name</th>
<th>Shopcenter streetnumb</th>
<th>Shopcenter streetname</th>
<th>Shopcenter postal</th>
<th>Shopcenter province</th>
</tr>
<% for product in #products%>
<tr>
<td><%= product.name %></td>
<td><%= product.brand %></td>
<td><%= product.quantity_available %></td>
<td><%= product.category %></td>
<td><%= product.shopCenter_name %></td>
<td><%= product.shopCenter_streetNumb %></td>
<td><%= product.shopCenter_streetName %></td>
<td><%= product.shopCenter_postal %></td>
<td><%= product.shopCenter_province %></td>
</tr>
<% end %>
</table>
I load this all is good, but if I comment one of the line of codes in my model:
def self.search(search)
if search
#find(:all)
else
find(:all)
end
end
I expect this to work also at least for the initial render, or when I submit an empty search term, but it's not. And changing the code to of the model to:
def self.search(search)
if search
find_all_by_name(search)
else
find(:all)
end
end
Doesn't work it gives me an error that the view is working with a nil object, which is impossible because my database has entries.
Can someone explain what is going on? I have the impression that both the conditions in my model are being executed. At least that's what 2 puts statement in each case showed me.
Please advice.
I think you should set search = nil if search == "" in your controller otherwise it will always go to the first condition.
It had some compatibility issues with Rails 3.
I updated rails and ruby and it works fine now

Resources