Ruby on Rails Array access - ruby-on-rails

My issue involves an array that is apparently not nil but when I try to access it, it is.
The array is returned from a find on an active record. I have confirmed it is in fact an array with the .class method
#show_times = Showing.find_showtimes(params[:id])
#show_times.inspect =>shows that the array is not empty and is a multidimensional array.
#show_times[0] =>is nil
#show_times[1] =>is nil
#show_times.first.inspect => NoMethodError (undefined method `first')
I am perplexed as to why this is..

It's not an array, it's an active record magic structure that mostly looks like an array. I think you can do to_a on it to get a real array, but then a lot of the magic goes away.

find_showtimes is not a built-in finder - if it were, it would return either a single ActiveRecord object or an array of ActiveRecord objects - never a multidimensional array. So the first thing I'd do is have a look a the source of that method.
EDIT: Given your source code (in the comment) - you're actually getting a Hash, not an Array, back from your finder. See the docs for Enumerable's group_by. The Hash is mapping your theater objects to an array of showing objects. This is what you want to do:
Showing.find_showtimes(params[:id]).each do |theater, showtimes|
puts "Theater #{theater} is showing the movie at #{showtimes.join(', ')}"
end

If you're in the console and you want to explore the #show_times object, you can use the keys method to see all the hash keys and then get to individual hash items (such as all the show times) like so:
#show_times[:theater_one]
Same thing will work in your model/view but using each/map/collect would be cleaner as pretty code goes.

Related

How to get active record's name after using find .where

Straight forward here:
<% #yyy = CityRace.where(city_race_id2: "3") %>
<% #xxx = #yyy.name %>
The #yyy is returning the proper record using the ID I have passed into it, but I'm trying to get the objects name. For some reason .name isn't working. Any idea what I'm going wrong here?
How do I find a record's name where id = a certain id?
where returns an ActiveRecord_Relationship, meaning an object containing CityRace objects for every row in the database with city_race_id2 equals to 3, no matter if there's only one, the result is an ActiveRecord_Relationship object, and that doesn't respond to name.
If you need the name of a particular object from that result, you can access to the specific element by its index and invoke name on it, e.g:
CityRace.where(city_race_id2: "3").first.name
Or to retrieve the name from every object:
CityRace.where(city_race_id2: "3").pluck(:name)
this one returns an array of strings, so, you must iterate over them to print them all or get a specific one.
In the other hand if you need a single row from the query, use find_by:
CityRace.find_by(city_race_id2: "3").name
.where returns an ActiveRecord::Relation which behaves like an array. You can think of it like a special kind of array that allows you to chain on more active record queries on it. When you call certain methods like each or to_a it evaluates the query into an actual array.
In any case, what you are looking for here is not something array-like. You want #yyy to refer to a single record.
Simple fix, just use find_by instead of where. Also take a look at https://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find and find vs find_by vs where

NSMutable array containsObject, does it check the contents of the object or the object type?

I am a little confused to how containsObject works. Does it check to see if it contains an instance of an object type or does it compare the inside of the objects variables etc to see if they match?
This is an implementation detail, you can work on the basis that it calls isEqual: on each items and works on the result of that.
Under the hood it's probably calling hash on each item and comparing that, then, if the hash matches it will call isEqual: to make sure it's a real match.

Rails difference in object created from a .find(:id) and .where() methods

What is the difference in the objects created with these 2 methods:
tec = Technique.find(6)
tec2 = Technique.where(:korean => 'Jok Sul')
The data returned for each is exactly the same, yet the first object will respond perfectly to an inherited method like update_attributes while the second object will give an error of method not found.
When I do tec.class and tec2.class one is an ActiveRecord::Relation and the other doesn't give me a class at all, it just prints out the content of the object.
Maybe when you use the .where method you get an array, even if there is only one match and therefore you always have to issue the .each method to get at the contents? But that makes it hard to deal with when you want to update records, etc.
Can someone clarify this for me? Specifically, how to deal with matches found through the .where method.
Thanks.
Try:
tec2 = Technique.where(:korean => 'Jok Sul').first
Good question.
tec_scope = Technique.where(:korean => 'Jok Sul') # create an internal query
Remember, here only the query is created, it is not executed. You can programmatically build on top of this query if you so wished. The scope (or query if you so wish) will be executed in 2 ways. "Implicit" or "Explicit". Implicit way of running the query happens for example in the console, which invokes a method on the scope which automatically runs the query for you. This wont happen in your controllers unless you run it explicitly for .e.g
tec_scope.all # returns array
tec_scope.first # retuns one element
Scopes are just adding where clauses/predicates to your query. It's query building and delaying the execution till it is needed.
However,
tec_objects = Technique.find(6) # explicitly runs a query and returns one object (in this case)
This will explicitly run the query there and then. It is a question of the timing of execution of the query.
The difference is subtle but very important.
This hasnt got anything to do with whether you get one result or an array.
Technique.find([4,5]) # will return an array
Technique.find(4) # will return one object
Technique.where(:some_key => "some value").all # will return an array
Technique.where(:id => 5).first # will return one object
The difference is in timing of the execution of the query. Don't let the console fool you into believing there is no difference. Console is implicitly firing the query for you :)
The find(6) returns a single object, because you're specifying the object ID in the database, which is guaranteed to be unique by convention.
The where call returns a collection, which may be only 1 item long, but it still returns a collection, not a single object.
You can reveal this difference. Using your example code, if you call tec.class vs. tec2.class I think you'll find that they aren't the same class of object, as you expect.
That is, the methods available to a collection of objects is different than the methods available on an instance of that object.

how to search from an array? (i have a problem when i'm searching an array)

Hi i have a problem when i'm searching an array (#doweets is the array, array with Doweet objects, Doweet is like status...)
how can i do the same search like here:
doweets = Doweet.where(:date => time1..time2)
on variable of array? when i write like this i get an error:
doweets = #doweets.where(:date => time1..time2)
what to do, to do it with select? how can i do it?
thanks guys,
gal
Not tested, but it should look a bit like this:
doweets = #doweets.select{|d| d.date>=time1 && d.date<=time2}
where is a method of Relation. Don't use all to return all results as Array. You can add finder methods as chain, and the query is executed when results are required, i.e., each, first or all are invoked. For Array, you should use find_all to search.
FYI:
ActiveRecord Query Interface
Module Enumerable

Comma Delinated string, of Ids, from Array of Objects. RoR

Why doesn't this work?
I have an array of Objects, one of the attributes is the db id. I can make the array like so.
qc_parts.map!{|a| a.id}
However when I want to just make it a string. With
qc_parts.map!{|a| a.id}.join(",")
I only get an array out. I've also tried .to_s & .to_a
Any idea why this would be happening?
qc_parts.map!{|a| a.id}.join(",") will return a string, but it will not to put that value into the variable qc_parts. To do that you have to do
qc_parts = qc_parts.map{|a| a.id}.join(",")
If I've misunderstood, and you actually are seeing the join method return an array, then something strange is going on.

Resources