Skip to content

Instantly share code, notes, and snippets.

@jhjguxin
Created September 11, 2012 09:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jhjguxin/3697325 to your computer and use it in GitHub Desktop.
Save jhjguxin/3697325 to your computer and use it in GitHub Desktop.
try class eval on rails model
#(Ruby - Using class_eval to define methods)[http://stackoverflow.com/questions/9561072/ruby-using-class-eval-to-define-methods]
class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s # make sure it's a string
attr_reader attr_name
attr_reader attr_name+"_history"
class_eval %Q"
def #{attr_name}=(value)
if !defined? @#{attr_name}_history
@#{attr_name}_history = [@#{attr_name}]
end
@#{attr_name} = value
@#{attr_name}_history << value
end
"
end
end
class Foo
attr_accessor_with_history :bar
end
class Foo2
attr_accessor_with_history :bar
def initialize()
@bar = 'init'
end
end
f = Foo.new
f.bar = 1
f.bar = nil
f.bar = '2'
f.bar = [1,nil,'2',:three]
f.bar = :three
puts "First bar:", f.bar.inspect, f.bar_history.inspect
puts "Correct?", f.bar_history == [f.class.new.bar, 1, nil, '2', [1,nil,'2',:three], :three] ? "yes" : "no"
old_bar_history = f.bar_history.inspect
f2 = Foo2.new
f2.bar = 'baz'
f2.bar = f2
puts "\nSecond bar:", f2.bar.inspect, f2.bar_history.inspect
puts "Correct?", f2.bar_history == [f2.class.new.bar, 'baz', f2] ? "yes" : "no"
puts "\nIs the old f.bar intact?", f.bar_history.inspect == old_bar_history ? "yes" : "no"
# encoding: utf-8
module SphinxIndexable
module Question
def self.included(base)
base.class_eval <<-"end_eval"
define_index do
indexes title
indexes content
#indexes identity_taggings.tag(:name), as: :identity_tags
#indexes timeline_taggings.tag(:name), as: :timeline_tags
#indexes category_taggings.tag(:name), :as => :category_tags
indexes tag_taggings.tag(:name), :as => :tag_tags
#has identity_taggings.tag(:id), as: :identity_tags
#has timeline_taggings.tag(:id), as: :timeline_tags
where "deleted_at is null"
#声明使用实时索引
set_property :delta => true
end
end_eval
end
end
module Knowledge
def self.included(base)
base.class_eval <<-"end_eval"
define_index do
indexes title
indexes summary
indexes content
#indexes identity_taggings.tag(:name), as: :identity_tags
#indexes timeline_taggings.tag(:name), as: :timeline_tags
#indexes category_taggings.tag(:name), :as => :category_tags
indexes tag_taggings.tag(:name), :as => :tag_tags
#has identity_taggings.tag(:id), as: :identity_tags
#has timeline_taggings.tag(:id), as: :timeline_tags
where "deleted_at is null"
#声明使用实时索引
set_property :delta => true
end
end_eval
end
end
module Profile
def self.included(base)
base.class_eval <<-"end_eval"
define_index do
indexes nickname
indexes label
indexes real_name
indexes user.email
#声明使用实时索引
set_property :delta => true
end
end_eval
end
end
module Group
def self.included(base)
base.class_eval <<-"end_eval"
define_index do
indexes name
where "deleted_at is null"
#声明使用实时索引
set_property :delta => true
end
end_eval
end
end
module Goods
def self.included(base)
base.class_eval <<-"end_eval"
define_index do
indexes goods_name
indexes goods_brief
indexes goods_desc
where "is_on_sale is true"
#声明使用实时索引
#set_property :delta => true
end
end_eval
end
end
end
=begin
#how to call
class Group < ActiveRecord::Base
#establish_connection :group_development
establish_connection "group_#{Rails.env}"
include SphinxIndexable::Group
end
=end
#[Callbacks相关的源码在callbacks.rb文件里](http://rails-everyday.group.iteye.com/group/wiki/1145)
module ActiveRecord
module Callbacks
CALLBACKS = %w(
after_find after_initialize before_save after_save before_create after_create before_update after_update before_validation
after_validation before_validation_on_create after_validation_on_create before_validation_on_update
after_validation_on_update before_destroy after_destroy
)
def self.included(base) #:nodoc:
base.extend(ClassMethods)
base.class_eval do
class << self
include Observable
alias_method_chain :instantiate, :callbacks
end
[:initialize, :create_or_update, :valid?, :create, :update, :destroy].each do |method|
alias_method_chain method, :callbacks
end
end
CALLBACKS.each do |method|
base.class_eval <<-"end_eval"
def self.#{method}(*callbacks, &block)
callbacks << block if block_given?
write_inheritable_array(#{method.to_sym.inspect}, callbacks)
end
end_eval
end
end
module ClassMethods #:nodoc:
def instantiate_with_callbacks(record)
object = instantiate_without_callbacks(record)
if object.respond_to_without_attributes?(:after_find)
object.send(:callback, :after_find)
end
if object.respond_to_without_attributes?(:after_initialize)
object.send(:callback, :after_initialize)
end
object
end
end
def create_or_update_with_callbacks #:nodoc:
return false if callback(:before_save) == false
result = create_or_update_without_callbacks
callback(:after_save)
result
end
def create_with_callbacks #:nodoc:
return false if callback(:before_create) == false
result = create_without_callbacks
callback(:after_create)
result
end
def update_with_callbacks #:nodoc:
return false if callback(:before_update) == false
result = update_without_callbacks
callback(:after_update)
result
end
def valid_with_callbacks? #:nodoc:
return false if callback(:before_validation) == false
if new_record? then result = callback(:before_validation_on_create) else result = callback(:before_validation_on_update) end
return false if result == false
result = valid_without_callbacks?
callback(:after_validation)
if new_record? then callback(:after_validation_on_create) else callback(:after_validation_on_update) end
return result
end
def destroy_with_callbacks #:nodoc:
return false if callback(:before_destroy) == false
result = destroy_without_callbacks
callback(:after_destroy)
result
end
private
def callback(method)
notify(method)
callbacks_for(method).each do |callback|
result = case callback
when Symbol
self.send(callback)
when String
eval(callback, binding)
when Proc, Method
callback.call(self)
else
if callback.respond_to?(method)
callback.send(method, self)
else
raise ActiveRecordError, "Callbacks must be a symbol denoting the method to call, a string to be evaluated, a block to be invoked, or an object responding to the callback method."
end
end
return false if result == false
end
result = send(method) if respond_to_without_attributes?(method)
return result
end
def callbacks_for(method)
self.class.read_inheritable_attribute(method.to_sym) or []
end
end
end
class Knowledge User < ActiveRecord::Base
class << self
extend ThinkingSphinx::Index::ClassMethods
end
self.class_eval do
extend ThinkingSphinx::Index::ClassMethods
end
# ...
end
class Index
def knowledge_index
"asdfasdfa"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment