I'm trying to order a column inside array but is not ordering is showing values without ordering by lastname ASC.
Here is my table:
|products|
|id| |money| |client_id|
1 1000 1
2 2000 4
3 2000 7
4 2000 5
5 2000 6
6 2000 3
7 2000 2
|customers|
|id| |name| |lastname1| |lastname2|
1 Lionel Messi Bueno
2 Cristiano Ronaldo Tiger
3 Cecs Fabregas Midtlon
4 Andres Iniesta Blanco
5 Neymar Dos Santos Junior
Here is my controller
class ProductController < ApplicationController
def index
#products= Product.all
end
end
Here is the model
class Client < ActiveRecord::Base
has_many :products
def str_name
return lastname1.to_s+" "+lastname2.to_s+" "+name.to_s
end
end
class Product < ActiveRecord::Base
belongs_to :client
end
Here is my view
<table>
<tr>
<td>Money</td>
<td>Client</td>
</tr>
<% #products.each do |p| %>
<tr>
<td><%= p.money %></td>
<td><%= p.str_name %></td>
<% end %>
</tr>
</table>
I tried but is not ordering by lastname1 asc:
<% #products.each do |p| %>
<tr>
<td><%= p.money %></td>
<td><% #a= p.client(:order=>"lastname1 ASC")%> <%= #a.str_name %></td>
<% end %>
The log is:
SELECT * FROM `clients` WHERE (`clients`.`id` = 1)
SELECT * FROM `clients` WHERE (`clients`.`id` = 2)
SELECT * FROM `clients` WHERE (`clients`.`id` = 3)
SELECT * FROM `clients` WHERE (`clients`.`id` = 4)
And should be like this:
SELECT * FROM `clients` order by last_name1 ASC
Please somebody can help me?
<% #a= p.client(:order=>"lastname1 ASC")%> <%= #a.str_name %></td>
The line above does technically nothing. When you are already in the loop and you ask for the client of the current product, how many is it going to return? Only one, right ? Right, if you have a belongs_to on the other side (which I hope you do, this answer relies on it). So you're actually "sorting" a set of one element every iteration. And that's why your Select is ignoring the "order by". What you should be doing though, is to get a list of all the products ordered by their respective clients' "lastname1". This should not be done in a view like you're trying to do, but in your controller. In your controller:
#In Rails 4
#products = Product.joins(:client).order('clients.lastname1 ASC')
#Other version (be careful where to use plurals and where not to)
#products = Product.find(:all, :joins => :client, :order => 'clients.lastname1 ASC')
And in your view:
<% #products.each do |p| %>
<tr>
<td><%= p.money %></td>
<td><%= p.client.str_name %></td>
</tr>
<% end %>
<% #products.each do |p| %>
<tr>
<td><%= p.money %></td>
<td><% #a= p.client(:order=>"lastname1 ASC")%> <%= #a.str_name %></td>
<% end %>
Not sure if this answers your question, but in the second td, the ERB tag isn't printing out anything to the page. Check your syntax.
If you're actually trying to set #a equal to something like that, it's best done in the controller.
That was just something I noticed. I'll continue to look at your code to see if I can find why you're not getting the result you desire.
In your code, it looks like each product only has one client, however I can't be sure since you did not post code for your Product model. If that is the case, then p.client will only ever return one client, and there is no reason to sort the results; ActiveRecord may be smart enough to skip that step. This could also explain the queries in your log.
If you want a many-to-many relationship between clients and products, you should create a join table.
rails generate model ClientProduct client_id:integer product_id:integer
Your resulting relationships would be
Client:
class Client < ActiveRecord::Base
has_many :client_products
has_many :products, :through => :client_products
...
end
Product:
class Product < ActiveRecord::Base
has_many :client_products
has_many :clients, :through => :client_products
...
end
ClientProduct:
class ClientProduct < ActiveRecord::Base
belongs_to :client
belongs_to :product
...
end
Related
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 %>
I have developed rails app with three classes.
class Location < ActiveRecord::Base
has_many :observations
end
class Observation < ActiveRecord::Base
belongs_to :location
has_one :rainfall
has_one :temperature
has_one :winddirection
has_one :windspeed
has_one :dewpoint
end
class Rainfall < ActiveRecord::Base
belongs_to :observation
end
Railfall is related to Observation through an observation_id and Observation is related to Location through a location_id.
If i go to console and type something like:
Location.all.first.observations.first.rainfall.value
it returns me the data in value column of rainfall
However when i want to combine all the info in rails in a table and in my view/location/index.html.erb i put:
<tbody>
<% #locations.each do |location| %>
<tr>
<td><%= location.name %></td>
<% unless #observations = nil %>
<% location.observations.each do |obs| %>
<td><%= obs.name %></td>
<% unless #rainfalls = nil %>
<td><%= obs.rainfalls.value %></td>
<% end %>
<% end %>
I get an error:
undefined method `rainfalls' for Observation:0x00000004219068>
I have spent the last 5 hours trying just about everything i can and am getting a tad frustrated....any ideas?
Note i have a locations controller but observation and rainfall were generated as models, so do not. Am thinking i need to add something to my location controller, just can't work out what, and I am unsure why it returns the correct data in console, just no in app.
Observation.has_one :rainfall, so it should be:
<%= obs.rainfall.value %>
You have one to one relationship, not has_many. Replace
<%= obs.rainfalls.value %>
by
<%= obs.rainfall.value %>
I've got two models - service_request_work_plan where service_request_work_plan has_many work_plan_tasks and work_plan_tasks belongs to service_request_work_plan. The linkage works, associations render properly and I have the code below in my show view for service_reqeust_work_plan, the goal of which is to show the work_plan_tasks in order. The show action works properly, but they are not showing in order (i.e. order_of_exeuction). What am I missing?
<table>
<tr>
<th>Order of Execution</th>
<th>Task</th>
<th>SLO</th>
<th>Task Instructions</th>
</tr>
<% #service_request_work_plan.work_plan_tasks.each do |work_plan_task| %>
<tr>
<td><%= work_plan_task.order_of_execution %></td>
<td><%= work_plan_task.task_name %></td>
<td><%= work_plan_task.task_slo %></td>
<td><%= work_plan_task.task_instructions %></td>
</tr>
<% end %>
</table>
class ServiceRequestWorkPlan < ActiveRecord::Base
attr_accessible :testing_company_id, :work_plan_name, :work_plan_comments
belongs_to :testing_company
has_many :work_plan_tasks
end
class WorkPlanTask < ActiveRecord::Base
attr_accessible :testing_company_id, :task_name, :task_instructions, :service_request_work_plan_id, :task_slo, :order_of_execution
belongs_to :testing_company
belongs_to :service_request_work_plan
end
def show
#service_request_work_plan = ServiceRequestWorkPlan.find(params[:id])
end
Add a .order(order_of_execution: :asc) for work_plan_tasks when querying the database from the controller. See http://guides.rubyonrails.org/active_record_querying.html#ordering
Controller:
def show
#service_request_work_plan = ServiceRequestWorkPlan.find(params[:id]).work_plan_tasks.order(order_of_execution: :asc)
end
Change this line:
<% #service_request_work_plan.work_plan_tasks.each do |work_plan_task| %>
into this line:
<% #service_request_work_plan.work_plan_tasks.all.order(:order_of_execution).each do |work_plan_task| %>
Default order is ascending, so the above line is complete. If you need descending order:
order(:order_of_execution => :desc)
I am still fairly new to Rails and fairly sure the way I'm attempting to go about this is inefficient or just plain silly, but here's what I'm trying to accomplish. I have 2 models, Cases (patient case files) and Inventories (medical transplant materials used in Cases).
class Case < ActiveRecord::Base
has_many :inventories
accepts_nested_attributes_for :inventories, :reject_if => :all_blank
end
class Inventory < ActiveRecord::Base
belongs_to :case
end
Inventories are created through a separate process and the goal is to associate them with a Case through the Case form. What I am trying to do is put a table on my Case form that lists the available Inventories along with checkboxes to select the desired Inventories to associate with the Case being created. This is further complicated by the fact that I need to be able to include nested fields for a couple of attributes on each Inventory (:case_price and :case_ship_price). I had previously done this in a very roundabout way using a has_many through association and storing those attributes on the pivot table, but it involved some hacky code to capture the field inputs from params and then save them through this block:
class CasesController < ApplicationController
def create
#case = Case.new(params[:case])
if #case.save
#case.case_lineitems.each do |li|
li.update_attributes(:price => params[:lineitem_price][li.inventory_id.to_s],
:shipping_cost => params[:lineitem_shipping][li.inventory_id.to_s])
end
redirect_to #case
else
render 'new'
end
end
end
This felt extremely clumsy and I was worried about problems it might cause, so I wanted to give a simple has_many, belongs_to relationship a try. However, I'm not sure if the typical <%= check_box_tag :inventory_ids, inventory.id, #case.inventories.include?(inventory), name: 'case[inventory_ids][]' %> works for that type of relationship. Here is what this section of my form looks like presently:
<table>
<thead>
<tr>
<th></th>
<th>Product</th>
<th>Serial #</th>
<th>Price</th>
<th>Shipping</th>
</tr>
</thead>
<tbody>
<% #inventories.each do |inventory| %>
<tr>
<td>
<%= check_box_tag :inventory_ids, inventory.id, #case.inventories.include?(inventory), name: 'case[inventory_ids][]' %>
</td>
<td><%= inventory.product.name %></td>
<td><%= inventory.serial_num %></td>
<%= f.fields_for :inventories, inventory do |inv| %>
<td>
<%= inv.text_field :case_price %>
</td>
<td>
<%= inv.text_field :case_ship_price %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
This results in the first checkbox defaulting to checked, and if I leave all unchecked, all of the inventories become associated upon submission. Checking only a subset results in an exception along the lines of Couldn't find Inventory with ID=206 for Case with ID=. Finally, checking all of the Inventories seems to result in the associations and nested attributes saving correctly.
How do I clean this up so that it works as desired? And if I need to go back to a has_many through relationship, is there a better way to save attributes on the pivot table on the same form that creates the row on pivot table? I'd really appreciate any help with this, as no amount of searching has gotten me out of this challenge.
I'm trying to pick out an instance of a model ("Package") by its relation to two other models to which it belongs ("Cut" and "Animal"). While there are, say many packages with :cut_id 3 and many with :animal_id 4, there should only be one with both, and I want to pick that one out and display its contents in a table.
I've tried the following DIY mess, and it's not really working. (cutfind is a method I created that I know works for calling out all of the cuts associated with the given animal.)
<% #animal.cutfind.each do |cut| %>
<tr>
<td><%= cut.name %></td>
<td><%= number_to_currency(cut.price) %></td>
<td><%= cut.package_weight %> lb</td>
<% #a = Package.where(:animal_id => #animal.id) %>
<% #pset = #a.where(:cut_id => cut.id) %>
<% #pset.each do |p| %>
<td><%= p.original %></td>
<td><%= p.left %></td>
<% end %>
</tr>
<%end%>
Any idea how to do this [better]? Thanks.
Update: I tried this other DIY mess and am getting the same problem (the cells aren't even being created, which leads me to believe that #pset is empty).
This is in my animal model:
def packagefind
Package.where(:animal_id => self.id)
end
And then I changed the above like so:
<td><%= cut.package_weight %> lb</td>
<% #pset = #animal.packagefind.where(:cut_id => cut.id) %>
<% #pset.each do |p| %>
<td><%= p.original %></td>
<td><%= p.left %></td>
<% end %>
Rails will automatically generate methods to help you find the associated records if you define the following relations:
class Animal
has_many :cuts
has_many :packages, :through => :cuts
end
class Cut
belongs_to :animal
belongs_to :package
end
class Package
has_many :cuts
has_many :animals, :through => :cuts
end
In your controller, the following line will eager load all the records you will need in your view:
#animal = Animal.includes(:cuts => :package)
Your view can then be shortened to:
<% #animal.cuts.each do |cut| %>
<tr>
<td><%= cut.name %></td>
<td><%= number_to_currency(cut.price) %></td>
<td><%= cut.package_weight %> lb</td>
<td><%= cut.package.original %></td>
<td><%= cut.package.left %></td>
</tr>
<%end%>
As I'm not able to comment on your post, I take a guess:
You have the folllowing architecture:
Cut -> Package <- Animal
In this, "->" and "<-" are one-to-many relationships so that
class Package < ActiveRecord::Base
has_many :cuts
has_many :animals
end
So, you want "the" package, that has Cut with id 3 and Animal id 4.
Did you try:
x = Product.select { |product| product.cuts.include?(Cut.find(3)) }.select{ |product| product.animals.include?(Animal.find(4)) }
?
EDIT: I first suggested to you use
Product.find_by_product_id_and_animal_id()
which didn't work but showed the OP the way to do it