How to find the difference between two arrays after calling a method - ruby-on-rails

I'm trying to subtract the earliest date from two arrays:
def days_pending
start = [object.created_at]
finish = [Time.now.strftime('%Y-%m-%d')]
if object.app_sign_date
start.push(object.app_sign_date)
end
if object.submitted_date
start.push(object.submitted_date)
end
if object.inforce_date
finish.push(object.inforce_date)
end
if object.closed_date
finish.push(object.closed_date)
end
finish.min - start.min
I have no problem calling min on the arrays, but have a problem calling the min method and then subtracting. I get NoMethodError: undefined method-' for "2015-01-01":String`.

the array finish has first element as string not the date. you need to add appropriate object instead ie. date or datetime
finish = [Time.now]
or
finish = [DateTime.now]

After calling Time.now.strftime('%Y-%m-%d'), what you got is a string.
Change to Time.now should work.

If you need the output to be in the form "2015-01-01" you could use parse:
Time.parse(finish.min) - start.min

Related

How to wait for all Concurrent::Promise in an array to finish/resolve

#some_instance_var = Concurrent::Hash.new
(0...some.length).each do |idx|
fetch_requests[idx] = Concurrent::Promise.execute do
response = HTTP.get(EXTDATA_URL)
if response.status.success?
... # update #some_instance_var
end
# We're going to disregard GET failures here.
puts "I'm here"
end
end
Concurrent::Promise.all?(fetch_requests).execute.wait # let threads finish gathering all of the unique posts first
puts "how am i out already"
When I run this, the bottom line prints first, so it's not doing what I want of waiting for all the threads in the array to finish its work first, hence I keep getting an empty #some_instance_var to work with below this code. What am I writing wrong?
Never mind, I fixed this. That setup is correct, I just had to use the splat operator * for my fetch_requests array inside the all?().
Concurrent::Promise.all?(*fetch_requests).execute.wait
I guess it wanted multiple args instead of one array.

Call a method from constructed string in Ruby / Rails

I've got a problem in doing some metaprogramming in Ruby / Rails which must be minor, but I can't get the clue.
I wan't to assign values to an active record relation, with my model having attributes:
MyModelClass.p1_id,
.p2_id,
...
.p8_id
SecondModel.position #Integer in (1..8)
I now want to do the following
sms = SecondModel.where(:xyz => 'bla')
sms.each do |sm|
mmc = MyModellClass.first
mmc.#somehow construct method here = sm.id
end
So that somehow this is accomplished
mmc.p1_id = sm.id
mmc.p2_id = sm.id
..
mmc.p8_id = sm.id
To sum up: I want to create that p*n*_id stuff dynamically, but I can't find out, how to tell Ruby, that this should be a method. I tried so far:
mmc.send('p#{sm.position.to_s}_id'.to_sym) = sm.id
But this doesn't work. Any clues?
You were close. Try this:
mmc.send("p#{sm.position.to_s}_id=", sm.id)
Here we call the method with = and pass the value of attribute as the second argument of send

undefined method `offset' for an array in Ruby

I am using the following step in my pagination method steps:
Edit : nodes2 is an array.
nodes = nodes2.take(per_page).offset((page_number.to_i - 1) * per_page)
#length = (nodes2.count/per_page).ceil
I get the following error:
undefined method 'offset' for #<Array:0x00000005905128>
Basically I am using the following steps and they work fine as I get the objects out of .leaves method, but am not sure how to deal with the array
nodes = inode.leaves.limit(per_page).offset((page_number.to_i - 1) * per_page)
#length = (inode.leaves.count/per_page).ceil
Could some one pls help me out. Thanks!
take is a method on Array. When you run it against nodes2 (which I assume is an ActiveRecord::Relation object), it's doing the equivalent of this:
nodes = nodes2.to_a.take(per_page)...
So because of this, offset is being run on an Array object. You could try making take(...) be the last method call, that way offset is still being run against ActiveRecord:
nodes = nodes2.offset((page_number.to_i - 1) * per_page).take(per_page)

Merge Time into a DateTime to update Datetime

I need to update time info in a DateTime.
I get a string in the format "14" or "14:30" (for example), so I need to give it to Time parser to get the right hour. Then I need to update self.start_at which is a datetime which already has a time, but I need to update it.
self.start_at_hours = Time.parse(self.start_at_hours) # example 14:30:00
# NEED TO UPDATE self.start_at which is a datetime
I was using the change method on self.start_at but it only takes hour and minutes separated and I'm not sure what should I do.
Have you thought about doing somethings like this?
time_to_merge = Time.new
date_to_merge = Date.today
merged_datetime = DateTime.new(date_to_merge.year, date_to_merge.month,
date_to_merge.day, time_to_merge.hour,
time_to_merge.min, time_to_merge.sec)
For replacing time, the .change() method should work, like this:
my_datetime = my_datetime.change(hour: my_time.hour, min: my_time.min, sec: my_time.sec)
For adding time, try converting to seconds and then adding them:
my_datetime += my_time.seconds_since_midnight.seconds

How to compare dates?

get_time_now = Time.now.strftime('%d/%m/%y')
question_deadline_time = (question.deadline.to_time - 2.days).strftime('%d/%m/%y')
if get_time_now == question_deadline_time #2 days till deadline
Notifier.deliver_deadline_notification(inquiry, question, user, respondent , i)
end
I need :
If until deadline's date are remaining 2 DAYS so I deliver email. How i can do it?
UPD
when i write:
deadline = question.deadline.midnight - 2.days
if Time.now.midnight >= deadline
I get:
lib/scripts/deadline_notifier.rb:26: undefined method `midnight' for "19/07/11":String (NoMethodError)
from lib/scripts/deadline_notifier.rb:18:in `each'
from lib/scripts/deadline_notifier.rb:18
without midnight i get:
lib/scripts/deadline_notifier.rb:26: undefined method `-' for "19/07/11":String (NoMethodError)
from lib/scripts/deadline_notifier.rb:18:in `each'
from lib/scripts/deadline_notifier.rb:18
Use a combindation of .midnight (or .end_of_day) and 2.days to get what you want:
deadline = question.deadline.midnight - 2.days
if Time.now.midnight >= deadline
#deliver
end
edited:
I highly recommend you change question.deadline to be a datetime. If you can't do that, then you need to convert your string to a date to perform calculations on it. #floor's method works fine, or you can do this as well:
"2011-07-18".to_date
From the error it looks like you are trying to run a DateTime method on a string. If you have a DateTime object and run a strftime('%d/%m/%y') on it, you can't call DateTime methods any more because it is no longer an object, just a plain ol' string. So you can't run midnight or use the subtract operand.
Also, what format is the string that you are storing? You can try casting it with "date string".to_date, then running your methods on it.

Resources