Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added support for Ruby 1.9.1 and some performance improvements.

Performance improvements center around invocations to methods.
Document creation was previously invoking
send("#{key}=".to_sym, val) if methods.include? "#{key}="
as this allowed any hash to be passed to the document initializer.
It turns out that removing the methods.include? call speeds document creation
up by an order of magnitude. This is noticeable in real world code when
retrieving large numbers of objects from CouchDB.
  • Loading branch information...
commit a74db3dc9f0434be69de64994387df1e0f9dd5d9 1 parent bce16e6
@paulcarey authored
View
2  lib/relaxdb.rb
@@ -6,7 +6,7 @@
require 'cgi'
require 'net/http'
require 'logger'
-require 'parsedate'
+require 'parsedate' if RUBY_VERSION.to_f < 1.9
require 'pp'
require 'tempfile'
View
4 lib/relaxdb/all_delegator.rb
@@ -23,6 +23,10 @@ def __getobj__
@ids
end
+ def __setobj__ obj
+ # Intentionally empty
+ end
+
def load
__getobj__
@objs = RelaxDB.load! @ids
View
40 lib/relaxdb/document.rb
@@ -42,7 +42,7 @@ def self.property(prop, opts={})
end
if opts[:default]
- define_method("set_default_#{prop}") do
+ define_method("__set_default_#{prop}__") do
default = opts[:default]
default = default.is_a?(Proc) ? default.call : default
instance_variable_set("@#{prop}".to_sym, default)
@@ -72,11 +72,15 @@ def self.create_validator(att, v)
v.arity == 1 ?
define_method(method_name) { |att_val| v.call(att_val) } :
define_method(method_name) { |att_val| v.call(att_val, self) }
- elsif instance_methods.include? "validator_#{v}"
- define_method(method_name) { |att_val| send("validator_#{v}", att_val, self) }
else
- define_method(method_name) { |att_val| send(v, att_val) }
- end
+ v_meths = instance_methods.select { |m| m =~ /validator_/ }
+ v_meths.map! { |m| m.to_sym } if RUBY_VERSION.to_f < 1.9
+ if v_meths.include? "validator_#{v}".to_sym
+ define_method(method_name) { |att_val| send("validator_#{v}", att_val, self) }
+ else
+ define_method(method_name) { |att_val| send(v, att_val) }
+ end
+ end
end
def self.create_validation_msg(att, validation_msg)
@@ -85,7 +89,7 @@ def self.create_validation_msg(att, validation_msg)
define_method("#{att}_validation_msg") { |att_val| validation_msg.call(att_val) } :
define_method("#{att}_validation_msg") { |att_val| validation_msg.call(att_val, self) }
else
- define_method("#{att}_validation_msg") { validation_msg }
+ define_method("#{att}_validation_msg") { |att_val| validation_msg }
end
end
@@ -125,12 +129,14 @@ def initialize(hash={})
@errors = Errors.new
@save_list = []
@validation_skip_list = []
-
+
# Set default properties if this object isn't being loaded from CouchDB
unless hash["_rev"]
+ default_methods = methods.select { |m| m =~ /__set_default/ }
+ default_methods.map! { |m| m.to_sym } if RUBY_VERSION.to_f < 1.9
properties.each do |prop|
- if methods.include?("set_default_#{prop}")
- send("set_default_#{prop}")
+ if default_methods.include? "__set_default_#{prop}__".to_sym
+ send("__set_default_#{prop}__")
end
end
end
@@ -149,10 +155,7 @@ def set_attributes(data)
val = Time.parse(val).utc rescue val
end
- # Ignore param keys that don't have a corresponding writer
- # This allows us to comfortably accept a hash containing superflous data
- # such as a params hash in a controller
- send("#{key}=".to_sym, val) if methods.include? "#{key}="
+ send("#{key}=".to_sym, val)
end
end
@@ -262,10 +265,12 @@ def validates?
att_names = props + rels
att_vals = prop_vals + rel_vals
- total_success = true
+ total_success = true
+ validate_methods = methods.select { |m| m =~ /validate_/ }
+ validate_methods.map! { |m| m.to_sym } if RUBY_VERSION.to_f < 1.9
att_names.each_index do |i|
att_name, att_val = att_names[i], att_vals[i]
- if methods.include? "validate_#{att_name}"
+ if validate_methods.include? "validate_#{att_name}".to_sym
total_success &= validate_att(att_name, att_val)
end
end
@@ -283,10 +288,13 @@ def validate_att(att_name, att_val)
end
unless success
- if methods.include? "#{att_name}_validation_msg"
+ v_msg_meths = methods.select { |m | m =~ /_validation_msg/ }
+ v_msg_meths.map! { |m| m.to_sym } if RUBY_VERSION.to_f < 1.9
+ if v_msg_meths.include? "#{att_name}_validation_msg".to_sym
begin
@errors[att_name] = send("#{att_name}_validation_msg", att_val)
rescue => e
+ puts "#{e.backtrace[0, 5].join("\n")}"
RelaxDB.logger.warn "Validation_msg for #{att_name} with #{att_val} raised #{e}"
@errors[att_name] = "validation_msg_exception:invalid:#{att_val}"
end
View
2  lib/relaxdb/query.rb
@@ -67,7 +67,7 @@ def merge(paginate_params)
paginate_params.instance_variables.each do |pp|
val = paginate_params.instance_variable_get(pp)
method_name = pp[1, pp.length]
- send(method_name, val) if methods.include? method_name
+ send(method_name, val) if @@params.include? method_name
end
end
View
2  lib/relaxdb/view_object.rb
@@ -7,7 +7,7 @@ def initialize(hash)
hash.each do |k, v|
if k.to_s =~ /_at$/
- v = Time.local(*ParseDate.parsedate(v)) rescue v
+ v = Time.parse(v).utc rescue v
end
instance_variable_set("@#{k}", v)
View
24 spec/belongs_to_spec.rb
@@ -71,24 +71,18 @@
end
it "may be used reciprocally" do
- C1 = Class.new(RelaxDB::Document) do
- belongs_to :c2
- end
- C2 = Class.new(RelaxDB::Document) do
- belongs_to :c1
- end
- i1, i2 = C1.new, C2.new
+ fb, bf = FooBar.new, BarFoo.new
- i1.c2 = i2
- i1.save!
- i2.c1 = i1
- i2.save!
+ fb.bf = bf
+ fb.save!
+ bf.fb = fb
+ bf.save!
- i1 = RelaxDB.load i1._id
- i1.c2.should == i2
+ fb = RelaxDB.load fb._id
+ fb.bf.should == bf
- i2 = RelaxDB.load i2._id
- i2.c1.should == i1
+ bf = RelaxDB.load bf._id
+ bf.fb.should == fb
end
describe "validator" do
View
8 spec/callbacks_spec.rb
@@ -26,14 +26,14 @@
it "should prevent the object from being saved if it returns false" do
c = Class.new(RelaxDB::Document) do
- before_save lambda { false }
+ before_save lambda { |o| false }
end
c.new.save.should == false
end
it "should add a description to errors when false is returned" do
c = Class.new(RelaxDB::Document) do
- before_save lambda { false }
+ before_save lambda { |o| false }
end
x = c.new
x.save
@@ -42,14 +42,14 @@
it "should not prevent the object from being saved if it returns nil" do
c = Class.new(RelaxDB::Document) do
- before_save lambda { nil }
+ before_save lambda { |o| nil }
end
c.new.save!
end
it "may be a proc" do
c = Class.new(RelaxDB::Document) do
- before_save lambda { false }
+ before_save lambda { |o| false }
end
c.new.save.should == false
end
View
8 spec/document_spec.rb
@@ -25,10 +25,10 @@
p.viewed_at.should be_close(now, 1)
end
- it "will silently ignore parameters that don't specify class attributes" do
- # Consider this a feature or bug. It allows an object containing both request params
- # and superflous data to be passed directly to a constructor.
- Post.new(:foo => "").save
+ it "will fail on parameters that don't specify class attributes" do
+ lambda {
+ Post.new :foo => ""
+ }.should raise_error
end
it "should create a document with a non conflicing state" do
View
20 spec/has_many_spec.rb
@@ -14,12 +14,12 @@
it "should infer the class name from the relationship if not supplied" do
view = mock(:view).as_null_object
RelaxDB::ViewCreator.should_receive(:has_n).with(
- "", # client_class
+ "MochaN", # client_class
:foo_bars, # relationship
"FooBar", # target_class
- "" # relationship_to_client
+ "mocha_n" # relationship_to_client
).and_return view
- klass = Class.new(RelaxDB::Document) do
+ class ::MochaN < RelaxDB::Document
has_many :foo_bars
end
end
@@ -27,12 +27,12 @@
it "should use the class name if supplied" do
view = mock(:view).as_null_object
RelaxDB::ViewCreator.should_receive(:has_n).with(
- "", # client_class
- :foo_bars, # relationship
- "Bar", # target_class
- "" # relationship_to_client
+ "MochaBar", # client_class
+ :foo_bars, # relationship
+ "Bar", # target_class
+ "mocha_bar" # relationship_to_client
).and_return view
- klass = Class.new(RelaxDB::Document) do
+ class ::MochaBar < RelaxDB::Document
has_many :foo_bars, :class => "Bar"
end
end
@@ -121,11 +121,11 @@
it "should invoke the derived properties writer" do
RelaxDB.enable_view_creation
- class HmsdParent < RelaxDB::Document
+ class ::HmsdParent < RelaxDB::Document
property :foo, :derived => [:zongs, lambda {|f, o| o.zongs.first.z / 2 }]
has_many :zongs, :class => "HmsdChild"
end
- class HmsdChild < RelaxDB::Document
+ class ::HmsdChild < RelaxDB::Document
property :z
belongs_to :hmsd_parent
end
View
8 spec/migration_spec.rb
@@ -67,7 +67,7 @@
describe ".run_all" do
it "should save the version after each successful migration" do
- @mig.run_all "a/b/1_", lambda {}
+ @mig.run_all ["a/b/1_"], lambda { |o| }
RelaxDB::MigrationVersion.version.should == 1
end
@@ -75,7 +75,7 @@
v = RelaxDB::MigrationVersion.retrieve
v.version = 2
v.save!
- @mig.run_all "3_", lambda {}
+ @mig.run_all ["3_"], lambda { |o| }
RelaxDB::MigrationVersion.version.should == 3
end
@@ -83,13 +83,13 @@
v = RelaxDB::MigrationVersion.retrieve
v.version = 2
v.save!
- @mig.run_all "1_foo", lambda {}
+ @mig.run_all ["1_foo"], lambda { |o| }
RelaxDB::MigrationVersion.version.should == 2
end
it "should raise an exception on failure" do
lambda do
- @mig.run_all "1_foo", lambda { raise "Expected" }
+ @mig.run_all ["1_foo"], lambda { |o| raise "Expected" }
end.should raise_error(RuntimeError, "Expected")
end
View
4 spec/relaxdb_spec.rb
@@ -164,7 +164,7 @@
RelaxDB.delete_db replica rescue :ok
RelaxDB.enable_view_creation
- class ReplicaTest < RelaxDB::Document; end
+ class ::ReplicaTest < RelaxDB::Document; end
RelaxDB::View.design_doc.save
ReplicaTest.new.save # implicitly saved to orig
@@ -345,7 +345,7 @@ class CvdBar < RelaxDB::Document
RelaxDB.enable_view_creation
- class CveBar < RelaxDB::Document
+ class ::CveBar < RelaxDB::Document
view_docs_by :foo
has_one :foo1
has_many :foon
View
8 spec/spec_models.rb
@@ -1,3 +1,11 @@
+class FooBar < RelaxDB::Document
+ references :bf
+end
+
+class BarFoo < RelaxDB::Document
+ references :fb
+end
+
class Atom < RelaxDB::Document
end
View
6 spec/view_by_spec.rb
@@ -25,6 +25,12 @@
docs.size.should == 10
end
+ it "should return arrays that behave normally" do
+ p1 = Primitives.by_str :key => "1"
+ p2 = Primitives.by_str :key => "2"
+ RelaxDB.load!(p1 + p2).map { |p| p.str }.join.should == "12"
+ end
+
describe "delegator" do
it "should load the returned doc ids" do
View
2  spec/view_docs_by_spec.rb
@@ -14,7 +14,7 @@
RelaxDB.use_db "relaxdb_spec"
RelaxDB.enable_view_creation
- class ViewByFoo < RelaxDB::Document
+ class ::ViewByFoo < RelaxDB::Document
property :foo
view_docs_by :foo, :descending => true
end
Please sign in to comment.
Something went wrong with that request. Please try again.