Upon the creation of a department, users have the option to add the name of a school. On the show page of the school, I want to show all the departments with the school of that name.
My school controller's show action looks like this:
def show
#department = Department.where(:school == 'university of connecticut')
end
This obviously isn't working. What is the correct syntax for this?
Either if these should give you the expected results:
#department = Department.where(school: 'university of connecticut').first
or
#department = Department.where('school = ?', 'university of connecticut').first
where takes either a hash or a SQL statement. Note that in the first example, we're using the shortcut hash method when using a symbol symbol: value, which is equivalent to :symbol => value
Also, keep in mind that where returns an ActiveRecord::Relation object, not an ActiveRecord object. You'll need to add .first or another form of .find if you wish to receive an ActiveRecord object directly.
You're close:
Department.where(school: 'university of connecticut').first
i.e. normal hash syntax.
Related
I am building a job application site. A student can apply for a job, a student has many applications, and each one of these applications has only one job posting it connects to. When I query the database, ActiveRecord is returning a ActiveRecord::Relation, which is an array. I can look at the properties of the object, but I have to go down a level.
Getting object[0] I have to do this to look at properties object[0].id, object[0].name.
Would like to do this object.id, object.name
This is my query:
#application = Application.where(user_id: current_user.id, posting_id: #posting.id)
Let me answer your question
Active Record returns ActiveRecord::Relation instead of flat object
#application = Application.where(user_id: current_user.id, posting_id: #posting.id)
What’s returned by this query looks like an array of records but if
we call class on it we’ll see that it’s actually an instance of
ActiveRecord::Relation.
#application.class => ActiveRecord::Relation
The Relation Class -Railscasts Episodes-239
Having queries return an ActiveRecord::Relation object allows us to
chain queries together and this Relation class is at the heart of the
new query syntax. Let’s take a look at this class by searching through
the ActiveRecord source code for a file called relation.rb.
At the top of the class a number of constants are defined, one of
which is a Struct. If you’re not familiar with structs these are a way
of quickly defining a class dynamically by passing in a list of
attributes in the constructor.
require 'active_support/core_ext/object/blank'
module ActiveRecord
# = Active Record Relation
class Relation
JoinOperation = Struct.new(:relation, :join_class, :on)
ASSOCIATION_METHODS = [:includes, :eager_load, :preload]
MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having]
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :create_with, :from]
include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches
I would strongly suggest you to read out Railscasts Episodes-239 for more info.
1) Select the first element of the array:
#application = Application.
where(user_id: current_user.id, posting_id: #posting.id).
first
2) You can use #find_by
#application = Application.
find_by(user_id: current_user.id, posting_id: #posting.id)
I have a table that has alot of data inside it
I'm wanting to do something like this. To grab everything inside a column that matches something else inside another column in another table.
So #car = Cardata.find_by(#carmake)
So, #carmake will be volvo, Typed in a separate form and stored in a table.
In the table Cardata there is a massive list (about 40k records) with different cars ranging from ford to renault to volvo.
The question is. Would #car display all the records that have the word volvo inside?? Or is it the wrong way of doing this? or do i need to label it by column?
Sam
To get all of them:
#cars = Cardata.where(carmake: #carmake).all
To get just the first:
#car = Cardata.where(carmake: #carmake).first
you should be doing:
#car = Cardata.find_by_attribute_name(#carmake) # This will return the first car that matches #carmake.
Assuming attribute_name is model.
You'd do:
Cardata.find_by_model(#carmake)
If you want all the cars that matches #carmake.
You need to do:
Cardata.where(model: #carmake) # this will return an array of all cars with model #carmake.
Assuming you have a column in car data for make, I think you'd want to do something like:
#cars = Cardata.where(make: #carmake).all
I have a User model with a name attribute. In my PagesController, I want to set an instance variable equal to all of the User objects, but I want to order them based on last name. I know I can do:
#sortedusers = User.order(:name => :asc)
to order the users based on their name attribute, but how do I do it based on last name? (i.e. how do I order the Users based on the last word of their name attributes?
Thanks.
Define a virtual attribute last name in your model
def last_name
name.split(' ').last
end
and then
User.order(:last_name => :asc)
I'd suggest storing the users' last name separately. Barring that, you can use sort_by, like so:
items.sort_by! { |a| a.split(' ') } or something along those lines. Note, this most likely cannot be used straight, it's merely intended to point you in the right direction, as most of my answers are.
I'm building a Sinatra application using three database's tables: user, post and like.
I'd want to run a query that will find an entry in the like table like so:
FIND in like WHERE user_id == params[:user_id] AND post_id == params[:post_id]
(for one condition I'll be using: Like.find_by_user_id(params[:user_id]))
My question is:
How to run a find query with multiple conditions using the ActiveRecord Gem?
Use where:
Like.where('user_id = ? AND post_id = ?', params[:user_id], params[:post_id])
or
Like.where('user_id = :user_id AND post_id = :post_id', params)
Is important to keep in mind that the paremeters of the where need to be converted to the expected type for example params[:post_id].to_i
Similar to find_by_user_id for user_id column you can combine multiple column names and get a dynamic finder find_by_user_id_and_post_id:
Like.find_by_user_id_and_post_id(params[:user_id], params[:post_id])
When there are more than "bearable" columns in the find_by_ finder, you could use where and supply the condition as follows:
Like.where(user_id: params[:user_id], post_id: params[:post_id])
Like.find_by_user_id(params[:user_id]) - this syntax is deprecated in ActiveRecord 4.
Instead try using where method of ActiveRecord query interface, to pass array conditions. Example:
Like.where("user_id = ? AND post_id = ?", params[:user_id], params[:post_id])
If you are expecting one record to be the result:
To replace find_by_whatever you can use find_by(whatever) for example User.find_by(username:"UsernameIsMyUsername",password:"Mypassword"). You should use find_by if there is only one record that you expect to match your search.
If you are expecting more than one record to be the result:
If you expect more than one you should use where with where(username:"MyUsername",password:"Password"). This will return all the resulting records in an array.
Given an object like contacts:
Contact.rb (id, fname, lname, key_tag)
#contacts = Contacts.where(:user_id => #user.id)
Given #contacts comes back with 1000s of records in that one DB query. How can I then get/see if a object exists in #contacts that matches a given 'key_tag'.
I tried:
#contacts.where(:key_tag => 'def12')
But that requeries the database which is exactly what I want to avoid. Ideas? Thanks
what you Have is an Relation there. So adding the other where changes the relation and queries that data back. It should be lazily loaded. So in your code
Contact.rb (id, fname, lname, key_tag)
#contacts = Contacts.where(:user_id => #user.id)
If you don't touch #contacts, it shouldn't even hit the DB. But once you try to get data from it, it will then be executed and data comes back. If you are going to show all of them, you could use something like #all to return them as an array, and then use Array#select to search through it. Depending upon the speed of the system and/or your db, it might be more efficient to the DB do the select.
#contacts = Contacts.where(:user_id => #user.id).all
#contacts_with_key = #contacts.select { |c| c.key_tag == 'def12' }
You can use Enumerable find method:
#contacts.find {|c| c.key_tag == 'def12'}
Try Enumerable#find_all
#contacts.find_all {|a| a[:key_tag] == 'def12'}
Or if you want to only find first one(given that key_tag is unique)
#contacts.find {|a| a[:key_tag] == 'def12'}
be sure to:
include Enumerable