Can't add modifed elements to Array in Ruby - ruby

I have select of events from db.
I need clone each element 30 times and set elem.shedule different dates (every day at current month -2013-04-01 .. 2013-04-30).
It is my code ('shedule' field is date):
daily_events = Events.All
repeated_events = []
for event in(daily_events)
for day in(1..date.end_of_month.day)
repeat_event = event
repeat_event.shedule = Date.new(date.year, date.month, day)
repeated_events << repeat_event
end
end
But as results I have each elem 30 times everywhere with same last of month day date (2013-04-30)
How to fix it?
If I set repeated_events+=repeat_event instead of repeated_events << repeat_event
I have TypeError in EventsController#index
can't convert Event to Array (Event#to_ary gives NilClass)
I think it is because I clone just a reference to element, not contents of element. What is way to fix it?

Each time through the inner loop, repeat_event is a reference to the same event object. Your array ends up storing many references to that single object, so when you make an assignment to repeat_event.shedule, it affects them all.
Try using dup to make a copy, like so:
repeat_event = event.dup

I figured out that I need deep copy and use Marshal module
So my solution is
repeat_event = Marshal.load(Marshal.dump(every_day_event))
Thanks for all!

Related

How to loop through days, starting today and through a target date

I tried using answers for this question but was not able to get something that worked.
I want to be able to loop through days, starting today and going up to a target date set for an object.
The target date is of type Date.
I have tried a few things, all variations on the answers above, this was last attempt.
count = 0
Time.now..goal.target_date do
count += 1
end
This does not loop through anything and returns 0 as the count. Right now this is only in dev, with one object, so I know there are many days between now and the target (which is set for December 31 of this year).
I also tried this.
count = 0
Date.new(Time.now)..goal.target_date do |date|
count += 1
end
Which returns the error undefined method 'div' for 2018-10-06 17:23:41 -0500:Time. (Same error if I use Date.today just with :DATE instead of :Time at the end).
Can anyone help me get this to run the loop for each day between now and the target date?
Thanks!
Just wrote this one using de Date.upto() method and it worked... you just gotta make sure that 'goal.target_date' is also a valid instance of Date
require 'date'
from = Date.today
goto = from + 3
from.upto(goto) do |date|
puts date
end
Do you need a loop? If not, try this:
count = (goal.target_date - Date.current).to_i
I hope it useful for you. :)

Ruby 2D Extracting Information

I am relatively new to coding and am learning ruby right now. I came across a problem where I have a huge data record (>100k record) consisting of unique ID and another consisting of the date of birth. So it's basically a 2D array. How do I go about creating a method such that every time when I key in method(year), it will give me all the unique ID of those born in the year i choose? And how do I loop this?
The method I tried doing is as follow:
def Id_with_year(year)
emPloyee_ID_for_searching_year = [ ]
employeelist.sort_by!{|a,b|b}
if employeelist.select{|a,b| b == year}.map{|a,b| a}
return emPloyee_ID_for_searching_year
end
end
I should point out that the ID are sorted. That's why I am trying to sort the year in this method so that it will give me all the ID for the year I key in. The output I had was that it returned me [ ] with nothing inside instead of the ID.
Sidenote: methods in ruby are to be named in snake case (this is not mandatory, though.)
The problem you experience is you return what was never changed. The below should work:
def id_with_year(year)
employeelist.sort_by(&:last) # sorting by last element of array
.select{|_,b| b == year} # select
.map(&:first) # map to the first element
end

ruby / rails - hash max by :key does not return largest value

I have a query that looks for all events on a given date #s_date. Event start_datetime is within day OR - event end_datetime is within day
#s_hash_items = #company.events.where('(start_datetime > ? AND start_datetime < ?) OR
(end_datetime > ? AND end_datetime < ?)',
#s_date.beginning_of_day, #s_date.end_of_day,
#s_date.beginning_of_day, #s_date.end_of_day)
I am then trying to find the latest end_datetime value from this array. E.g. there are 3 events finishing at 14:00, 17:30 and 15:00, I want to return 17:30. But, if there is an event that runs over to the next day, I want the max result to be 23:59:59 on #s_date).
My code to do that looks like this
#s_end_hour = [#s_hash_items2.max_by{:end_datetime}.end_datetime, Time.now.end_of_day].sort.first.hour
So it produces an array with latest end date time, and end of day, and picks out whichever one is earlier (sort.first), then returns the hour number, e.g. 17 in this case.
However, the max_by method is not finding the event with the latest end_datetime. It seems to vary depending on the order of the #s_hash_items result. But the order of #s_hash_items shouldn't matter - I just want the max value. What am I doing wrong here? Thanks.
This doesn't do what you think it does:
#s_hash_items2.max_by{:end_datetime}
That's same as saying:
#s_hash_items2.max_by { 11 }
i.e. you're asking max_by to find the element with maximum :end_datetime Symbol (a constant value) and that's a bit pointless.
If you want max_by to call the end_datetime method then you want a block that returns the the end_datetime value of the objects:
#s_hash_items2.max_by { |item| item.end_datetime }
or more concisely (and probably what you were trying to say):
#s_hash_items2.max_by(&:end_datetime)
The & more or less turns the symbol into the { |item| item.end_datetime } block in the first previous example.

UTC time resets to 2000-01-01 (ruby). How do I prevent the time from resetting?

I'm using a task and the spreadsheet gem to read in an excel spreadsheet into my database. One of the columns I'm reading in is "start_time." To do this, I'm forming an array of values, then passing in each of these array values, one by one.
cnum_array = [] # for start times
sheet1.each 3 do |row|
unless row[9].blank?
time = Time.parse(row[9])
cnum_array << time.utc
end
end
count = 0
for course in Course.all
course.update_attribute :start_time, cnum_array[count]
count += 1
end
This seems to work fine. If I insert a "puts course.start_time" statement within this last loop, it prints off the right time. Like so:
count = 0
for course in Course.all
course.update_attribute :start_time, cnum_array[count]
puts course.start_time
count += 1
end
This gives me the right time, e.g. "2012-01-23 15:30:00."
But when I look up the course time later (e.g. via my console's Course.find(1).start_time), it gives me "2000-01-01 15:20:00." So the time of day is right, but the day itself goes back to 2000-01-01.
Does anyone know why this is happening, and how I can fix it? Thanks!
You are using the Time class. This class deals with times, not dates. My guess is that your database column is of type time as well.
I recommend you use a datetime (or possibly timestamp) column type.

How do I generate a hash from an array

I'm trying to build a hash from an array. Basically I want to take the unique string values of the array and build a hash with a key. I'm also trying to figure out how to record how many times that unique word happens.
#The text from the .txt file:
# **Bob and George are great! George and Sam are great.
#Bob, George, and sam are great!**
#The source code:
count_my_rows = File.readlines("bob.txt")
row_text = count_my_rows.join
puts row_text.split.uniq #testing to make sure array is getting filled
Anyways I've tried http://ruby-doc.org/core/classes/Hash.html
I think I need to declare a empty hash with name.new to start I have no idea how to fill it up though. I'm assuming some iteration through the array fills the hash. I'm starting to think I need to record the value as a separate array storing the time it occurs and the word then assign the hash key to it.
Example = { ["Bob",2] => 1 , ["George",3], =>2 }
Leave some code so I can mull over it.
To get you started,
h={}
h.default=0
File.read("myfile").split.each do |x|
h[x]+=1
end
p h
Note: this is not complete solution

Resources