Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
status_column and reflection_name methods rely in own instance
  • Loading branch information
Ricard Forniol committed May 31, 2011
1 parent c977f51 commit c385d2f
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 32 deletions.
7 changes: 2 additions & 5 deletions lib/activity_counter/active_record/reflection.rb
Expand Up @@ -13,7 +13,7 @@ def reverseme
end
end
def status_column_name
(is_belongs_to? and (options[:status_field] or :status).to_sym) or reverseme.status_column_name
(belongs_to? and (options[:status_field] or :status).to_sym) or reverseme.status_column_name
end
def load_default_counters
@default_counters = []
Expand All @@ -31,12 +31,9 @@ def load_default_counters
end
end
def has_status_counter?
(is_belongs_to? and options[:counter_cache] and options[:counter_cache].reject{|k,v| k == :default }.keys.count > 1)
(belongs_to? and options[:counter_cache] and options[:counter_cache].reject{|k,v| k == :default }.keys.count > 1)
end
private
def is_belongs_to?
macro == :belongs_to
end
def reverse_class
klass
end
Expand Down
58 changes: 41 additions & 17 deletions lib/activity_counter/model/cached.rb
Expand Up @@ -2,32 +2,43 @@ module ActivityCounter
module Model
module Cached
module ClassMethods

def define_class_accessor(name, default=nil)
unless respond_to?(name)
class_eval <<-MAGIC
@@#{name} = #{default.inspect}
def #{name}=(name)
def self.#{name}=(name)
@@#{name} = name
end
def #{name}
def self.#{name}
@@#{name}
end
MAGIC
end
end

## Add status_update methods and trigger them to their events
def configure_cached_class(reflection)
{
:status_column_name => reflection.status_column_name,
:reflection_name => reflection.name
}.each_pair{ |name,value| define_class_accessor(name, value) }
status_column_name= reflection.status_column_name
reflection_name= reflection.name

send(:include, InstanceMethods)
reflection.load_default_counters
define_status_counters if reflection.has_status_counter?
#define_default_counters
end

alias_method :original_method_missing, :method_missing
def method_missing(name, *args)
default_methods = { :status_column_name => :status, :reflection_name => nil }
if default_methods.keys.include?(name)
define_class_accessor(name, default_methods[name])
send name
else
original_method_missing(name, args)
end
end

private
def define_status_counters
# Custom status based counters
Expand All @@ -38,9 +49,9 @@ def define_status_counters
def define_default_counters(counters)
counters.each do |counter|
case counter
when :total then define_total_counter
when :new_default then define_new_default
when :new_simple then define_new_simple
when :total then define_total_counter
when :new_default then define_new_default
when :new_simple then define_new_simple
end
end
end
Expand Down Expand Up @@ -68,15 +79,18 @@ def decrease_new_on_updated_at_distinct_of_created_at

module InstanceMethods
def status_column_name
self.class.status_column_name
@status_column_name ||= status.status_field
end
def reflection_name
# at this moment only one is expected, is ready to accept more
@reflection_name ||= find_status_reflections.first.name
end
def status
@status ||= Status.new(self, self.class.reflection_name)
@status ||= Status.new(self, reflection_name)
@status = @status.send(:call, self)
@status
end
def after_create_update_default_counter
puts "estatus column: #{status_column_name}"
if self[status_column_name].nil? && !status.default.nil?
self[status_column_name] = status.default
status.should_not_update!
Expand Down Expand Up @@ -111,7 +125,14 @@ def #{name}
super
end
end


private
def find_status_reflections
@status_reflections ||= []
@status_reflections.empty? and self.class.reflections.each_pair{ |name,reflection|
reflection.has_status_counter? and @status_reflections << reflection }
@status_reflections
end
# It represents the "status" column for the current instance
# .status => this name might change
# .list => known statuses list
Expand All @@ -123,19 +144,21 @@ def #{name}
# .after => after update status name
# .cached_class_name => class name of the class containing status (Invitation in this case)
# .cached_relation_name => belongs_to relation name
# .changes => changes if any on the status column
# .changes => changes on the status column
class Status
attr_reader :record, :reflection, :status_field
attr_reader :record, :reflection

def initialize(record, reflection_name)
@counter = {}
@record = record
@reflection = reflection_for(reflection_name)
@owner = @record.send(@reflection.name)
@statuses = @reflection.options[:counter_cache].reject{|status,value| status == :default }
@status_field = @record.status_column_name
@should_update = true
end
def status_field
@status_field ||= reflection_for(record.reflection_name).status_column_name
end
def list
@statuses
end
Expand Down Expand Up @@ -214,6 +237,7 @@ def reflection_for(name)
(reflection.nil? and raise "Reflection #{name} not found for #{record.class.to_s} Class") or reflection
end
end

end
end
end
Expand Down
2 changes: 1 addition & 1 deletion test/dummy/app/models/site.rb
@@ -1,4 +1,4 @@
class Site < ActiveRecord::Base
has_many :users
#has_many :users

end
7 changes: 6 additions & 1 deletion test/dummy/app/models/user.rb
@@ -1,5 +1,10 @@
class User < ActiveRecord::Base
STATUSES = {
:unactive => 0,
:active => 1,
:disabled => 2
}
has_many :events
has_many :invitations, :dependent => :destroy
belongs_to :site, :counter_cache => {:default => true}
#belongs_to :site, :counter_cache => {:default => [:total, {:new => :unactive}]}.merge(STATUSES)
end
5 changes: 5 additions & 0 deletions test/dummy/db/migrate/20110524114256_tables.rb
Expand Up @@ -3,6 +3,7 @@ def self.up
create_table :users, :force => true do |t|
t.string :name
t.string :email
t.string :status
t.timestamps
end
create_table :invitations, :force => true do |t|
Expand All @@ -24,12 +25,16 @@ def self.up
t.string :name
t.integer :count, :default => 0
end
create_table :sites, :force => true do |t|
t.string :user_id
end
end

def self.down
drop_table :counters
drop_table :events
drop_table :invitations
drop_table :users
drop_table :sites
end
end
13 changes: 5 additions & 8 deletions test/unit/event_invitations_test.rb
Expand Up @@ -23,25 +23,22 @@ def setup
assert @event.invitees.respond_to?(:accepted)
assert @event.invitees.respond_to?(:rejected)
end
test "event invitations counter increase on create, and decrease on delete invitation" do
test "event invitations counter increase on create and decrease on delete invitation" do
assert_equal(0, @event.invitees.pending.to_s.count)
assert_equal(@event, @event.invitees.owner)
@event.invitees << @invitation
assert_equal(1, @event.invitees.pending.count)

@invitation.destroy
assert_equal(0, @event.invitees.pending.count(:force => true))
end
test "event invitations counter decrease/increase on update" do
@event.invitees << @invitation
@invitation.reload
assert_equal(1, @event.invitees.pending.count)
@invitation.update_attribute(:estat, Invitation::STATUS[:accepted])
assert_equal([:pending, :accepted], Counter.all.map{|c| c.name.to_sym })
assert_equal(0, @event.invitees.pending.count(:force => true))
assert_equal(1, @event.invitees.accepted.count(:force => true))
assert_equal(:accepted, @invitation.status.current.name)
end
test "event invitations counter decrease on destroy" do
@event.invitees << @invitation
@invitation.reload
@invitation.destroy
assert_equal(0, @event.invitees.pending.count(:force => true))
end
end

0 comments on commit c385d2f

Please sign in to comment.