saved_report.rb
Hipposoft 2011
Describe and record all parameters needed to generate reports.
13-Oct-2011 (ADH): Created.
Range maps and “update_cached_ranges”: An effective hack to map a Report’s indication of date range to a Date value which can be stored in the database. Store very early dates, so that people can ask the database to sort on the cache values and get relative-style date reports collected together. Yes, this does mean that attempts to report time in early January of the year 4000 would result in confusion, but only confusion for views which use the cached range values for sorting. They’re not used for any report mathematics calculations. In practice only the ‘Saved Reports’ index view would do the wrong thing; and it’s something of an edge use case :-)
A high future date is used rather than a low past date (e.g. the 1900s) so that sorting makes sense. If you wanted to see your most recent reports, for example, you’d sort descending by start date. But chances are any of the relative dates are likely to be the most recent, or a good enough approximation, so they should show up first in a descending sort.
It would theoretically be possible to sweep a user’s saved reports at an “appropriate moment” (e.g. rendering of the index view) and update all of the cached dates to actual values and give a true accurate sort, but that’s an unbounded performance problem and not really necessary.
Various constants used by the “20111013142252_add_saved_reports_support.rb” migration file and various pieces of application code
Is the given user permitted to update this report? Only report owners or administrators can do so.
# File app/models/saved_report.rb, line 157 def can_be_modified_by?( comparison_user ) comparison_user == user or comparison_user.admin? end
Return (and cache) a TrackRecordReport::Report instance based on the attributes of this SavedReport model instance. The result is cached for later access within the current request. If you alter attribute values, pass ‘true’ on entry to force a refresh of the cache and update the TrackRecordReport::Report instance.
Optionally, pass in a user. Without this, the saved report’s own user details will be used for task filtering and so-on. If you allow another user to view someone else’s report, then you will want to pass in that other user’s details, since that user may be subject to different restrictions (in particular, differing permitted task lists).
# File app/models/saved_report.rb, line 103 def generate_report( flush_cache = false, viewing_user = user ) if ( @report.nil? || flush_cache ) # The TrackRecord internal Report object can be created from this # instance's attributes directly, except for many-to-many relationships, # which are not exposed in that hash and must be assigned manually. @report = TrackRecordReport::Report.new( viewing_user, attributes() ) @report.title = title @report.active_task_ids = active_task_ids @report.inactive_task_ids = inactive_task_ids @report.reportable_user_ids = reportable_user_ids end # Sneakily in passing attempt to update our cached start and end ranges update_cached_ranges( @report ) @report end
Is the given user permitted to do anything with this report? A shared report can be viewed by anyone, privileged users can view any report and of course the report’s owner can view it.
# File app/models/saved_report.rb, line 150 def is_permitted_for?( comparison_user ) shared? or comparison_user == user or comparison_user.privileged? end
# File app/models/saved_report.rb, line 141 def range_end_cache raw_attr_val = self[ :range_end_cache ] CACHED_REVERSE_RANGE_MAP[ raw_attr_val ] || raw_attr_val end
Overload default attribute accessors to provide more meaningful values for start and end ranges (see private method “update_cached_ranges” for the other half of this from an implementation standpoint, if interested).
Each returns either a Date for a fixed report start or end date, or a symbol - “:all” indicates start-or-end-of-all-time, while symbols starting with ‘last’, ‘this’ or ‘two’ and ending in ‘_month’ or ‘_week’ refer to last month/week, this month/week or two months/weeks ago, respectively (e.g. “:two_week”, “:last_month”).
# File app/models/saved_report.rb, line 136 def range_start_cache raw_attr_val = self[ :range_start_cache ] CACHED_REVERSE_RANGE_MAP[ raw_attr_val ] || raw_attr_val end