Record not always found - ruby-on-rails

Consider the following
# setup an array of the question ids so far
questions_array = []
questions_array.push(session[:questions_array])
# take a random question whom id is not included in the session[:questions_array]
#question = Question.offset(rand(Question.count)).where('id NOT IN (?)',questions_array).take
# push id to array and later on assign the new array to the session
questions_array.push(#question.id)
session[:questions_array] = questions_array
I have two questions database. One of the two gets returned the other one gives me the error
NoMethodError (undefined method 'id' for nil:NilClass):
this line gives the error questions_array.push(#question.id)
this does not happen everytime! and that is what's strange!

This is how, you can solve it though:
Question
.where.not(id: questions_array)
.order('random()')
.first
But if the questions table get say more than 10,000 records for example, it will be slow. Then you could write recursive procedure, which will pick a random record and check some condition. if condition matches, returns the record, or recursion will go on with some base condition to break in worst case.

My bad seems that the problem lies in the fact that i first get a random id and then check if that id is not in the array which is not what i wanted. So if the random id was included in the array it would give an error as there is none to take.
this is the new line of code.
#question = Question.where('id NOT IN (?)',questions_array).first

Related

In Rails, how do I delete all the objects in an array?

I am using Rails 5 and I want to delete an array of objects. In a previous thread, I read "destroy_all" was the truth and the light. I had two arrays of objects, which I subtract to get a third array
unused_currencies = all_currencies - currencies_from_feed
unused_currencies.destroy_all
but when using destroy_all I got this error:
NoMethodError: undefined method `destroy_all' for #<Array:0x007feea8878770>
This code will make a single SQL query:
unused_currencies = all_currencies - currencies_from_feed
CurrencyModel.delete(unused_currencies)
where CurrencyModel is the model of your currencies.
You might want to use destroy if you need to run callbacks on the models:
unused_currencies = all_currencies - currencies_from_feed
CurrencyModel.destroy(unused_currencies.map(&:id))
This code will make a number of queries proportional to the number of unused currencies
Destroy_all is for active-record type things.
What exactly are you trying to do? if you just want to get rid of the array, you can override it with
unused_currencies = []
If you're trying to destroy a bunch of active record objects in the array you're going to have to iterate over it and delete each object individually.
destroy_all works for the ActiveRecord::Relation
If you want to clear the array, you can do: unused_currencies = []
If you want to delete each item in the in the array:
unused_currencies.each(&:destroy). This will generate a delete query per item.
To delete all the objects at once (assuming they all belong to the same model. This will blow up in your face if they don't!)
unused_currencies.first.class.destroy_all(unused_currencies.map(&:id))
If you use map, you load in memory all data. I think you can just do:
all_currencies.where.not(id: currencies_from_feed.select(:id)).destroy_all
if all_currencies and currencies_from_feed are ActiveRecord::Relation, this will generate only one request sql.

Storing value of calculation that query result is being ordered by with Rails

I'm new to rails but I still feel I should know the answer to this. Drawing a complete blank.
I have the following query that returns the expected results. However I want to also store the value the calculation they are being ordered by returns.
What is the best way of extracting this value.
Here is the line of code
#service = Service.order("ST_Distance(services.lon_lat, ST_GeomFromText('POINT (lat lon)', 4326))").limit(10)
As I said it returns the correct results but I'd also like to find the distance for each result
Thank you
Try this:
#services = Service.select("*, ST_Distance(services.lon_lat, ST_GeomFromText('POINT (lat lon)', 4326)) as st_distance").order("st_distance").limit(10)
the objects you get back in #services (note i changed this to the plural in keeping with convention) should have an additional method .st_distance, which is what i set the results of that function to be called with as st_distance

Rails: how to correctly modify and save values of records in join table

I would like to understand why in Rails 4 (4.2.0) I see the following behaviour when manipulating data in a join table:
student.student_courses
returns all associated records of courses for a given user;
but the following will save changes
student.student_courses[0].status = "attending"
student.student_courses[0].save
while this will not
student.student_courses.find(1).status = "attending"
student.student_courses.find(1).save
Why is that, why are those two working differently, is the first one the correct way to do it ?
student.student_courses[0] and student.student_courses.find(1) are subtly different things.
When you say student.student_courses, you're just building a query in an ActiveRecord::Relation. Once you do something to that query that requires a trip to the database, the data is retrieved. In your case, that something is calling [] or find. When you call []:
student.student_courses[0]
your student will execute the underlying query and stash all the student_courses somewhere. You can see this by looking at:
> student.student_courses[0].object_id
# and again...
> student.student_courses[0].object_id
# same number is printed twice
But if you call find, only one object is retrieved and a new one is retrieved each time:
> student.student_courses.find(1).object_id
# and again...
> student.student_courses.find(1).object_id
# two different numbers are seen
That means that this:
student.student_courses[0].status = "attending"
student.student_courses[0].save
is the same as saying:
c = student.student_courses[0]
c.status = "attending"
c.save
whereas this:
student.student_courses.find(1).status = "attending"
student.student_courses.find(1).save
is like this:
c1 = student.student_courses.find(1)
c1.status = "attending"
c2 = student.student_courses.find(1)
c2.save
When you use the find version, you're calling status= and save on entirely different objects and since nothing was actually changed in the one that you save, the save doesn't do anything useful.
student_courses is an ActiveRecord::Relation, basically a key => value store. The find method would only work on a model

How to get column from active record query

1 and #2 both do not work. Active Record drives me nuts because I cam never remember when it returns an object or an array. Neither is working this time.
question = Question.select('id, question, promo_title, promo_code, group_id').where(:group_id => group_id).limit(1)
1
cookies[:question_id] = question['id']
2
cookies[:question_id] = question.id
You need to do
cookies[:question_id] = question[0].id
Your query will give you Question::ActiveRecord_Relation object. In order to get the data, you can use #each to iterate through all the records, and #[] to get any specific from the resultant collection. In your case it is holding only one record, so you can use #[] method with the argument to it as 0.
Now question[0] will give you a Question instance, now you can call the #id method on it as per the regular Rails way.

rails combine parameters in controller

Hopefully this is a little clearer. I'm sorry but I'm very new to coding in general. I have multiple tables that I have to query in succession in order to get to the correct array that I need. The following logic for the query is as follows:
this gives me an array based upon the store :id
store = Stores.find(params[:id])
this gives me another array based upon the param .location found in the table store where that value equals the row ID in the table Departments
department = Departments.find(store.location)
I need to preform one last query but in order to do so I need to figure out which day of the meeting is needed. In order to do this I have to create the parameter day_of_meeting found in the table Stores. I try to call it from the array above and create a new variable. In the Table Departments, I there are params such as day_1, day_2 and so on. I need to be able to call something like department.day_1 or department.day_2. Thus, I'm trying to actually create the variable by join the words "department.day_" to the variable store.day_of_meeting which would equal some integer, creating department.day_1...
which_day = ["department.day_", store.day_of_meeting].join("")
This query finds uses the value found from the variable department.day_1 to query table Meeting to find the values in the corresponding row.
meeting = Meeting.find(which_day)
Does this make my problem any clearer to understand?
findmethod can only accept parameters like Meeting.find(1) or Meeting.find("1-xx").
so, what you need is Meeting.find(department.send("day_" + store.day_of_meeting.to_s))
Hope to help!

Resources