I have a collection of objects students. I want to get only ids of all the students. Student model is implemented in Datamapper. I am new to Ruby on Rails and Datamapper. Is there any way so that I can get id of all the students in collection students. So basically I want the following thing:
students = Student.all
ids = students.get_ids
I don't know how to implement get_ids.
Variable "students" is an array, you should not apply get_ids on it.
The function should get no parameters.
def get_ids
Student.all.map { |student| student.id }
end
If you really need all the student objects, use students.map(&:id) which is short for students.map{|s| s.id} and returns an array of all ids.
To get the ids directly from your database, use Student.where(...).pluck(:id) without all, which is much faster and less memory intensive than instantiating all the student objects.
Edit:
Sorry, the pluck method is ActiveRecord only. But the other answers have an alternative with the fields option.
If you just want to get an active record relation, try this:
Student.select(:id)
That should return you an ActiveRecord relation with all the objects and IDs in each object.
If what you want is not an ActiveRecord relation, but rather just the ids, go with the simple "pluck" method
Student.pluck(:id)
You need fields
Student.all(:fields=>[:id])
See more : How to fetch only specified fields of model with DataMapper?
Related
Given following models and association:
(source: rubyonrails.org)
How can I get an array of pairs (physician_name, patient_name) that are appointed for certain day (appointment_date)? You can assume that one patient will never go to the same physician twice. Never.
I already tried things like:
#appointments = Appointment.where(appointment_date: params[:date])
but I have no idea what to do further. Should I iterate through this array and get every pair like this below?
#appointments.each do |appointment|
#physician = Physicians.where(id: :appointment.physician_id)
#patient = Patients.where(id: :appointment_patient_id)
I believe there's much easier way.
I'm using Rails 4.2.5.1.
I think what you want is approximately this:
Appointment.includes([:physician, :patient]).where(:date => appointment_date).map{|a| [a.physician.name, a.patient.name]}
Since only the Physician and Patient models have the names, they'll need to be loaded in the query (ok, you could avoid it by doing some fancy SQL trickery, but this is database-agnostic, which is convenient). Hence includes, which eager-loads associated models.
Then use .where to return only the appointments on the day you want (may be more complex if you're actually setting times in those DateTime values).
And finally, iterate over the list and return an Array of Arrays (Ruby not having Tuples) containing the names.
I have a custom model called product, and it has many reviews.
i have a method that calculates the review
def rating
total = 0
reviews_count = reviews.count
return 0 if reviews_count == 0
reviews.each do |review|
total += review.grade
end
total.to_f/reviews_count
end
i would like to know how could i use this method to Order my products.
At products_controller.rb, if i use:
#products = Product.all.order("price")
its easy, it gives me the products list ordered by price. But, if i use, for example:
#products = Product.all.sort_by{|p| p.rating}
it gives me an array and not a "ActiveRecord::Relation"
I would like to know how could i order my product using a custom method that returns a value.
In general, you can't. Ordering happens in your database, which has no knowledge about any method you typed in your application. What you need is a way of translating your method into a valid sql. In your case, you can do:
Product.joins(:reviews).group('products.id').order('AVG(reviews.grade)')
That will give you sorted results and the relation object. However, relations with join are not that nice to work with, especially if you try to add another join. Also this might get quite slow when your database grows.
What you're doing in your example is running the query then using sort_by to sort the result set.
If you want to get back an activerecord collection instead of an array, and potentially chain this with other scopes, you should move the logic from your method into SQL, and put it in a scope.
How do I get records from a table with a specific ID and store these records in an Array?
For better understanding I try to explain it to you more clear:
Imagine a table with the following columns: (ID,FIX_ID,AMOUNT)
where ID is an unique ID which always will auto_incremented by 1.
FIX_ID is an ID which can appear multiple times in the table.
And AMOUNT is just a simple type which represents the amount of some "things".
So all I want to get now is every record from the table which have the FIX_ID that I am looking for.
Remember: The FIX_ID is not unique => it can appear multiple times.
And that's it. So imagine that I want to get all records with the FIX_ID of 10. All these records which I will get should be stored in an Array.
My question to you: Is it possible to realize this "request" to the database with ActiveRecord?
If so, then how?
You can get an ActiveRecord::Relation object like this:
ModelName.where('FIX_ID = ?', 10)
Relation object will perform a database query as soon as you call methods like all, each or any? on it. If you really need an array, call to_a on that Relation:
ModelName.where('FIX_ID = ?', 10).to_a
In rails-
I need to execute a sql query against the database; the query is not related to any specific Model it can have mix data from multiple tables or from some other table. I have ways to do this=-
first is by executing query agains Model and capture the result like this-
res=User.find_by_sql("select * from customers joins and conditions")
res=User.find_by_sql("select * from [other table] joins and conditions")
Problem with this approach, I am not feeling comfortable with it because in User class objects I am capturing data of other table. like the first query result has data from customer table so in the user object I got customer's attribute. And more interesting problem is- if the resulting query has id attribute then
res.first.id will be id of customer and
if User model has relation with UserRoles model and if I access this relation with res.first.roles then it will fetch roles from UserRole for customer id, which is completely wrong.
And there might be may problems also.
So I think it has lot of chaos.
And good part is we dont not need to deal with connection and result would be an array of objects. so accessing object attributes with res.first.id is easier the hast like row["id"].
and second approach to use ActiveRecord connection and execute the query like
this res = ActiveRecord::Base.connection.query("sql query")
in place of query we can use select_one, select_all and can also make query parameterized.
The problem it has is it returns array of hash, but I need array of objects for easy accessibility in code. So I wrote a class to convert hash to object (I think rail does same thing in background) and is working fine.
So I need some suggestion on both the approach and need to decide which one is better.
First find_by_sql vs select_all
find_by_sql, This method returns an array of objects by initiating them.
users = User.find_by_sql("SELECT * FROM users"); #=> [#, #, #, # ....]
Accessing properties
users[0].name #Getting property in object oriented fashion
select_all, This method returns an array of objects but does not initiate them, and each object represents a row of database.
users = User.connection.select_all("SELECT * FROM users"); #=> #
Accessing properties
users[0]["name"] #Getting property in non-object oriented fashion
Whether find_by_sql is better, because of it is a simple way of custom querying to the database and returns instantiated objects
I've 2 objects, Student and Homework. This is a one-to-many relationship where a student can have many Homeworks
I'm trying to use a .find method to retrieve all students and just one homework that he has.
I know I can use Student.find(:all, :include => :homeworks). But, this will return me the student and all it's homeworks.
If your relation is one-to-many, you can't pick just one without deciding which one should it be (e.g. first one, if you order them by ids). If so, you can use #first method on relation:
Student.find(:all, :include => :homeworks).each {|student| student.homeworks.first}
If you mean pulling only one subject for each student from database it is more of SQL problem. You would have to write 'ON' clause that would pick single subject on your criterion.
If you don't care about performance then your solution is ok.
Fetch all record and just use the first one in your views or controllers
If you do care about performance (fetching a lot of objects is expensive) then you can add another relation first_homework or latest_homework (adding a new column latest_homework_id in your table's schema) and populate it with the correct id every time a student is assigned a new homework (or a homework is completed or whenever it makes sense for your application logic)