diff --git a/README.md b/README.md index 8a56342..353ff82 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Birthday +# Birthday [![Build Status](https://secure.travis-ci.org/railslove/birthday.png)](http://travis-ci.org/railslove/birthday) This is a small gem that hooks into ActiveRecord and allows to tag a database field (date or datetime) as birthday, allowing to find birthdays with ease. @@ -12,11 +12,23 @@ After the gem has been properly tested, it will be released on RubyGems, and wil Read [a blog post about the gem](http://blog.railslove.com/2011/10/17/birthday-gem-easy-anniversaries-handling-ruby/) at Railslove blog to get a comprehensive guide to usage of this gem. +You can create your own adapters for the ORM adapters we're not supporting yet by writing a class with a class method `scope_hash`, which will return a hash normally used in `active_record` scopes. + + class SqliteAdapter + def self.scope_hash(field, date_start, date_end) + # do some magic and return scope hash you can use + # field is the field used in the database + # date_start and date_end can be anything that responds to .to_date method + end + end + +and then create an initializer file with this content, referencing the class you wrote: + + ::Railslove::Acts::Birthday::BaseAdapter.birthday_adapter = SqliteAdapter + ### To do -* Test PostgreSQL * kick class_eval? -* make tests more "aware" of environment ## Note on Patches/Pull Requests @@ -55,4 +67,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +THE SOFTWARE. diff --git a/birthday.gemspec b/birthday.gemspec index 8397a7b..97e6163 100644 --- a/birthday.gemspec +++ b/birthday.gemspec @@ -22,6 +22,7 @@ Gem::Specification.new do |s| s.add_development_dependency "rake" s.add_development_dependency "rspec" s.add_development_dependency "mysql2", '0.3.6' + s.add_development_dependency "mysql" s.add_development_dependency "delorean" s.add_development_dependency "pg" s.add_runtime_dependency "activerecord" diff --git a/lib/birthday.rb b/lib/birthday.rb index 8b595d7..1158296 100644 --- a/lib/birthday.rb +++ b/lib/birthday.rb @@ -4,4 +4,5 @@ require "railslove/acts/birthday/adapters/postgresql_adapter" require "railslove/acts/birthday/version" -ActiveRecord::Base.send :include, ::Railslove::Acts::Birthday \ No newline at end of file +ActiveRecord::Base.send :include, ::Railslove::Acts::Birthday +::Railslove::Acts::Birthday::BaseAdapter.birthday_adapter = "Railslove::Acts::Birthday::#{ActiveRecord::Base.connection.class.name.split("::").last}".constantize diff --git a/lib/railslove/acts/birthday/adapters/mysql2_adapter.rb b/lib/railslove/acts/birthday/adapters/mysql2_adapter.rb index 4513b56..2b1da7f 100644 --- a/lib/railslove/acts/birthday/adapters/mysql2_adapter.rb +++ b/lib/railslove/acts/birthday/adapters/mysql2_adapter.rb @@ -2,10 +2,8 @@ module Railslove module Acts #:nodoc: module Birthday #:nodoc: - module Adapters - class Mysql2Adapter < MysqlAdapter - end + class Mysql2Adapter < MysqlAdapter end end end -end \ No newline at end of file +end diff --git a/lib/railslove/acts/birthday/adapters/mysql_adapter.rb b/lib/railslove/acts/birthday/adapters/mysql_adapter.rb index 98fe7fa..4e97b66 100644 --- a/lib/railslove/acts/birthday/adapters/mysql_adapter.rb +++ b/lib/railslove/acts/birthday/adapters/mysql_adapter.rb @@ -2,27 +2,25 @@ module Railslove module Acts #:nodoc: module Birthday #:nodoc: - module Adapters - class MysqlAdapter - def self.scope_hash(field, date_start, date_end) - date_start = date_start.to_date - if ((date_end.respond_to?(:empty?) && date_end.empty?) || !date_end) - where_sql = "DATE_FORMAT(`#{field}`, '%m%d') = \"#{date_start.strftime('%m%d')}\"" + class MysqlAdapter < BaseAdapter + def self.scope_hash(field, date_start, date_end) + date_start = date_start.to_date + if ((date_end.respond_to?(:empty?) && date_end.empty?) || !date_end) + where_sql = "DATE_FORMAT(`#{field}`, '%m%d') = \"#{date_start.strftime('%m%d')}\"" + else + date_end = date_end.to_date + if date_end.strftime('%m%d') < date_start.strftime('%m%d') + where_sql = "(DATE_FORMAT(`#{field}`, '%m%d') >= \"0101\"" + where_sql << " AND DATE_FORMAT(`#{field}`, '%m%d') <= \"#{date_start.strftime('%m%d')}\")" + where_sql << " OR (DATE_FORMAT(`#{field}`, '%m%d') >= \"#{date_end.strftime('%m%d')}\"" + where_sql << " AND DATE_FORMAT(`#{field}`, '%m%d') <= \"1231\")" else - date_end = date_end.to_date - if date_end.strftime('%m%d') < date_start.strftime('%m%d') - where_sql = "(DATE_FORMAT(`#{field}`, '%m%d') >= \"0101\"" - where_sql << " AND DATE_FORMAT(`#{field}`, '%m%d') <= \"#{date_start.strftime('%m%d')}\")" - where_sql << " OR (DATE_FORMAT(`#{field}`, '%m%d') >= \"#{date_end.strftime('%m%d')}\"" - where_sql << " AND DATE_FORMAT(`#{field}`, '%m%d') <= \"1231\")" - else - where_sql = "DATE_FORMAT(`#{field}`, '%m%d') >= \"#{date_start.strftime('%m%d')}\" AND DATE_FORMAT(`#{field}`, '%m%d') <= \"#{date_end.strftime('%m%d')}\"" - end + where_sql = "DATE_FORMAT(`#{field}`, '%m%d') >= \"#{date_start.strftime('%m%d')}\" AND DATE_FORMAT(`#{field}`, '%m%d') <= \"#{date_end.strftime('%m%d')}\"" end - { :conditions => where_sql } end + { :conditions => where_sql } end end end end -end \ No newline at end of file +end diff --git a/lib/railslove/acts/birthday/adapters/postgresql_adapter.rb b/lib/railslove/acts/birthday/adapters/postgresql_adapter.rb index 582a626..cf40566 100644 --- a/lib/railslove/acts/birthday/adapters/postgresql_adapter.rb +++ b/lib/railslove/acts/birthday/adapters/postgresql_adapter.rb @@ -2,25 +2,23 @@ module Railslove module Acts #:nodoc: module Birthday #:nodoc: - module Adapters - class PostgreSQLAdapter - def self.scope_hash(field, date_start, date_end) - date_start = date_start.to_date - if ((date_end.respond_to?(:empty?) && date_end.empty?) || !date_end) - where_sql = "to_char(\"#{field}\", 'MMDD') = '#{date_start.strftime('%m%d')}'" + class PostgreSQLAdapter < BaseAdapter + def self.scope_hash(field, date_start, date_end) + date_start = date_start.to_date + if ((date_end.respond_to?(:empty?) && date_end.empty?) || !date_end) + where_sql = "to_char(\"#{field}\", 'MMDD') = '#{date_start.strftime('%m%d')}'" + else + date_end = date_end.to_date + if date_end.strftime('%m%d') < date_start.strftime('%m%d') + where_sql = "to_char(\"#{field}\", 'MMDD') BETWEEN '0101' AND '#{date_end.strftime('%m%d')}'" + where_sql << "OR to_char(\"#{field}\", 'MMDD') BETWEEN '#{date_start.strftime('%m%d')}' AND '1231'" else - date_end = date_end.to_date - if date_end.strftime('%m%d') < date_start.strftime('%m%d') - where_sql = "to_char(\"#{field}\", 'MMDD') BETWEEN '0101' AND '#{date_end.strftime('%m%d')}'" - where_sql << "OR to_char(\"#{field}\", 'MMDD') BETWEEN '#{date_start.strftime('%m%d')}' AND '1231'" - else - where_sql = "to_char(\"#{field}\", 'MMDD') BETWEEN '#{date_start.strftime('%m%d')}' AND '#{date_end.strftime('%m%d')}'" - end + where_sql = "to_char(\"#{field}\", 'MMDD') BETWEEN '#{date_start.strftime('%m%d')}' AND '#{date_end.strftime('%m%d')}'" end - { :conditions => where_sql } end + { :conditions => where_sql } end end end end -end \ No newline at end of file +end diff --git a/lib/railslove/acts/birthday/birthday.rb b/lib/railslove/acts/birthday/birthday.rb index 92eb98a..5b70497 100644 --- a/lib/railslove/acts/birthday/birthday.rb +++ b/lib/railslove/acts/birthday/birthday.rb @@ -2,22 +2,24 @@ module Railslove module Acts #:nodoc: module Birthday #:nodoc: + + class BaseAdapter + def self.birthday_adapter + @@birthday_adapter + end + + def self.birthday_adapter=(value) + @@birthday_adapter = value + end + end + def self.included(base) base.extend ClassMethods end module ClassMethods - # Expects an array of date or datetime fields. If the first object - # in passed array is a class with a class method `scope_hash` - # class SqliteAdapter - # def self.scope_hash(field, date_start, date_end) - # # do some magic and return scope hash you can use - # end - # end - # - # then this class is used as an adapter to create its scope for birthday finders. - # + # Expects an array of date or datetime fields. # An example code in basic model would be: # # class Person < ActiveRecord::Base @@ -34,15 +36,7 @@ module ClassMethods # person.created_at_age => 2 # person.created_at_today? => true/false def acts_as_birthday(*args) - args = args.to_a.flatten.compact - klass = args.shift if args.first.class == Class - if klass && klass.class == Class - @@_birthday_backend = klass - else - @@_birthday_backend ||= "Railslove::Acts::Birthday::Adapters::#{ActiveRecord::Base.connection.class.name.split("::").last}".constantize - end - - birthday_fields = args.map(&:to_sym) + birthday_fields = args.to_a.flatten.compact.map(&:to_sym) scope_method = ActiveRecord::VERSION::MAJOR == 3 ? 'scope' : 'named_scope' @@ -50,7 +44,7 @@ def acts_as_birthday(*args) self.send(scope_method, :"find_#{field.to_s.pluralize}_for", lambda{ |*scope_args| raise ArgumentError if scope_args.empty? or scope_args.size > 2 date_start, date_end = *scope_args - @@_birthday_backend.scope_hash(field, date_start, date_end) + ::Railslove::Acts::Birthday::BaseAdapter.birthday_adapter.scope_hash(field, date_start, date_end) }) class_eval %{ @@ -73,4 +67,4 @@ def #{field}_today? end end -end \ No newline at end of file +end diff --git a/lib/railslove/acts/birthday/version.rb b/lib/railslove/acts/birthday/version.rb index e95c850..62c329c 100644 --- a/lib/railslove/acts/birthday/version.rb +++ b/lib/railslove/acts/birthday/version.rb @@ -1,7 +1,7 @@ module Railslove module Acts module Birthday - VERSION = "0.0.1" + VERSION = "0.0.2" end end end diff --git a/spec/database.yml b/spec/database.yml index 52ef2b7..4d378b6 100644 --- a/spec/database.yml +++ b/spec/database.yml @@ -1,5 +1,5 @@ mysql: - adapter: mysql2 + adapter: mysql database: birthday_plugin_test username: encoding: utf8 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e8dee75..432dc1b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,16 +1,20 @@ $:.unshift(File.dirname(__FILE__)) $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) -require 'test/unit' require 'rubygems' require 'rspec' +require 'delorean' +require 'yaml' -def fixture(file_name) - File.read(fixture_path(file_name)) -end - -def fixture_path(file_name) - File.expand_path(File.dirname(__FILE__)) + "/fixtures/#{file_name}" +config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml')) +adapter = ENV['DB'] || 'mysql' +case adapter +when 'mysql' + require 'mysql2' +when 'postgres' + require 'pg' +else + require adapter end if ENV['RAILS'].nil? @@ -20,31 +24,18 @@ def fixture_path(file_name) # load activerecord and activesupport and plugin manually require 'active_record' require 'active_support' + ActiveRecord::Base.configurations.update config + ActiveRecord::Base.establish_connection(adapter) + ActiveRecord::Base.default_timezone = :utc $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib') - Dir["#{$LOAD_PATH.last}/**/*.rb"].each do |path| + Dir["#{$LOAD_PATH.last}/**/*.rb"].each do |path| require path[$LOAD_PATH.last.size + 1..-1] end require "railslove/acts/birthday/birthday" end -require 'delorean' -require 'yaml' -config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml')) -adapter = ENV['DB'] || 'mysql' -case adapter -when 'mysql' - require 'mysql2' -when 'postgres' - require 'pg' -else - require adapter -end - -ActiveRecord::Base.configurations.update config -ActiveRecord::Base.establish_connection(adapter) -ActiveRecord::Base.default_timezone = :utc load(File.dirname(__FILE__) + "/schema.rb") RSpec.configure do |config| config.include Delorean -end \ No newline at end of file +end