<body>

Caiwangqin's blog

Focus on Web2.0, Business, Architecture, Agile, Technic and beyond…

acts_as_countable

2007年3月28日 星期三

我想找到一个类似acts_as_commentable和acts_as_rateable的plugins,给任何一个object统计阅读次数,结果没有找到。于是开始动手写一个acts_as_countable,由于编写时间较短,该插件虽然实现了counter的功能,但效率低下,而且在page_cache时无法使用,以下是公开的源代码,有需要的朋友可以加以改进。


一、Create Table


CREATE TABLE `counts` (
`id` int(11) NOT NULL auto_increment,
`count` int(11) default ‘1′,
`created_at` datetime NOT NULL,
`countable_id` int(11) NOT NULL default ‘0′,
`countable_type` varchar(15) NOT NULL default ‘’,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;



二、Create plugin


ruby script/generate plugin acts_as_countable



三、Open /vendor/plugins/act_as_countable/lib/act_as_countable.rb and put this code inside:


# ActsAsCountable
module Jesse
module Acts #:nodoc:
module Countable #:nodoc:


def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def acts_as_countable
has_many :counts, :as => :countable, :dependent => :destroy, :o rder => ‘created_at DESC’
include Jesse::Acts::Countable::InstanceMethods
extend Jesse::Acts::Countable::SingletonMethods
end
end
module SingletonMethods
def find_counts_for(obj)
countable = ActiveRecord::Base.send(:class_name_of_active_record_descendant, self).to_s
Count.find(:first,
:conditions => [”countable_id = ? and countable_type = ?”, obj.id, countable])
end
end
module InstanceMethods
def counter
Count.find(:first,
:conditions => [”countable_id = ? and countable_type = ?”, id, self.type.name])
end
# Helper method that defaults the submitted time.
def add_count(count)
counter = Count.find(:first, :conditions => [”countable_id = ? and countable_type = ?”, count.countable_id, self.type.name ])
if counter.nil?
counts << count
else
counter.update_attribute(:count, counter.count + 1)
end
end
end

end
end
end



四、Create /vendor/plugins/act_as_countable/lib/count.rb and put this code inside:


class Count < ActiveRecord::Base
belongs_to :countable, :polymorphic => true


def self.find_counts_for_countable(countable_str, countable_id)
find(:first,
:conditions => [”countable_type = ? and countable_id = ?”, countable_str, countable_id]
)
end

def self.find_countable(countable_str, countable_id)
countable_str.constantize.find(countable_id)
end
end



五、put this code inside our /vendor/plugins/act_as_countable/init.rb


require ‘acts_as_countable’
ActiveRecord::Base.send(:include, Jesse::Acts::Countable)



六、How to Use


1. put acts_as_countable inside model, like acts_as_commentable

2. in view action:

count = Count.new
count.countable_id = @obj.id
@obj.add_count(count)



Resources:



标签:

posted by Caiwangqin, 上午7:42

<< 主页