Skip to content

Instantly share code, notes, and snippets.

@ml
Created February 9, 2010 14:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ml/299243 to your computer and use it in GitHub Desktop.
Save ml/299243 to your computer and use it in GitHub Desktop.
DataMapper.setup(:default, :adapter => 'mysql', :database => "test", :username => "root")
DataMapper.setup(:dual, :adapter => "dual", :default => repository(:default), :redis => {:db => 1})
class DualAdapter < AbstractAdapter
def create(query)
@default.create query
end
def read(query)
query = simplify(query) if simplify_applies?(query)
@default.read query
end
def simplify(query)
equal_to = query.conditions.operands.select { |o|
o.is_a?(DataMapper::Query::Conditions::EqualToComparison) &&
o.subject.parent_model == User &&
o.subject.child_model == Status
}
equal_to.each { |e| query.conditions.operands.delete e }
raise "dupa" if equal_to.size > 1
equal_to = equal_to.first
child_model = equal_to.subject.child_model
parent_key = equal_to.subject.parent_key.first.name
key = redis_key(child_model, equal_to.value.send(parent_key))
child_ids = @redis.zrevrange(key, query.offset, query.limit - 1) #TODO use either zrevrange or zrange depending on query.order?
query.conditions << DataMapper::Query::Conditions::InclusionComparison.new(Status.properties[:id], child_ids)
query
end
def redis_key(model, key)
#statuses ids are stored in Redis zsets
"#{model.name.split("::").last.downcase.first}:#{key}"
end
def simplify_applies?(query)
query.conditions.operands.any? { |o|
o.is_a?(DataMapper::Query::Conditions::EqualToComparison) &&
o.subject.parent_model == User &&
o.subject.child_model == Status
}
end
def initialize(name, uri_or_options)
super
@default = @options[:default]
@redis = Redis.new(@options[:redis])
end
end
class Status
include ::DataMapper::Resource
def self.default_repository_name; :dual; end
property :id, Serial
property :user_id, Integer
belongs_to :user
end
class User
include DataMapper::Resource
property :id, Serial
property :login, String
has n, :statuses, :repository => Status.default_repository_name, :order => [:id.desc]
end
User.first.statuses(:limit => 5) # superb fast SELECT `id`, `user_id` FROM `statuses` WHERE `id` IN (190, 189, 188, 187, 186) ORDER BY `id` DESC LIMIT 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment