Skip to content

Commit

Permalink
JSON support
Browse files Browse the repository at this point in the history
  • Loading branch information
bpo committed Apr 26, 2010
1 parent 9049109 commit b9e3185
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 24 deletions.
3 changes: 2 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ source :gemcutter

gem "dm-core", ">= 0.10.2"
gem "dm-validations", ">= 0.10.2"
gem "dm-types", ">= 0.10.2"
gem "redis", ">= 0.1.2"
gem "jeweler", ">= 1.4.0"
gem "rspec", "~> 1.3.0"
gem "rake", ">= 0.8.7"
gem "rake", ">= 0.8.7"
6 changes: 3 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ begin
gemspec.homepage = HOMEPAGE
gemspec.description = SUMMARY
gemspec.authors = AUTHORS
gemspec.add_dependency "dm-core", "0.10.0"
gemspec.add_dependency "ezmobius-redis"
gemspec.add_dependency "dm-core", ">= 0.10.2"
gemspec.add_dependency "redis"
gemspec.files = %w(MIT-LICENSE README.textile Rakefile) + Dir.glob("{lib,spec}/**/*")
gemspec.has_rdoc = true
gemspec.extra_rdoc_files = ["MIT-LICENSE"]
Expand All @@ -43,4 +43,4 @@ desc "Run specs"
Spec::Rake::SpecTask.new do |t|
t.spec_files = FileList['spec/**/*_spec.rb']
t.spec_opts = %w(-fs --color)
end
end
15 changes: 10 additions & 5 deletions dm-redis-adapter.gemspec
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# Generated by jeweler
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
# -*- encoding: utf-8 -*-

Gem::Specification.new do |s|
s.name = %q{dm-redis-adapter}
s.version = "0.0.9"
s.version = "0.0.6"

s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Dan Herrera"]
s.date = %q{2010-03-03}
s.date = %q{2010-04-26}
s.description = %q{DataMapper adapter for the Redis key-value database}
s.email = %q{whoahbot@gmail.com}
s.extra_rdoc_files = [
Expand All @@ -18,22 +21,23 @@ Gem::Specification.new do |s|
"Rakefile",
"lib/dm_redis.rb",
"spec/dm_redis_spec.rb",
"spec/dm_redis_validations_spec.rb",
"spec/spec_helper.rb"
]
s.has_rdoc = true
s.homepage = %q{http://github.com/whoahbot/dm-redis-adapter}
s.rdoc_options = ["--charset=UTF-8"]
s.require_paths = ["lib"]
s.rubygems_version = %q{1.3.1}
s.rubygems_version = %q{1.3.6}
s.summary = %q{DataMapper adapter for the Redis key-value database}
s.test_files = [
"spec/dm_redis_spec.rb",
"spec/dm_redis_validations_spec.rb",
"spec/spec_helper.rb"
]

if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 2
s.specification_version = 3

if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<dm-core>, [">= 0.10.2"])
Expand All @@ -47,3 +51,4 @@ Gem::Specification.new do |s|
s.add_dependency(%q<redis>, [">= 0"])
end
end

38 changes: 25 additions & 13 deletions lib/dm_redis.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class RedisAdapter < AbstractAdapter
def create(resources)
resources.each do |resource|
initialize_serial(resource, @redis.incr("#{resource.model.to_s.downcase}:#{redis_key_for(resource.model)}:serial"))
@redis.set_add(key_set_for(resource.model), resource.key.join)
@redis.sadd(key_set_for(resource.model), resource.key.join)
end
update_attributes(resources)
end
Expand All @@ -38,10 +38,18 @@ def read(query)
records = records_for(query).each do |record|
query.fields.each do |property|
next if query.model.key.include?(property)
record[property.name.to_s] = property.typecast(@redis["#{query.model.to_s.downcase}:#{record[redis_key_for(query.model)]}:#{property.name}"])

# Integers are stored as Strings in Redis. If there's a
# string coming out that should be an integer, convert it
# now. All other typecasting is handled by datamapper
# separately.
if property.primitive == Integer
record[property.name.to_s] = property.typecast(@redis["#{query.model.to_s.downcase}:#{record[redis_key_for(query.model)]}:#{property.name}"])
else
record[property.name.to_s] = @redis["#{query.model.to_s.downcase}:#{record[redis_key_for(query.model)]}:#{property.name}"]
end
end
end

records = query.match_records(records)
records = query.sort_records(records)
records
Expand Down Expand Up @@ -81,11 +89,11 @@ def update(attributes, collection)
def delete(collection)
records_for(collection.query).each do |record|
collection.query.model.properties.each do |p|
@redis.delete("#{collection.query.model.to_s.downcase}:#{record[redis_key_for(collection.query.model)]}:#{p.name}")
@redis.del("#{collection.query.model.to_s.downcase}:#{record[redis_key_for(collection.query.model)]}:#{p.name}")
end
@redis.set_delete(key_set_for(collection.query.model), record[redis_key_for(collection.query.model)])
@redis.srem(key_set_for(collection.query.model), record[redis_key_for(collection.query.model)])
collection.query.model.properties.select {|p| p.index}.each do |p|
@redis.set_delete("#{collection.query.model.to_s.downcase}:#{p.name}:#{encode(record[p.name])}", record[redis_key_for(collection.query.model)])
@redis.srem("#{collection.query.model.to_s.downcase}:#{p.name}:#{encode(record[p.name])}", record[redis_key_for(collection.query.model)])
end
end
end
Expand All @@ -101,13 +109,17 @@ def delete(collection)
# @api private
def update_attributes(resources)
resources.each do |resource|
model = resource.model
attributes = resource.dirty_attributes

resource.model.properties.select {|p| p.index}.each do |property|
@redis.set_add("#{resource.model.to_s.downcase}:#{property.name}:#{encode(resource[property.name.to_s])}", resource.key)
@redis.sadd("#{resource.model.to_s.downcase}:#{property.name}:#{encode(resource[property.name.to_s])}", resource.key)
end

resource.attributes(:field).each do |property, value|
next if resource.key.include?(property)
@redis["#{resource.model.to_s.downcase}:#{resource.key.join}:#{property}"] = value unless value.nil?
model.properties(self.name).each do |property|
next unless attributes.key?(property)
value = attributes[property]
@redis["#{resource.model.to_s.downcase}:#{resource.key.join}:#{property.name}"] = value unless value.nil?
end
end
end
Expand All @@ -127,7 +139,7 @@ def records_for(query)

query.conditions.operands.select {|o| o.is_a?(DataMapper::Query::Conditions::EqualToComparison)}.each do |o|
if query.model.key.include?(o.subject)
if @redis.set_member?(key_set_for(query.model), o.value)
if @redis.sismember(key_set_for(query.model), o.value)
keys << {"#{redis_key_for(query.model)}" => o.value}
end
end
Expand All @@ -144,7 +156,7 @@ def records_for(query)

# Keys are empty, fall back and load all the values for this model
if keys.empty?
@redis.set_members(key_set_for(query.model)).each do |val|
@redis.smembers(key_set_for(query.model)).each do |val|
keys << {"#{redis_key_for(query.model)}" => val.to_i}
end
end
Expand Down Expand Up @@ -183,7 +195,7 @@ def key_set_for(model)
# Array of id's of all members matching the query
# @api private
def find_matches(query, operand)
@redis.set_members("#{query.model.to_s.downcase}:#{operand.subject.name}:#{encode(operand.value)}")
@redis.smembers("#{query.model.to_s.downcase}:#{operand.subject.name}:#{encode(operand.value)}")
end

##
Expand Down
2 changes: 1 addition & 1 deletion spec/dm_redis_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

after(:all) do
redis = Redis.new(:db => 15)
redis.flush_db
redis.flushdb
end

it_should_behave_like 'An Adapter'
Expand Down
30 changes: 29 additions & 1 deletion spec/dm_redis_validations_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require File.expand_path("../spec_helper", __FILE__)
require 'redis'
require 'rubygems'
require 'dm-validations'
require 'dm-types'
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib/dm_redis.rb'))

describe DataMapper::Adapters::RedisAdapter do
Expand All @@ -24,8 +26,34 @@ class Crumblecake
Crumblecake.new(:flavor => "snozzbler").valid?.should be_false
end

describe "json support" do
before(:all) do
class Host
include DataMapper::Resource

property :id, Serial
property :name, String
property :env, DataMapper::Types::Json, :default => lambda { {} }
end
end

it "should be able to store json blocks" do
h = Host.create( :name => "new_vm", :env => {"foo" => "bar"} )

h.reload
h.env["foo"].should == "bar"
end

it "should be able to update json blocks" do
h = Host.create( :name => "new_vm" )
h.env = h.env.merge "baz" => "bof"
h.save
h.reload.env["baz"].should == "bof"
end
end

after(:all) do
redis = Redis.new(:db => 15)
redis.flush_db
redis.flushdb
end
end

0 comments on commit b9e3185

Please sign in to comment.