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_fieldcolumn. -
#archived_years ⇒ Object
Constructs a single-level hash of years using the defined
date_fieldcolumn.
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
- Years (integer)
- Months (integer)
- 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 => => [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}) = #{options[: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 |