I'm new to rails and I'm trying to use the where method to retrieve a record from my data table. However, using it doesn't seem to return any results.
employee = Employee.where("first_name = ?", "bill") #doesn't work
employee = Employee.where(:first_name => "bill") #doesn't work
employee = Employee.find_by_first_name("bill") #works
I'm testing the results by printing employee.first_name and like I said the first two don't return anything whereas the third one returns "bill". What's going on here?
The first two will return an array (all employees with that name). Employee.find_by_first_name will only return the first result -- Employee.find_all_by_first_name should return an array like the first two queries.
See if this does what you expect:
Employee.where("first_name = ?", "bill").first
(for completeness, what Employee.where actually returns is a chainable scope object that acts like an array)
what happens for the first two when you run employee.first_name? It looks to me like you should be getting an no method exception since Array does not have a method first_name.
Using the where clause will not automatically return the first employee model object found, it will return an ActiveRecord::Relation which will then be automatically evaluated into an array by rails when you try to access it. The where clause will give you back all employees with a first_name == "bill"
The find_by_first_name will only return a single instance of the Employee class, even if there are multiple employees with the name "bill".
If you were to try employee.first.fist_name after running the first two, I believe you would find that you get "bill" if everything in the database is correct and there is an employee with the first name of "bill".
Related
Very short question, I feel like the answer must be already on StackOverflow but I couldn't find it.
I have some incoming parameters. They each have a unique ID.
I query the database and get an active record association using something like:
existing_things = current_user.things.where(uuid: [param_uuids])
This gives me an Active Record Association of those objects.
However, what I later do is something like:
existing_things.where(uuid: some_specific_uuid)
Of course, when I run the above query, it issues an SQL statement.
What I would love to do is find an object in a pre-loaded Active Record array of objects, and return that object without issuing another query.
How should I do that?
The same way you would if it was an ordinary array: Enumerable#find.
existing_things.find { |t| t.uuid == some_specific_uuid }
(or select if you're expecting more than one match)
If you're doing a lot of lookups like that, you might want to get a Hash involved:
things_by_uuid = existing_things.index_by(&:uuid)
things_by_uuid[some_specific_uuid]
(again, if you're expecting more than one match per value, there's group_by)
If I have a collection of records returned from an Active Record query, how can I access one of those records if I know its ID?
There are two ways to do this. Assuming you have an ActiveRecord relation called records and are searching for id:
You can use the ActiveRecord::FinderMethods#find method, but this will result in another call to the database:
records.find(id)
You can search through the collection without using the database by calling Ruby's Enumerable#find method as follows:
records.find { |r| r.id == id }
Although they share the same name, we are invoking two different find methods in the above example. The first will use more database resources, while the latter will use more application server resources. I am not sure which one is faster in the end.
TableName.find(id)
should do it.
Or if you already have a bunch of records in an Active Record query you can pull out the one with the known id like:
active_record_query = User.where(first_name: "Jim")
record = active_record_query.where(id: record_id).first
Supposing I have a result set of users and I want to find the user with ID = 3 in that set:
foo = User.all
user3 = foo.find {|x| x.id == 3}
Of course if you know the ID, you could just find it. Supposing I have a users table and I know the ID of the user I want is 3:
user3 = User.find(3)
You can find records with from the database with ActiveRecord::FinderMethods#find.
Thing.find(1) will query the database for SELECT things.* FROM things WHERE things.id = 1. And raise an ActiveRecord::NotFoundError if the record cannot be found. Find can also be used with a list of ids.
If you have a relation that is already loaded from the database you would use Enumerable#find or its alias #detect. ActiveRecord::Relation includes Enumerable so it works even if you don't explicitly cast to an array with .to_a.
Passes each entry in enum to block. Returns the first for which block
is not false. If no object matches, calls ifnone and returns its
result when it is specified, or returns nil otherwise.
Example:
[1,2,3,4].find(&:even?) # => 2
User.all.load.find { |u| u.id == 1 }
Yes. You can use the find method.
# Assuming you were retrieving an ActiveRecordRelation s
s = MyRecord.where(name: "test")
s.find(id)
For further information see: http://api.rubyonrails.org/v5.0/classes/ActiveRecord/FinderMethods.html#method-i-find
Im completely new to Ruby on Rails. Im working on an existing API and I have a sql query which is executed with:
results = ActiveRecord::Base.connection.select_all(query)
The output of the results is:
{"availability"=>"In Stock", "available_to_purchase"=>1}
{"availability"=>"Void", "available_to_purchase"=>0}
{"availability"=>"Out of Stock", "available_to_purchase"=>0}
{"availability"=>"In Stores Only", "available_to_purchase"=>0}
I know want to get all values for availability based on available_to_purchase being 0. I have tried:
res = results.where(available_to_purchase: 0)
But I get an error saying:
undefined method `where'
I also tried:
res = results.select { |result| result.available_to_purchase == 0 }
But i end up with the error:
undefined method `available_to_purchase'
I know I can loop through and check available_to_purchase is 0, then add to a new array. But is there any method to quickly filter active record results based on value of a column?
Going directly through the connection avoids nearly everything ActiveRecord is intended to provide you. First thing, read Active Record Basics. The Rails guides are really well put together and should contain everything you need for your first few weeks using the framework.
The reason you aren't getting the where method you expected is that it's a method on ActiveRecord::Relation, and select_all just returns you a list of hashes. By the time you call results.where, it's too late. You need to instantiate a Product model (or whatever would match your table name), which is as simple as:
class Product < ActiveRecord::Base
end
Rails will look at the products table (again, I'm making up your table name) for the attributes a Product has, and then you'll be able to query based on them with where:
results = Product.where(available_to_purchase: 0)
The model will also have the accessor methods you were trying for, so you can do things like results[0].available_to_purchase == 0 or results[0].availability = 'Already in your house'.
In order to call .where on the results, you need an instance of an active record relation. Regular ActiveRecord queries will return this. select_all, however, returns an array of hashes. Array does not have the method where.
res = results.select { |result| result.available_to_purchase == 0 }
Your second error is because you are attempting to access ruby hash keys incorrectly. Properties must be accessed asresult['available_to_purchase']
Here is the answer to your question. I do agree with others though that you should be using ActiveRecord.
results.select { |result| result['available_to_purchase'] == 0 }
Question: Is it possible to build a class method scope that can query objects based on values inside an array in a table? If yes, how can I do this?
In my example, I have a “wells” table that has an array field called “well_tags”. I want to build a query that returns all objects that have a specified value (such as “ceramic”) in the wells_tags array. The basic query would be something like this:
#well = Well.all
#query = #well.where(“well_tags contains ceramic”)
And then the class method scope would look something like this, with the “well_tag_search” param passed in from the controller:
class Well < ActiveRecord::Base
def self.well_tag_filter(well_tag_search)
if well_tag_search.present?
where(“well_tags contains ceramic")
else
Well.all
end
end
I found another post that asks a similar question (see link below), but I cannot get the answer to work for me...the result is always 'nil' when I know there should be at least 1 object. I am a beginner using sqlite (for now) as my database and rails 4.0.
Active Record Query where value in array field
Thanks!
UPDATE: some progress
I figured out how to create an array of all the objects I want using the ‘select’ method. But I still need to return the results as an Active Record object so I create a class method scope.
#well = Well.select
{ |well| if well.well_tags.present?
then well.well_tags.include? ‘ceramic' end }
#well.class #=> array
Not sure where Show is coming from.
Can you try doing Well.all instead of Show.all?
I have a where operation on a model that returns a single object. But I can't seem to use it in object notation (it appears to return an array with the object at [0]).
store = Store.where("some_id = ?", some_id)
puts store.name # doesn't work
puts store # shows array with the object at [0]
Because sometimes you don't know how many objects a query should return, so for consistency you always get an array.
To get a single object use
store = Store.where("some_id = ?", some_id).first
If you are looking for the primary ID of the model, you can also use
store = Store.find(some_id)
which will raise a RecrodNotFound exception (handled by rails as a 404 by default) if it doesn't find the object.
There are also dynamic finders
Store.find_by_some_id(some_id)
They are equivalent to
Store.where(:some_id => some_id).first
Where clause in rails 3.x will always return and arel objec, which you can use for method chaining.
Thus return statement of the where clause is always an array.
For accessing the first element you have to do
object.first as suggested by Jakub