Show 3 items based on a date that can be future and past - ruby-on-rails

I have a model that holds a date that can be either upcoming or past. I preferably want to see the 3 upcoming items. But if there aren't any, I want to show the ones that have already past, with the most recent first.
So if there are all future ones:
future - future - future
If there are only two future ones:
past - future - future
How should I achieve this in my model?

if is range that you want you can adapt this for your case.
month = Date.today
range = ["`users`.`created_at`>= '#{month.beginning_of_month}') AND (`users`.`created_at` <= '#{month.end_of_month}'"]
User.where(range)

you can use simple data manipulation with rails by rails .order method
ex: Model.all.order('created_at DESC').limit(3)
This will give you last 3 future records.

Related

How to use startOfYear()/endOfYear() functions in Jira JQL?

I am trying to churn a report using JQL filter that displayed monthly ticket assigned to particular person in a year.
I am really confused regarding the usage of StartofYear() and EndofYear()
Since we only started using JIRA in November, below query should return data for the month of November (11M) but I am not sure why, the query below is not returning any data...
after startofyear("+11M") before endofyear("+11M")
From what I understand, the above query should return data from Starting of November to end of November right?
The offset parameter in the startOfYear/endOfYear functions is the offset of whole years (e.g. startOfYear(-1) means start of the last year).
Also, you need to specify an object that you want to limit to these months (e.g. issues created or resolved). And you need to use different operators.
In your case, you need to use any of the following JQLs:
created >= startOfMonth(-1) AND created <= endOfMonth(-1) (for November when executed in December)
created >= 2021-01-11 AND created <= 2021-11-30
Instead of <= endOfMonth(-1) you can use < startOfMonth().
See also more information in Atlassian Documentation.

Efficiently retrieving ice_cube schedules for a given time period

I'm looking into using Ice Cube https://github.com/seejohnrun/ice_cube for recurring events.
My question is, if I then need to get any events that fall within a given time period (say, on a day or within a week), is there any better way than to loop through them all like this:
items = Records.find(:all)
items.each do |item|
schedule = item.schedule
if schedule.occurs_on?(Date.new)
#if today is a recurrence, add to array
end
end
This seems horribly inefficient but I'm not sure how else to go about it.
That's one approach - but what people do more often is end up denormalizing their schedules into a format that is conveniently queryable.
You may have a collection called something like ScheduleOccurrences - that you build each week / and then query that instead.
Its unfortunate it has to work this way, but sticking to the iCal way of managing schedules has led IceCube to need to format its data in certain ways (specifically ways that can line up with the requirements of the iCal RFC).
I've been doing some thinking recently about what a library would look like that shook away some of those restrictions, for greater flexibility like this - but its definitely still a bit off.
Hope this helps
I faced a similar problem and here was my approach:
Create a column on Event table to store the next occurrence date, and write a method which stores that value after_save. (method available through ice_cube. Perhaps index column too for faster querying.)
Then you can query the database for occurrences happening in the timeframe you need. See below:
Event.where(next_occurrence: Date.today.all_day)
Store EventOccurrences on a separate table.
Update the next_occurrence column for the rows returned to you by your query. Or something similar. This works for me because I'm running a daily job, so that update next_occurrence will run regularly. But you may need to tweak a bit.

How do you store recurring time periods on a database? Like "from the first of january to the last day of may"?

I have to store recurring date periods, similar to the one in the title, and I have no idea if there is an optimal day to do this. The first solution I came up with was to have day and month fields for start and end dates, but this solution doesnt sound very right to me.
I am using Ruby on Rails with SQL.
To store recurring dates of arbitrary complexity, you want to look into temporal expressions.
Some gems available are: runt, TExp or icecube
I've used both runt and icecube, as well as storing recurring dates (weekly schedules) in serialized ruby objects. The gems are the most flexible, if a little hard to use when your use case is simple.
Also if you need to parse textual expersions, look at Chronic
In ruby, you could probably express this nicely (for a particular year) with a Range:
(Time.utc(2012, 1, 1)..Time.utc(2012, 5, 1).end_of_month)
But storing this in a database...can only think of doing what you said (columns for start/end day and month), and then adding wrapper methods on the model similar to this:
def current_start
Time.utc(current_year, start_month, start_day)
end
...
def current_range
(current_start..current_end)
end
I would just use two dates... afaik that maps nicely to ruby Date objects anyway, with which you can do the usual arithmetic.

Find WorkItems that were assigned to X in the last 30 days

I'm trying to find all WorkItems that were assigned to a person X in the last 30 days.
The big problem I have is the "in the last 30 days"-part.
I thought about using the "ever" or "asof" keywords, but couldn't find a good answer yet.. something like WHERE [Assigned To] = 'X' AND (([Assigned To] != 'X') asof '<30daysago>').
But this is still not a bulletproof solution.
Any better ideas?
Thanks & kind regards
Simon
It appears that this is not possible using just WIQL, but you can get close.
The keyword #Today will give you today's date, then just subtract your range from it. The EVER keyword applied to [Status]='AssignedTo' and a comparison against a date 30 days in the past to [StateChangeDate] is what you'll need to accomplish this.
As close as you can get with WIQL and existing fields:
This says, from all revisions (status changes) return records where the user 'X' has ever been AssignedTo and the State has changed in the last 30 days. This will basically give you a slightly fuzzy picture of what your User has been working on in the last month.
WHERE [Microsoft.VSTS.Common.StateChangeDate] >= #today - 30
AND [System.AssignedTo] EVER 'Bennett Aaron'
ORDER BY [System.State]
Add the missing field:
You could add a custom field called AssignedDate that is captured during the New->AssignedTo workflow transition that you create in the Work Item Definition XML. You can accomplish this using the Team Foundation Server Power Tools extension to Visual Studio. This would give you exactly what you need as well as additional reporting options going forward.
TFS API
I cannot help you with this one, but I believe you could query using the TFS API.
A couple of quick gotchas I've experienced to save you time on ASOF and EVER:
AsOf won't help you by itself with this as it does not support a range of dates. It allows you to query as if it were another date. In other words, if you forgot to capture the results of a query yesterday, you can use an AsOf query to get the results that you would have gotten had it run yesterday. What I understand is that you want to query a basic date range.
EVER might not work as you expect against dates as I believe it uses the exact value of the field (timestamp portion of the date field would be included) it tests with. Just make sure the EVER keyword is used against the status field rather than a date.

How would you build this daily class schedule?

What I want to do is very simple but I'm trying to find the best or most elegant way to do this. The Rails application I'm building now will have a schedule of daily classes. For each class the fields relevant to this question are:
Day of the week
Starting time
Ending time
A single entry could be something such as:
day of week: Wednesday
starting time: 10:00 am
ending time: Noon
Also I must mention that it's a bi-lingual Rails 2.2 app and I'm using the native i18n Rails feature. I actually have several questions.
Regarding the day of the week, should I create an extra table with list of days, or is there a built-in way to create that list on the fly? Keep in mind these days of the week will have to be rendered in English or Spanish in the schedule view depending on the locale variable.
While querying the schedule I will need to group and order the results by weekday, from Monday to Sunday, and of course order the classes within each day by starting time.
Regarding the starting time and ending time of each class would you use datetime fields or integer fields? If the latter how would you implement this exactly?
Looking forward to read the different suggestions you guys will come up with.
I would just store the day of the week as an integer. 0 => Monday ... 6 => Sunday (or any way you want. ie. 0 => Sunday). Then store the start time and end time as Time.
That would make grouping really easy. All you would have to do is sort by the day of the week and the start time.
You can display this in multiple ways, but here is what I would do.
Have functions like: #sunday_classes = DailyClass.find_sunday_classes that returns all the classes for Sunday sorted by start time. Then repeat for each day.
def find_sunday_classes
find_by_day_of_week(1, :order -> 'start_time')
end
Note: find_by probably should have id at the end but that's just preference in how you want to name the column.
If you want the full week then call all seven from the controller and loop trough them in the view. You could even create detail pages for each day.
Translation is the only tricky part. You can create a helper function that takes an integer and returns the text for the appropriate day of the week based on local.
That's very basic. Nothing complicated.
If your data is a Time then I would store that as a Time - otherwise you will always have to convert it out of the database when you do date and time related operations on it. The day is redundant data, as it will be part of the time object.
This should mean that you don't need to store a list of days.
If t is a time then
t.strftime('%A')
will always give you the day as a string in English. This could then be translated by i18n as required.
So you only need to store starting time and ending time, or starting time and duration. Both should be equivalent. I would be tempted to store ending time myself, in case you need to do data manipulations on ending times, which therefore won't have to be calculated.
I think most of the rest of what you describe should also fall out of storing time data as instances of Time.
Ordering by week day and time will just be a matter of ordering by your time column. i.e.
daily_class.find(:all, :conditions => ['whatever'], :order => :starting_time)
Grouping by day is a little more tricky. However this is an excellent post on how to group by week. Grouping by day will be analogous.
If you are dealing with non-trivial volumes of data, it may be better to do it in the database, with a find_by_sql and that may depend on your database's time and date functionality, but again storing the data as a Time will also help you here. For example in Postgresql (which I use), getting the week of a class is
date_trunc('week', starting_time)
which you can use in a Group By clause, or as a value to use in some loop logic in rails.
Re days-of-week, if you need to have e.g. classes that meet 09:00-10:00 on MWF, then you could either use a separate table for days a class meets (keyed by both class ID and DOW) or be evil (i.e. non-normalized) and keep the equivalent of an array of DOW in each class. The classic argument is this:
The separate table can be indexed in a way to support either class-oriented or DOW-oriented selects, but takes a bit more glue to put the entire picture together for a class.
The array-of-DOW is simpler to visualize for beginning programmers and slightly simpler to code about, but means that reasoning about DOW requires looking at all classes.
If this is only for your personal class schedule, do what gets you the value you're looking for, and live with the consequences; if you're trying to build a real system for multiple users, I'd go with a separate table. All those normalization rules are there for a reason.
As far as (human-readable) DOW names, that's a presentation-layer issue, and shouldn't be in the core concept of DOW. (Suppose you decided to move to Montreal, and needed French? That should be another "face" and not a change to the core implementation.)
As for starting/ending times, again the issue is your requirements. If all classes begin and end at hour (x:00) boundaries, you could certainly use 0..23 as the hours of the day. But then your life would be miserable as soon as you had to accommodate that 45-minute seminar. As the old commercial said, "Pay me now or pay me later."
One approach would be to define your own ClassTime concept and partition all reasoning about times to that class. It could start with a simplistic representation (integral hours 0..23, or integral minutes after midnight 0..1439) and then "grow" as needed.

Resources