search and change field value in query result in rails - ruby-on-rails

I have a model Sensor and a query from this model:
#sensors = Sensor.where(device_id: 4)
Output is:
Id seq_num temp
5 1 40
6 2 41
7 3 45
First: I want to search this query result for example locate (find) for seq_num = 2
(#sensors.find(seq_num = 2))
Second: after find a record change temp value and save to database. It is possible that all of record changed.
How can do first and second?

If seq_num value is unique for all sensors, then you can find a sensor in #sensors list by its seq_num value using this code:
sensor = #sensors.detect { |s| s.seq_num == 2 }
detect method returns the first found element or nil in nothing was found.
To save all the sensors after updating their temp value you can use this code:
#sensors.each { |s| s.save }
or
#sensors.each(&:save)
Only those sensors that have temp value changed will be saved.

# First
#sensors = Sensor.where(device_id: 4, seq_num: 2)
# Second
Sensor.update_all({:temp => 1}, {device_id: 4, seq_num: 2})

your question is a bit unclear. You want to get a list of all sensors, and then only get the one with seq_num 2. Do you still need the rest of the data in #sensors? Then you want to change the value in the one you found and save it? Also do you need to work with the device, since asssuming sensor belongs to device you can query through the Device association.
if you need all sensors in #sensors. you can do this.
#sensors = Sensor.where(device_id: 4)
#sensor = #sensors.find { |sensor| sensor.seq_num == 2 }
if you only need the one sensor you can do
#senser = Sensor.where(device_id: 4, seq_num: 2)
as for changing the data and saving it ,
#sensor.temp = new_temp
#sensor.save

Related

Check values between two arrays

Feel like the title summed it up pretty well. I have two large arrays, all containing ids.
One is the old_list and one is the current_list. What I would like to do is this:
delete all the values in the old_list, that are not present in the current_list
if the value in the current_list is present in the old_list don't do anything
if the value in current_list is new then create it and add it to the old_list
This is set as a background job that updates every 4 hours. Thus I want to see if any new value have appeared, or been removed since I last checked.
Here is what I have currently, which is not complete:
twitter.follower_ids("#{uid}").each do |f_id|
# unless user already has follower id saved
unless followers.map(&:follower_id).include?(f_id.to_s)
followers.create do |follower|
follower.follower_id = f_id
end
end
end
You need to do the below Set operation :
(old_list & current_list) | current_list
Example :
old_v = [1,2,43]
new_v = [1,11,21]
(old_v & new_v) | new_v # => [1, 11, 21]
Array#& and Array#|.

If table contains a key with specific value

It might be a bit confusing, but I have a table, for example, called Ant.
This table, contains a bunch of other (unnamed) tables. These tables represent ants, and hold values.
Kind of like this:
Ant = {
{age=3,speed=10},
{age=6,speed=7}
}
My question is, how would I check if any of the unnamed table inside of the Ant table contains a specific value to age.
So, for example, I'd like to check if any of my ants are aged 3 years old.
I hope I was clear enough, and thanks in advance!
You can loop through the table and check:
for i, v in ipairs(Ant) do
if v.age == 3 then
print( i )
end
end
It'll print the index at which your 3 year old ants are stored.
If all you need to check the value of age in each sub-table, building a custom iterator is another way:
function age_iter(t)
local i = 0
return function()
i = i + 1
return t[i] and t[i].age
end
end
To iterate over all the age value would be:
for age in age_iter(Ant) do
print(age)
end
It's easy to modify it to check if one of the age value is equal to 3.

Ruby random selection from array sometimes returns same value repeatedly

I am using this to select a random Matchup, and I test it's results, and draw a random Matchup until it meets the criteria of a while loop:
m = Matchup.order("RANDOM()").first
The loop is set to break after 10 cycles (to avoid infinite loops), and I will arbitrarily break out of the loop, check the logs, and see that the Matchup is the same every time it went through the loop. A simplified version of the loop would be something like this:
counter = 0
while counter < 5
m = Matchup.order("RANDOM()").first
logger.debug('Matchup ID: ' + m.id)
counter += 1
end
The log will look like this:
Matchup ID: 7
Matchup ID: 7
Matchup ID: 7
Matchup ID: 7
Matchup ID: 7
Why would m = Matchup.order("RANDOM()").first arbitrarily not pull a different Matchup? The strangest part is that sometimes it works without issue, and others it gets stuck in the loop b/c m is not changing. Any suggestions?
If you want to see the actual loop, you can see it here (in the getRandomMatchup function):
https://github.com/jackerman09/wdis/blob/master/app/controllers/static_pages_controller.rb
To add another variant :)
ids = Matchup.pluck(:id)
m = Matchup.find( ids.shuffle.first )
This will work well unless the set of id values is excessive, in which case you are shuffling a very large array. However, in the 1k to 2k set size, it will not be noticeable to a user.
Or simply:
ids = Matchup.pluck(:id)
m = Matchup.find( ids.sample )
Will choose a random item from the ids array.
You can use shuffle for this:-
Matchup.all.shuffle!.first
Assuming this model is a normal ActiveRecord model, You could try something like:
max_id = Matchup.maximum(:id)
id = rand(max_id)
m = Matchup.find(id)
...
Doing so might be cheaper than asking the database to get you randomly ordered records. However, the downside of this approach is that records may be deleted, so Matchup.find(id) may be nil.
Another, better, way to do this might be:
ids = Matchup.pluck(:id)
m = Matchup.find(ids[rand(ids.length)])

groovy simple way to find hole in list?

I'm using the grails findAllBy() method to return a list of Position(s). Position has an integer field called location, which ranges from 1 to 15. I need to find the lowest location in the position list that is free.
For example, if there are positions at locations 1,2 and 4, then the algorithm should return 3. If locations 1 - 4 were filled, it would return 5.
Is there some simple groovy list/map functions to get the right number?
Thanks
If your list of positions were (limited to a mx of 5 for brevity):
def list = [ 1, 2, 4, 5 ]
And you know that you have a maximum of 5 of them, you can do:
(1..5).minus(list).min()
Which would give you 3
Just another option, because I originally thought he wanted to know the first unused slot in a list, say you had this:
def list = ['a', 'b', null, 'd', 'e', null, 'g']
You could easily find the first empty slot in the array by doing this:
def firstOpen = list.findIndexOf{ !it } // or it == null if you need to avoid groovy truth
Tim's way works, and is good for small ranges. If you've got the items sorted by location already, you can do it in O(n) by leveraging findResult
def firstMissing = 0
println list.findResult { (it.location != ++firstMissing) ? firstMissing : null }
prints 3.
If they're not sorted, you can either modify your db query to sort them, or add sort{it.location} in there.

updating wrong value to database

I'm just trying to increment a record by 1 starting at 2000, when a new record is created upon clicking on the create action to create a record:
if resource_model == Student then #resource.testing_id = id + 2000 end
So if the record has an id of 1, I assume that the testing_id will be 2001. But instead it returns:
2147483647 (maximum mysql limit?)
Any suggestions on how to address this? Thanks.
You can't know record ID during create. ID is known after saving record do database.
You can't relay on ID to give you values like 1, 2, 3 ... and so on.
Don't store value like ID+2000, becouse you can get it at any time by calculating id+2000.
You can get next testing_id by something like this:
if resource_model == Student then
#resource.testing_id = Student.first(:order => "testing_id DESC").testing_id + 1
end
But if two processes at the same time will fetch the same value then you will have duplicate testing_id.
Object.idf is a (deprecated) method that returns the Ruby object ID, which uniquely identifies the object. Rails has overridden id so that in models it refers to the database primary key. I'm going to take a guess that your code snippet is from a controller, and that's why id is returning a strange and large number: It's the Ruby object id of the controller, not the primary key of the object. Give id a receiver, e.g. #resource.id, and see how that works.
2147483647 = 2 ^(32-1)
Could you show some of your code here?
From what i'm guessing here is that you are comparing apples with strawberries :P.
I think you are adding a "1" on a string so that means for example:
2000 + 1 = 20001
20001 + 1 = 200001
So if you do that a couple of times this means you will get to the maximum size of an int (21475483647). I don't know this for a 100% sure, but this has to do with the way you ask your question and the way you don't post code etc...
I hope this edit was helpfull tho.

Resources