Module: ArchiveTree::Core
- Defined in:
- lib/archive_tree/core.rb
Overview
:nodoc:
Instance Method Summary collapse
-
#archive_node(options = {}) ⇒ Object
Named scope that retrieves the records for a given year and month.
-
#archive_tree(options = {}) ⇒ Object
Constructs an archive tree in the form of a nested Hash.
-
#archived_months(options = {}) ⇒ Object
For a given year, constructs a single-level hash of months using the defined
date_field
column. -
#archived_years ⇒ Object
Constructs a single-level hash of years using the defined
date_field
column.
Instance Method Details
#archive_node(options = {}) ⇒ Object
Named scope that retrieves the records for a given year and month.
Note: This scope can be chained, e.g. Post.archive_node.where(‘id > 100’)
Default behaviors
* :year #=> defaults to the current year (e.g. 2010)
* :month #=> all
Example using default values:
Post.archive_node
Example overridding values:
Post.archive_node(:year => 2010, :month => 1)
18 19 20 21 22 23 24 |
# File 'lib/archive_tree/core.rb', line 18 def archive_node(={}) .reverse_merge! ({ :year => Time.now.year }) where("#{date_field} IS NOT NULL"). where("EXTRACT(YEAR FROM #{date_field}) = :year", :year => [:year]). where("EXTRACT(MONTH FROM #{date_field}) = :month OR :month IS NULL", :month => [:month]) end |
#archive_tree(options = {}) ⇒ Object
Constructs an archive tree in the form of a nested Hash.
Hash levels
1. Years (integer)
2. Months (integer)
3. Your records (ActiveRecord::Relation)
Default behaviors to take note:
* All records are sweeped by default based on their +date_field+ column
* Years without records are not returned
* Months without records are not returned
* The keys are integers, thus they will likely require conversion
Options
* :years => Array of years to sweep
* :months => Array of months to sweep of each year
* :years_and_months => Hash of years, each containing an Array of months to sweep
* :month_names => Accepts one of two symbols :long and :short. Please note that this overrides the default value
Examples context
Please note that for the sake of simplicity these examples assume that any given year has only one +Post+
record for any given month and will be represented in the following format:
{ 2010 => {1 => [post]} }
Default usage:
Post.archive_tree #=> { 2010 => { 1 => [Post], 2 => [Post] },
2011 => { 1 => [Post], 4 => [Post], 8 => [Post] } }
Sweep all months of the current year:
Post.archive_tree(:years => [Time.now.year]) #=> { 2010 => { 1 => [Post], 2 => [Post] } }
Skip all months other than January (1):
Post.archive_tree(:months => [1]) #=> { 2010 => { 1 => [Post] },
{ 2011 => { 1 => [Post] } } }
Only sweep January 2010:
Post.archive_tree(:years_and_months => { 2010 => [1] }) #=> { 2010 => { 1 => [Post] } }
Considerations This method has poor performance due to the ‘linear’ way in which the queries are being constructed and executed.
TODO: Optimize the queries.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/archive_tree/core.rb', line 127 def archive_tree( = {}) tree = {} years = [:years_and_months] ? [:years_and_months].keys : nil || [:years] || archived_years.keys || [] years.each do |year| tree[year] = {} months = archived_months(:year => year).keys if [:years_and_months] months.reject! { |m| ![:years_and_months][year].include?(m) } elsif [:months] months.reject! { |m| ![:months].include?(m) } end months.each do |month| tree[year][month] = {} tree[year][month] = archive_node(:year => year, :month => month) end end tree end |
#archived_months(options = {}) ⇒ Object
For a given year, constructs a single-level hash of months using the defined date_field
column.
The returned hash is a key-value-pair representing the number of records for a given month, within a given years. This hash can have string or integer keys, depending on the value of :month_names option, which can be passed in the options hash.
Default behaviors
* By default the months are returned in their integer representation (eg.: 1 represents January)
* The current year is assumed to be the default scope of the query
Options
* :year #=> Integer representing the year to sweep. Defaults to the current year.
* :month_names #=> Null, or absent will result in months represented as integer (default). Also accepts :long
and :short, depending on the desired lenght length for the month name.
Considerations Given the way the queries are currently constructed and executed this method suffers from poor performance.
TODO: Optimize the queries.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/archive_tree/core.rb', line 64 def archived_months( = {}) months = {} month_format = .delete(:month_names) || :int where("EXTRACT(YEAR FROM #{date_field}) = #{[:year] || Time.now.year}"). group("EXTRACT(MONTH FROM #{date_field})").size.each do |month, c| key = case month_format when :long Date::MONTHNAMES[month.to_i] when :short Date::ABBR_MONTHNAMES[month.to_i] else month.to_i end months[key] = c end months end |
#archived_years ⇒ Object
Constructs a single-level hash of years using the defined date_field
column.
The returned hash is a key-value-pair of integers. The key represents the year (in integer) and the value represents the number of records for that year (also in integer).
This method executes a SQL query of type COUNT, grouping the results by year.
Note: the query makes use of the YEAR sql command, which might not be supported by all RDBMs.
Exampe:
Post.years_hash #=> { 2009 => 8, 2010 => 30 }
37 38 39 40 41 42 43 |
# File 'lib/archive_tree/core.rb', line 37 def archived_years years = {} where("#{date_field} IS NOT NULL"). group("EXTRACT(YEAR FROM #{date_field})").size.each { |year, count| years[year.to_i] = count } years end |