ripple 0.9.0.beta → 0.9.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile CHANGED
@@ -1,16 +1,17 @@
1
- source :gemcutter
1
+ source :rubygems
2
2
 
3
3
  gem 'bundler'
4
4
  gem 'riak-client', :path => "../riak-client"
5
5
  gem 'activemodel', '~>3.0.0'
6
- gem 'rspec', '~>2.0.0'
6
+ gem 'rspec', '~>2.4.0'
7
7
  gem 'tzinfo'
8
8
  gem 'rake'
9
9
 
10
- if defined? JRUBY_VERSION
10
+ platforms :mri do
11
+ gem 'yajl-ruby'
12
+ end
13
+
14
+ platforms :jruby do
11
15
  gem 'json'
12
16
  gem 'jruby-openssl'
13
- else
14
- gem 'yajl-ruby'
15
- gem 'curb', '>0.6'
16
17
  end
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ gemspec = Gem::Specification.new do |gem|
11
11
  gem.email = "sean@basho.com"
12
12
  gem.homepage = "http://seancribbs.github.com/ripple"
13
13
  gem.authors = ["Sean Cribbs"]
14
- gem.add_development_dependency "rspec", "~>2.0.0"
14
+ gem.add_development_dependency "rspec", "~>2.4.0"
15
15
  gem.add_dependency "riak-client", "~>#{version}"
16
16
  gem.add_dependency "activesupport", "~>3.0.0"
17
17
  gem.add_dependency "activemodel", "~>3.0.0"
@@ -23,10 +23,12 @@ gemspec = Gem::Specification.new do |gem|
23
23
  lib/rails/generators/ripple/configuration/templates/ripple.yml
24
24
  lib/rails/generators/ripple/js/js_generator.rb
25
25
  lib/rails/generators/ripple/js/templates/js/contrib.js
26
+ lib/rails/generators/ripple/js/templates/js/iso8601.js
26
27
  lib/rails/generators/ripple/js/templates/js/ripple.js
27
28
  lib/rails/generators/ripple/model/model_generator.rb
28
- lib/rails/generators/ripple/model/templates
29
29
  lib/rails/generators/ripple/model/templates/model.rb
30
+ lib/rails/generators/ripple/observer/observer_generator.rb
31
+ lib/rails/generators/ripple/observer/templates/observer.rb
30
32
  lib/rails/generators/ripple/test/templates/test_server.rb
31
33
  lib/rails/generators/ripple/test/test_generator.rb
32
34
  lib/rails/generators/ripple_generator.rb
@@ -60,9 +62,9 @@ gemspec = Gem::Specification.new do |gem|
60
62
  lib/ripple/embedded_document.rb
61
63
  lib/ripple/i18n.rb
62
64
  lib/ripple/inspection.rb
63
- lib/ripple/locale
64
65
  lib/ripple/locale/en.yml
65
66
  lib/ripple/nested_attributes.rb
67
+ lib/ripple/observable.rb
66
68
  lib/ripple/properties.rb
67
69
  lib/ripple/property_type_mismatch.rb
68
70
  lib/ripple/railtie.rb
@@ -95,6 +97,7 @@ gemspec = Gem::Specification.new do |gem|
95
97
  spec/ripple/finders_spec.rb
96
98
  spec/ripple/inspection_spec.rb
97
99
  spec/ripple/key_spec.rb
100
+ spec/ripple/observable_spec.rb
98
101
  spec/ripple/persistence_spec.rb
99
102
  spec/ripple/properties_spec.rb
100
103
  spec/ripple/ripple_spec.rb
@@ -0,0 +1,76 @@
1
+ // Written by Paul Sowden, 2005
2
+ // http://delete.me.uk/2005/03/iso8601.html
3
+ // Released under the Academic Free License
4
+
5
+ Date.prototype.setISO8601 = function (string) {
6
+ var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
7
+ "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
8
+ "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
9
+ var d = string.match(new RegExp(regexp));
10
+
11
+ var offset = 0;
12
+ var date = new Date(d[1], 0, 1);
13
+
14
+ if (d[3]) { date.setMonth(d[3] - 1); }
15
+ if (d[5]) { date.setDate(d[5]); }
16
+ if (d[7]) { date.setHours(d[7]); }
17
+ if (d[8]) { date.setMinutes(d[8]); }
18
+ if (d[10]) { date.setSeconds(d[10]); }
19
+ if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
20
+ if (d[14]) {
21
+ offset = (Number(d[16]) * 60) + Number(d[17]);
22
+ offset *= ((d[15] == '-') ? 1 : -1);
23
+ }
24
+
25
+ offset -= date.getTimezoneOffset();
26
+ time = (Number(date) + (offset * 60 * 1000));
27
+ this.setTime(Number(time));
28
+ }
29
+
30
+ Date.prototype.iso8601 = function (format, offset) {
31
+ /* accepted values for the format [1-6]:
32
+ 1 Year:
33
+ YYYY (eg 1997)
34
+ 2 Year and month:
35
+ YYYY-MM (eg 1997-07)
36
+ 3 Complete date:
37
+ YYYY-MM-DD (eg 1997-07-16)
38
+ 4 Complete date plus hours and minutes:
39
+ YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
40
+ 5 Complete date plus hours, minutes and seconds:
41
+ YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
42
+ 6 Complete date plus hours, minutes, seconds and a decimal
43
+ fraction of a second
44
+ YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
45
+ */
46
+ if (!format) { var format = 6; }
47
+ if (!offset) {
48
+ var offset = 'Z';
49
+ var date = this;
50
+ } else {
51
+ var d = offset.match(/([-+])([0-9]{2}):([0-9]{2})/);
52
+ var offsetnum = (Number(d[2]) * 60) + Number(d[3]);
53
+ offsetnum *= ((d[1] == '-') ? -1 : 1);
54
+ var date = new Date(Number(Number(this) + (offsetnum * 60000)));
55
+ }
56
+
57
+ var zeropad = function (num) { return ((num < 10) ? '0' : '') + num; }
58
+
59
+ var str = "";
60
+ str += date.getUTCFullYear();
61
+ if (format > 1) { str += "-" + zeropad(date.getUTCMonth() + 1); }
62
+ if (format > 2) { str += "-" + zeropad(date.getUTCDate()); }
63
+ if (format > 3) {
64
+ str += "T" + zeropad(date.getUTCHours()) +
65
+ ":" + zeropad(date.getUTCMinutes());
66
+ }
67
+ if (format > 5) {
68
+ var secs = Number(date.getUTCSeconds() + "." +
69
+ ((date.getUTCMilliseconds() < 100) ? '0' : '') +
70
+ zeropad(date.getUTCMilliseconds()));
71
+ str += ":" + zeropad(secs);
72
+ } else if (format > 4) { str += ":" + zeropad(date.getUTCSeconds()); }
73
+
74
+ if (format > 3) { str += offset; }
75
+ return str;
76
+ }
@@ -0,0 +1,30 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'rails/generators/ripple_generator'
16
+
17
+ module Ripple
18
+ module Generators
19
+ class ObserverGenerator < NamedBase
20
+ desc 'Creates an observer for Ripple documents'
21
+ check_class_collision :suffix => "Observer"
22
+
23
+ def create_observer_file
24
+ template 'observer.rb', File.join("app/models", class_path, "#{file_name}_observer.rb")
25
+ end
26
+
27
+ hook_for :test_framework
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,4 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Observer < ActiveModel::Observer
3
+ end
4
+ <% end -%>
@@ -8,7 +8,11 @@ module Ripple
8
8
  def test_server_config
9
9
  {
10
10
  :app_config => {
11
- :riak_kv => { :js_source_dir => Ripple.config.delete(:js_source_dir) },
11
+ :riak_kv => {
12
+ :js_source_dir => Ripple.config.delete(:js_source_dir),
13
+ :map_cache_size => 0, # 0.14
14
+ :vnode_cache_entries => 0 # 0.13
15
+ },
12
16
  :riak_core => { :web_port => Ripple.config[:port] || 8098 }
13
17
  },
14
18
  :bin_dir => Ripple.config.delete(:bin_dir),
@@ -33,6 +33,8 @@ module Ripple
33
33
  include Query
34
34
  include Dirty
35
35
  include ActiveModel::MassAssignmentSecurity
36
+
37
+ attr_protected :key
36
38
  end
37
39
 
38
40
  module ClassMethods
@@ -55,17 +57,17 @@ module Ripple
55
57
  # nor embedded documents.
56
58
  # @return [Hash] all document attributes, by key
57
59
  def attributes
58
- self.class.properties.values.inject({}) do |hash, prop|
60
+ self.class.properties.values.inject(@attributes.with_indifferent_access) do |hash, prop|
59
61
  hash[prop.key] = attribute(prop.key)
60
62
  hash
61
- end.with_indifferent_access
63
+ end
62
64
  end
63
65
 
64
66
  # Mass assign the document's attributes.
65
67
  # @param [Hash] attrs the attributes to assign
66
- def attributes=(attrs)
68
+ def attributes=(attrs, guard_protected_attrs = true)
67
69
  raise ArgumentError, t('attribute_hash') unless Hash === attrs
68
- sanitize_for_mass_assignment(attrs).each do |k,v|
70
+ (guard_protected_attrs ? sanitize_for_mass_assignment(attrs) : attrs).each do |k,v|
69
71
  next if k.to_sym == :key
70
72
  if respond_to?("#{k}=")
71
73
  __send__("#{k}=",v)
@@ -50,7 +50,7 @@ module Ripple
50
50
  # @private
51
51
  module InstanceMethods
52
52
  # @private
53
- def save(*args, &block)
53
+ def really_save(*args, &block)
54
54
  state = new? ? :create : :update
55
55
  run_callbacks(:save) do
56
56
  run_callbacks(state) do
@@ -97,7 +97,7 @@ FalseClass.module_eval(&boolean_cast)
97
97
  # @private
98
98
  class Time
99
99
  def as_json(options={})
100
- self.utc.rfc822
100
+ self.utc.send(Ripple.date_format)
101
101
  end
102
102
 
103
103
  def self.ripple_cast(value)
@@ -109,7 +109,7 @@ end
109
109
  # @private
110
110
  class Date
111
111
  def as_json(options={})
112
- self.to_s(:rfc822)
112
+ self.to_s(Ripple.date_format)
113
113
  end
114
114
 
115
115
  def self.ripple_cast(value)
@@ -121,7 +121,7 @@ end
121
121
  # @private
122
122
  class DateTime
123
123
  def as_json(options={})
124
- self.utc.to_s(:rfc822)
124
+ self.utc.to_s(Ripple.date_format)
125
125
  end
126
126
 
127
127
  def self.ripple_cast(value)
@@ -134,7 +134,7 @@ end
134
134
  module ActiveSupport
135
135
  class TimeWithZone
136
136
  def as_json(options={})
137
- self.utc.rfc822
137
+ self.utc.send(Ripple.date_format)
138
138
  end
139
139
  end
140
140
  end
@@ -14,7 +14,7 @@
14
14
  require 'ripple'
15
15
 
16
16
  module Ripple
17
-
17
+
18
18
  # Raised by <tt>find!</tt> when a document cannot be found with the given key.
19
19
  # begin
20
20
  # Example.find!('badkey')
@@ -34,7 +34,7 @@ module Ripple
34
34
  end
35
35
  end
36
36
  end
37
-
37
+
38
38
  module Document
39
39
  module Finders
40
40
  extend ActiveSupport::Concern
@@ -60,7 +60,7 @@ module Ripple
60
60
  return find_one(args.first) if args.size == 1
61
61
  args.map {|key| find_one(key) }
62
62
  end
63
-
63
+
64
64
  # Retrieve single or multiple documents from Riak
65
65
  # but raise Ripple::DocumentNotFound if a key can
66
66
  # not be found in the bucket.
@@ -69,15 +69,15 @@ module Ripple
69
69
  raise DocumentNotFound.new(args, found) if !found || Array(found).include?(nil)
70
70
  found
71
71
  end
72
-
72
+
73
73
  # Find the first object using the first key in the
74
- # bucket's keys using find. You should not expect to
74
+ # bucket's keys using find. You should not expect to
75
75
  # actually get the first object you added to the bucket.
76
76
  # This is just a convenience method.
77
77
  def first
78
78
  find(bucket.keys.first)
79
79
  end
80
-
80
+
81
81
  # Find the first object using the first key in the
82
82
  # bucket's keys using find!
83
83
  def first!
@@ -112,15 +112,14 @@ module Ripple
112
112
  def find_one(key)
113
113
  instantiate(bucket.get(key, quorums.slice(:r)))
114
114
  rescue Riak::FailedRequest => fr
115
- return nil if fr.code.to_i == 404
116
- raise fr
115
+ raise fr unless fr.not_found?
117
116
  end
118
117
 
119
118
  def instantiate(robject)
120
119
  klass = robject.data['_type'].constantize rescue self
121
120
  klass.new.tap do |doc|
122
121
  doc.key = robject.key
123
- robject.data.except("_type").each {|k,v| doc.send("#{k}=", v) } if robject.data
122
+ doc.__send__(:attributes=, robject.data.except("_type"), false) if robject.data
124
123
  doc.instance_variable_set(:@new, false)
125
124
  doc.instance_variable_set(:@robject, robject)
126
125
  end
@@ -70,14 +70,16 @@ module Ripple
70
70
  # Saves the document in Riak.
71
71
  # @return [true,false] whether the document succeeded in saving
72
72
  def save(*args)
73
+ really_save(*args)
74
+ end
75
+
76
+ def really_save(*args)
73
77
  robject.key = key if robject.key != key
74
78
  robject.data = attributes_for_persistence
75
79
  robject.store(self.class.quorums.slice(:w,:dw))
76
80
  self.key = robject.key
77
81
  @new = false
78
82
  true
79
- rescue Riak::FailedRequest
80
- false
81
83
  end
82
84
 
83
85
  # Reloads the document from Riak
@@ -85,7 +87,7 @@ module Ripple
85
87
  def reload
86
88
  return self if new?
87
89
  robject.reload(:force => true)
88
- @robject.data.except("_type").each { |key, value| send("#{key}=", value) }
90
+ self.__send__(:attributes=, @robject.data.except("_type"), false)
89
91
  self
90
92
  end
91
93
 
@@ -0,0 +1,39 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ require 'ripple'
15
+
16
+ module Ripple
17
+ module Observable
18
+ extend ActiveSupport::Concern
19
+ include ActiveModel::Observing
20
+
21
+ included do
22
+ set_callback(:create, :before) { notify_observers :before_create }
23
+ set_callback(:create, :after) { notify_observers :after_create }
24
+
25
+ set_callback(:update, :before) { notify_observers :before_update }
26
+ set_callback(:update, :after) { notify_observers :after_update }
27
+
28
+ set_callback(:save, :before) { notify_observers :before_save }
29
+ set_callback(:save, :after) { notify_observers :after_save }
30
+
31
+ set_callback(:destroy, :before) { notify_observers :before_destroy }
32
+ set_callback(:destroy, :after) { notify_observers :after_destroy }
33
+
34
+ set_callback(:validation, :before) { notify_observers :before_validation }
35
+ set_callback(:validation, :after) { notify_observers :after_validation }
36
+ end
37
+
38
+ end
39
+ end
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  require 'ripple'
15
+ require 'riak/util/translation'
15
16
 
16
17
  module Ripple
17
18
  # Adds i18n translation/string-lookup capabilities.
data/lib/ripple.rb CHANGED
@@ -18,6 +18,7 @@ require 'active_support/json'
18
18
  require 'active_model'
19
19
  require 'ripple/i18n'
20
20
  require 'ripple/core_ext'
21
+ require 'ripple/translation'
21
22
 
22
23
  # Contains the classes and modules related to the ODM built on top of
23
24
  # the basic Riak client.
@@ -46,12 +47,11 @@ module Ripple
46
47
 
47
48
  # Utilities
48
49
  autoload :Inspection
49
- autoload :Translation
50
50
 
51
51
  class << self
52
52
  # @return [Riak::Client] The client for the current thread.
53
53
  def client
54
- Thread.current[:ripple_client] ||= Riak::Client.new(config)
54
+ Thread.current[:ripple_client] ||= Riak::Client.new(client_config)
55
55
  end
56
56
 
57
57
  # Sets the client for the current thread.
@@ -71,6 +71,21 @@ module Ripple
71
71
  @config ||= {}
72
72
  end
73
73
 
74
+ # The format in which date/time objects will be serialized to
75
+ # strings in JSON. Defaults to :iso8601, and can be set in
76
+ # Ripple.config.
77
+ # @return [Symbol] the date format
78
+ def date_format
79
+ (config[:date_format] ||= :iso8601).to_sym
80
+ end
81
+
82
+ # Sets the format for date/time objects that are serialized to
83
+ # JSON.
84
+ # @param [Symbol] format the date format
85
+ def date_format=(format)
86
+ config[:date_format] = format.to_sym
87
+ end
88
+
74
89
  # Loads the Ripple configuration from a given YAML file.
75
90
  # Evaluates the configuration with ERB before loading.
76
91
  def load_configuration(config_file, config_keys = [:ripple])
@@ -82,6 +97,11 @@ module Ripple
82
97
  raise Ripple::MissingConfiguration.new(config_file)
83
98
  end
84
99
  alias_method :load_config, :load_configuration
100
+
101
+ private
102
+ def client_config
103
+ config.slice(:host, :port, :prefix, :mapred, :client_id, :http_backend, :solr)
104
+ end
85
105
  end
86
106
 
87
107
  # Exception raised when the path passed to
data/ripple.gemspec CHANGED
@@ -2,38 +2,37 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{ripple}
5
- s.version = "0.9.0.beta"
5
+ s.version = "0.9.0.beta2"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Sean Cribbs"]
9
- s.date = %q{2010-12-29}
9
+ s.date = %q{2011-03-28}
10
10
  s.description = %q{ripple is an object-mapper library for Riak, the distributed database by Basho. It uses ActiveModel to provide an experience that integrates well with Rails 3 applications.}
11
11
  s.email = %q{sean@basho.com}
12
- s.files = ["Gemfile", "lib/rails/generators/ripple/configuration/configuration_generator.rb", "lib/rails/generators/ripple/configuration/templates/ripple.yml", "lib/rails/generators/ripple/js/js_generator.rb", "lib/rails/generators/ripple/js/templates/js/contrib.js", "lib/rails/generators/ripple/js/templates/js/ripple.js", "lib/rails/generators/ripple/model/model_generator.rb", "lib/rails/generators/ripple/model/templates/model.rb", "lib/rails/generators/ripple/test/templates/test_server.rb", "lib/rails/generators/ripple/test/test_generator.rb", "lib/rails/generators/ripple_generator.rb", "lib/ripple/associations/embedded.rb", "lib/ripple/associations/instantiators.rb", "lib/ripple/associations/linked.rb", "lib/ripple/associations/many.rb", "lib/ripple/associations/many_embedded_proxy.rb", "lib/ripple/associations/many_linked_proxy.rb", "lib/ripple/associations/one.rb", "lib/ripple/associations/one_embedded_proxy.rb", "lib/ripple/associations/one_linked_proxy.rb", "lib/ripple/associations/proxy.rb", "lib/ripple/associations.rb", "lib/ripple/attribute_methods/dirty.rb", "lib/ripple/attribute_methods/query.rb", "lib/ripple/attribute_methods/read.rb", "lib/ripple/attribute_methods/write.rb", "lib/ripple/attribute_methods.rb", "lib/ripple/callbacks.rb", "lib/ripple/conversion.rb", "lib/ripple/core_ext/casting.rb", "lib/ripple/core_ext.rb", "lib/ripple/document/bucket_access.rb", "lib/ripple/document/finders.rb", "lib/ripple/document/key.rb", "lib/ripple/document/persistence.rb", "lib/ripple/document.rb", "lib/ripple/embedded_document/finders.rb", "lib/ripple/embedded_document/persistence.rb", "lib/ripple/embedded_document.rb", "lib/ripple/i18n.rb", "lib/ripple/inspection.rb", "lib/ripple/locale/en.yml", "lib/ripple/nested_attributes.rb", "lib/ripple/properties.rb", "lib/ripple/property_type_mismatch.rb", "lib/ripple/railtie.rb", "lib/ripple/timestamps.rb", "lib/ripple/translation.rb", "lib/ripple/validations/associated_validator.rb", "lib/ripple/validations.rb", "lib/ripple.rb", "Rakefile", "ripple.gemspec", "spec/fixtures/config.yml", "spec/integration/ripple/associations_spec.rb", "spec/integration/ripple/nested_attributes_spec.rb", "spec/integration/ripple/persistence_spec.rb", "spec/ripple/associations/many_embedded_proxy_spec.rb", "spec/ripple/associations/many_linked_proxy_spec.rb", "spec/ripple/associations/one_embedded_proxy_spec.rb", "spec/ripple/associations/one_linked_proxy_spec.rb", "spec/ripple/associations/proxy_spec.rb", "spec/ripple/associations_spec.rb", "spec/ripple/attribute_methods_spec.rb", "spec/ripple/bucket_access_spec.rb", "spec/ripple/callbacks_spec.rb", "spec/ripple/conversion_spec.rb", "spec/ripple/core_ext_spec.rb", "spec/ripple/document_spec.rb", "spec/ripple/embedded_document/finders_spec.rb", "spec/ripple/embedded_document/persistence_spec.rb", "spec/ripple/embedded_document_spec.rb", "spec/ripple/finders_spec.rb", "spec/ripple/inspection_spec.rb", "spec/ripple/key_spec.rb", "spec/ripple/persistence_spec.rb", "spec/ripple/properties_spec.rb", "spec/ripple/ripple_spec.rb", "spec/ripple/timestamps_spec.rb", "spec/ripple/validations_spec.rb", "spec/spec_helper.rb", "spec/support/associations/proxies.rb", "spec/support/mocks.rb", "spec/support/models/address.rb", "spec/support/models/box.rb", "spec/support/models/car.rb", "spec/support/models/cardboard_box.rb", "spec/support/models/clock.rb", "spec/support/models/customer.rb", "spec/support/models/driver.rb", "spec/support/models/email.rb", "spec/support/models/engine.rb", "spec/support/models/family.rb", "spec/support/models/favorite.rb", "spec/support/models/invoice.rb", "spec/support/models/late_invoice.rb", "spec/support/models/note.rb", "spec/support/models/page.rb", "spec/support/models/paid_invoice.rb", "spec/support/models/passenger.rb", "spec/support/models/seat.rb", "spec/support/models/tasks.rb", "spec/support/models/tree.rb", "spec/support/models/user.rb", "spec/support/models/wheel.rb", "spec/support/models/widget.rb", "spec/support/test_server.rb", "spec/support/test_server.yml.example"]
12
+ s.files = ["Gemfile", "lib/rails/generators/ripple/configuration/configuration_generator.rb", "lib/rails/generators/ripple/configuration/templates/ripple.yml", "lib/rails/generators/ripple/js/js_generator.rb", "lib/rails/generators/ripple/js/templates/js/contrib.js", "lib/rails/generators/ripple/js/templates/js/iso8601.js", "lib/rails/generators/ripple/js/templates/js/ripple.js", "lib/rails/generators/ripple/model/model_generator.rb", "lib/rails/generators/ripple/model/templates/model.rb", "lib/rails/generators/ripple/observer/observer_generator.rb", "lib/rails/generators/ripple/observer/templates/observer.rb", "lib/rails/generators/ripple/test/templates/test_server.rb", "lib/rails/generators/ripple/test/test_generator.rb", "lib/rails/generators/ripple_generator.rb", "lib/ripple/associations/embedded.rb", "lib/ripple/associations/instantiators.rb", "lib/ripple/associations/linked.rb", "lib/ripple/associations/many.rb", "lib/ripple/associations/many_embedded_proxy.rb", "lib/ripple/associations/many_linked_proxy.rb", "lib/ripple/associations/one.rb", "lib/ripple/associations/one_embedded_proxy.rb", "lib/ripple/associations/one_linked_proxy.rb", "lib/ripple/associations/proxy.rb", "lib/ripple/associations.rb", "lib/ripple/attribute_methods/dirty.rb", "lib/ripple/attribute_methods/query.rb", "lib/ripple/attribute_methods/read.rb", "lib/ripple/attribute_methods/write.rb", "lib/ripple/attribute_methods.rb", "lib/ripple/callbacks.rb", "lib/ripple/conversion.rb", "lib/ripple/core_ext/casting.rb", "lib/ripple/core_ext.rb", "lib/ripple/document/bucket_access.rb", "lib/ripple/document/finders.rb", "lib/ripple/document/key.rb", "lib/ripple/document/persistence.rb", "lib/ripple/document.rb", "lib/ripple/embedded_document/finders.rb", "lib/ripple/embedded_document/persistence.rb", "lib/ripple/embedded_document.rb", "lib/ripple/i18n.rb", "lib/ripple/inspection.rb", "lib/ripple/locale/en.yml", "lib/ripple/nested_attributes.rb", "lib/ripple/observable.rb", "lib/ripple/properties.rb", "lib/ripple/property_type_mismatch.rb", "lib/ripple/railtie.rb", "lib/ripple/timestamps.rb", "lib/ripple/translation.rb", "lib/ripple/validations/associated_validator.rb", "lib/ripple/validations.rb", "lib/ripple.rb", "Rakefile", "ripple.gemspec", "spec/fixtures/config.yml", "spec/integration/ripple/associations_spec.rb", "spec/integration/ripple/nested_attributes_spec.rb", "spec/integration/ripple/persistence_spec.rb", "spec/ripple/associations/many_embedded_proxy_spec.rb", "spec/ripple/associations/many_linked_proxy_spec.rb", "spec/ripple/associations/one_embedded_proxy_spec.rb", "spec/ripple/associations/one_linked_proxy_spec.rb", "spec/ripple/associations/proxy_spec.rb", "spec/ripple/associations_spec.rb", "spec/ripple/attribute_methods_spec.rb", "spec/ripple/bucket_access_spec.rb", "spec/ripple/callbacks_spec.rb", "spec/ripple/conversion_spec.rb", "spec/ripple/core_ext_spec.rb", "spec/ripple/document_spec.rb", "spec/ripple/embedded_document/finders_spec.rb", "spec/ripple/embedded_document/persistence_spec.rb", "spec/ripple/embedded_document_spec.rb", "spec/ripple/finders_spec.rb", "spec/ripple/inspection_spec.rb", "spec/ripple/key_spec.rb", "spec/ripple/observable_spec.rb", "spec/ripple/persistence_spec.rb", "spec/ripple/properties_spec.rb", "spec/ripple/ripple_spec.rb", "spec/ripple/timestamps_spec.rb", "spec/ripple/validations_spec.rb", "spec/spec_helper.rb", "spec/support/associations/proxies.rb", "spec/support/mocks.rb", "spec/support/models/address.rb", "spec/support/models/box.rb", "spec/support/models/car.rb", "spec/support/models/cardboard_box.rb", "spec/support/models/clock.rb", "spec/support/models/customer.rb", "spec/support/models/driver.rb", "spec/support/models/email.rb", "spec/support/models/engine.rb", "spec/support/models/family.rb", "spec/support/models/favorite.rb", "spec/support/models/invoice.rb", "spec/support/models/late_invoice.rb", "spec/support/models/note.rb", "spec/support/models/page.rb", "spec/support/models/paid_invoice.rb", "spec/support/models/passenger.rb", "spec/support/models/seat.rb", "spec/support/models/tasks.rb", "spec/support/models/tree.rb", "spec/support/models/user.rb", "spec/support/models/wheel.rb", "spec/support/models/widget.rb", "spec/support/test_server.rb", "spec/support/test_server.yml.example"]
13
13
  s.homepage = %q{http://seancribbs.github.com/ripple}
14
14
  s.require_paths = ["lib"]
15
- s.rubygems_version = %q{1.3.7}
15
+ s.rubygems_version = %q{1.6.1}
16
16
  s.summary = %q{ripple is an object-mapper library for Riak, the distributed database by Basho.}
17
- s.test_files = ["spec/integration/ripple/associations_spec.rb", "spec/integration/ripple/nested_attributes_spec.rb", "spec/integration/ripple/persistence_spec.rb", "spec/ripple/associations/many_embedded_proxy_spec.rb", "spec/ripple/associations/many_linked_proxy_spec.rb", "spec/ripple/associations/one_embedded_proxy_spec.rb", "spec/ripple/associations/one_linked_proxy_spec.rb", "spec/ripple/associations/proxy_spec.rb", "spec/ripple/associations_spec.rb", "spec/ripple/attribute_methods_spec.rb", "spec/ripple/bucket_access_spec.rb", "spec/ripple/callbacks_spec.rb", "spec/ripple/conversion_spec.rb", "spec/ripple/core_ext_spec.rb", "spec/ripple/document_spec.rb", "spec/ripple/embedded_document/finders_spec.rb", "spec/ripple/embedded_document/persistence_spec.rb", "spec/ripple/embedded_document_spec.rb", "spec/ripple/finders_spec.rb", "spec/ripple/inspection_spec.rb", "spec/ripple/key_spec.rb", "spec/ripple/persistence_spec.rb", "spec/ripple/properties_spec.rb", "spec/ripple/ripple_spec.rb", "spec/ripple/timestamps_spec.rb", "spec/ripple/validations_spec.rb"]
17
+ s.test_files = ["spec/integration/ripple/associations_spec.rb", "spec/integration/ripple/nested_attributes_spec.rb", "spec/integration/ripple/persistence_spec.rb", "spec/ripple/associations/many_embedded_proxy_spec.rb", "spec/ripple/associations/many_linked_proxy_spec.rb", "spec/ripple/associations/one_embedded_proxy_spec.rb", "spec/ripple/associations/one_linked_proxy_spec.rb", "spec/ripple/associations/proxy_spec.rb", "spec/ripple/associations_spec.rb", "spec/ripple/attribute_methods_spec.rb", "spec/ripple/bucket_access_spec.rb", "spec/ripple/callbacks_spec.rb", "spec/ripple/conversion_spec.rb", "spec/ripple/core_ext_spec.rb", "spec/ripple/document_spec.rb", "spec/ripple/embedded_document/finders_spec.rb", "spec/ripple/embedded_document/persistence_spec.rb", "spec/ripple/embedded_document_spec.rb", "spec/ripple/finders_spec.rb", "spec/ripple/inspection_spec.rb", "spec/ripple/key_spec.rb", "spec/ripple/observable_spec.rb", "spec/ripple/persistence_spec.rb", "spec/ripple/properties_spec.rb", "spec/ripple/ripple_spec.rb", "spec/ripple/timestamps_spec.rb", "spec/ripple/validations_spec.rb"]
18
18
 
19
19
  if s.respond_to? :specification_version then
20
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
21
20
  s.specification_version = 3
22
21
 
23
22
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
24
- s.add_development_dependency(%q<rspec>, ["~> 2.0.0"])
25
- s.add_runtime_dependency(%q<riak-client>, ["~> 0.9.0.beta"])
23
+ s.add_development_dependency(%q<rspec>, ["~> 2.4.0"])
24
+ s.add_runtime_dependency(%q<riak-client>, ["~> 0.9.0.beta2"])
26
25
  s.add_runtime_dependency(%q<activesupport>, ["~> 3.0.0"])
27
26
  s.add_runtime_dependency(%q<activemodel>, ["~> 3.0.0"])
28
27
  else
29
- s.add_dependency(%q<rspec>, ["~> 2.0.0"])
30
- s.add_dependency(%q<riak-client>, ["~> 0.9.0.beta"])
28
+ s.add_dependency(%q<rspec>, ["~> 2.4.0"])
29
+ s.add_dependency(%q<riak-client>, ["~> 0.9.0.beta2"])
31
30
  s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
32
31
  s.add_dependency(%q<activemodel>, ["~> 3.0.0"])
33
32
  end
34
33
  else
35
- s.add_dependency(%q<rspec>, ["~> 2.0.0"])
36
- s.add_dependency(%q<riak-client>, ["~> 0.9.0.beta"])
34
+ s.add_dependency(%q<rspec>, ["~> 2.4.0"])
35
+ s.add_dependency(%q<riak-client>, ["~> 0.9.0.beta2"])
37
36
  s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
38
37
  s.add_dependency(%q<activemodel>, ["~> 3.0.0"])
39
38
  end
@@ -75,4 +75,4 @@ describe Ripple::Associations::Proxy do
75
75
  it { should be_blank }
76
76
  it { should_not be_present }
77
77
  end
78
- end
78
+ end
@@ -185,8 +185,20 @@ describe Ripple::AttributeMethods do
185
185
  lambda { @widget.attributes = nil }.should raise_error(ArgumentError)
186
186
  end
187
187
 
188
- it "should protect attributes from mass assignment" do
188
+ it "should protect attributes from mass assignment when initialized" do
189
189
  @widget = Widget.new(:manufactured => true)
190
190
  @widget.manufactured.should be_false
191
191
  end
192
+
193
+ it "should protect attributes from mass assignment by default" do
194
+ @widget = Widget.new
195
+ @widget.attributes = { :manufactured => true }
196
+ @widget.manufactured.should be_false
197
+ end
198
+
199
+ it "should allow protected attributes to be mass assigned" do
200
+ @widget = Widget.new
201
+ @widget.send(:attributes=, { :manufactured => true }, false)
202
+ @widget.manufactured.should be_true
203
+ end
192
204
  end
@@ -77,6 +77,15 @@ describe Ripple::Callbacks do
77
77
  @box.destroy
78
78
  end
79
79
 
80
+ it "should call save and validate callbacks in the correct order" do
81
+ Box.before_validation { $pinger.ping(:v) }
82
+ Box.before_save { $pinger.ping(:s) }
83
+ $pinger.should_receive(:ping).with(:v).ordered
84
+ $pinger.should_receive(:ping).with(:s).ordered
85
+ @box = Box.new
86
+ @box.save
87
+ end
88
+
80
89
  describe "validation callbacks" do
81
90
  it "should call validation callbacks" do
82
91
  Box.before_validation { $pinger.ping }
@@ -14,35 +14,86 @@
14
14
  require File.expand_path("../../spec_helper", __FILE__)
15
15
 
16
16
  describe Time do
17
- it "serializes to JSON in UTC, RFC 822 format" do
17
+ before { @date_format = Ripple.date_format }
18
+ after { Ripple.date_format = @date_format }
19
+
20
+ it "serializes to JSON in UTC, ISO 8601 format by default" do
21
+ Time.utc(2010,3,16,12).as_json.should == "2010-03-16T12:00:00Z"
22
+ end
23
+
24
+ it "serializes to JSON in UTC, RFC822 format when specified" do
25
+ Ripple.date_format = :rfc822
18
26
  Time.utc(2010,3,16,12).as_json.should == "Tue, 16 Mar 2010 12:00:00 -0000"
19
27
  end
20
28
  end
21
29
 
22
30
  describe Date do
23
- it "serializes to JSON RFC 822 format" do
31
+ before { @date_format = Ripple.date_format }
32
+ after { Ripple.date_format = @date_format }
33
+
34
+ it "serializes to JSON ISO 8601 format by default" do
35
+ Date.civil(2010,3,16).as_json.should == "2010-03-16"
36
+ end
37
+
38
+ it "serializes to JSON in UTC, RFC822 format when specified" do
39
+ Ripple.date_format = :rfc822
24
40
  Date.civil(2010,3,16).as_json.should == "16 Mar 2010"
25
41
  end
26
42
  end
27
43
 
28
44
  describe DateTime do
45
+ before { @date_format = Ripple.date_format }
46
+ after { Ripple.date_format = @date_format }
47
+
29
48
  before :each do
30
49
  Time.zone = :utc
31
50
  end
32
51
 
33
- it "serializes to JSON in UTC, RFC 822 format" do
52
+ it "serializes to JSON in UTC, ISO 8601 format by default" do
53
+ DateTime.civil(2010,3,16,12).as_json.should == "2010-03-16T12:00:00+00:00"
54
+ end
55
+
56
+ it "serializes to JSON in UTC, RFC822 format when specified" do
57
+ Ripple.date_format = :rfc822
34
58
  DateTime.civil(2010,3,16,12).as_json.should == "Tue, 16 Mar 2010 12:00:00 +0000"
35
59
  end
36
60
  end
37
61
 
38
62
  describe ActiveSupport::TimeWithZone do
39
- it "serializes to JSON in UTC, RFC 822 format" do
63
+ before { @date_format = Ripple.date_format }
64
+ after { Ripple.date_format = @date_format }
65
+
66
+ it "serializes to JSON in UTC, ISO 8601 format by default" do
67
+ time = Time.utc(2010,3,16,12)
68
+ zone = ActiveSupport::TimeZone['Alaska']
69
+ ActiveSupport::TimeWithZone.new(time, zone).as_json.should == "2010-03-16T12:00:00Z"
70
+ end
71
+
72
+ it "serializes to JSON in UTC, RFC822 format when specified" do
73
+ Ripple.date_format = :rfc822
40
74
  time = Time.utc(2010,3,16,12)
41
75
  zone = ActiveSupport::TimeZone['Alaska']
42
76
  ActiveSupport::TimeWithZone.new(time, zone).as_json.should == "Tue, 16 Mar 2010 12:00:00 -0000"
43
77
  end
44
78
  end
45
79
 
80
+ describe String do
81
+ it "can parse RFC 822 and ISO 8601 times" do
82
+ 'Tue, 16 Mar 2010 12:00:00 -0000'.to_time.should == Time.utc(2010,3,16,12)
83
+ '2010-03-16T12:00:00Z'.to_time.should == Time.utc(2010,3,16,12)
84
+ end
85
+
86
+ it "can parse RFC 822 and ISO 8601 dates" do
87
+ '16 Mar 2010'.to_date.should == Date.civil(2010,3,16)
88
+ '2010-3-16'.to_date.should == Date.civil(2010,3,16)
89
+ end
90
+
91
+ it "can parse RFC 822 and ISO 8601 datetimes" do
92
+ 'Tue, 16 Mar 2010 12:00:00 +0000'.to_datetime.should == DateTime.civil(2010,3,16,12)
93
+ '2010-03-16T12:00:00+00:00'.to_datetime.should == DateTime.civil(2010,3,16,12)
94
+ end
95
+ end
96
+
46
97
  describe "Boolean" do
47
98
  it "should be available to properties on documents" do
48
99
  lambda {
@@ -75,9 +75,11 @@ describe Ripple::Document::Finders do
75
75
  lambda { Box.find!("square") }.should_not raise_error(Ripple::DocumentNotFound)
76
76
  end
77
77
 
78
- it "should raise an exception when finding an existing document that has properties we don't know about" do
79
- @plain.raw_data = '{"non_existent_property":"whatever"}'
80
- lambda { Box.find("square") }.should raise_error
78
+ it "should put properties we don't know about into the attributes" do
79
+ @plain.raw_data = '{"non_existent_property":"some_value"}'
80
+ box = Box.find("square")
81
+ box[:non_existent_property].should == "some_value"
82
+ box.should_not respond_to(:non_existent_property)
81
83
  end
82
84
 
83
85
  it "should return the document when calling find!" do
@@ -86,18 +88,18 @@ describe Ripple::Document::Finders do
86
88
  end
87
89
 
88
90
  it "should return nil when no object exists at that key" do
89
- @bucket.should_receive(:get).with("square", {}).and_raise(Riak::FailedRequest.new(:get, 200, 404, {}, "404 not found"))
91
+ @bucket.should_receive(:get).with("square", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
90
92
  box = Box.find("square")
91
93
  box.should be_nil
92
94
  end
93
95
 
94
96
  it "should raise DocumentNotFound when using find! if no object exists at that key" do
95
- @bucket.should_receive(:get).with("square", {}).and_raise(Riak::FailedRequest.new(:get, 200, 404, {}, "404 not found"))
97
+ @bucket.should_receive(:get).with("square", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
96
98
  lambda { Box.find!("square") }.should raise_error(Ripple::DocumentNotFound, "Couldn't find document with key: square")
97
99
  end
98
100
 
99
101
  it "should re-raise the failed request exception if not a 404" do
100
- @bucket.should_receive(:get).with("square", {}).and_raise(Riak::FailedRequest.new(:get, 200, 500, {}, "500 internal server error"))
102
+ @bucket.should_receive(:get).with("square", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 500, {}, "500 internal server error"))
101
103
  lambda { Box.find("square") }.should raise_error(Riak::FailedRequest)
102
104
  end
103
105
 
@@ -123,7 +125,7 @@ describe Ripple::Document::Finders do
123
125
  describe "when using find with missing keys" do
124
126
  before :each do
125
127
  @bucket.should_receive(:get).with("square", {}).and_return(@plain)
126
- @bucket.should_receive(:get).with("rectangle", {}).and_raise(Riak::FailedRequest.new(:get, 200, 404, {}, "404 not found"))
128
+ @bucket.should_receive(:get).with("rectangle", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
127
129
  end
128
130
 
129
131
  it "should return nil for documents that no longer exist" do
@@ -153,7 +155,7 @@ describe Ripple::Document::Finders do
153
155
  it "should exclude objects that are not found" do
154
156
  @bucket.should_receive(:keys).and_return(["square", "rectangle"])
155
157
  @bucket.should_receive(:get).with("square", {}).and_return(@plain)
156
- @bucket.should_receive(:get).with("rectangle", {}).and_raise(Riak::FailedRequest.new(:get, 200, 404, {}, "404 not found"))
158
+ @bucket.should_receive(:get).with("rectangle", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
157
159
  boxes = Box.all
158
160
  boxes.should have(1).item
159
161
  boxes.first.shape.should == "square"
@@ -162,7 +164,7 @@ describe Ripple::Document::Finders do
162
164
  it "should yield found objects to the passed block, excluding missing objects, and return an empty array" do
163
165
  @bucket.should_receive(:keys).and_yield(["square"]).and_yield(["rectangle"])
164
166
  @bucket.should_receive(:get).with("square", {}).and_return(@plain)
165
- @bucket.should_receive(:get).with("rectangle", {}).and_raise(Riak::FailedRequest.new(:get, 200, 404, {}, "404 not found"))
167
+ @bucket.should_receive(:get).with("rectangle", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
166
168
  @block = mock()
167
169
  @block.should_receive(:ping).once
168
170
  Box.all do |box|
@@ -0,0 +1,134 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ require File.expand_path("../../spec_helper", __FILE__)
15
+
16
+ describe Ripple::Observable do
17
+ require 'support/models/clock'
18
+ require 'support/models/clock_observer'
19
+
20
+ before :each do
21
+ @client = Ripple.client
22
+ @backend = mock("Backend", :store_object => true)
23
+ @client.stub!(:backend).and_return(@backend)
24
+ @clock = Clock.new
25
+ @observer = ClockObserver.instance
26
+ end
27
+
28
+ context "given a document is created" do
29
+ it "should notify all observers twice" do
30
+ Clock.should_receive(:notify_observers).exactly(6).times
31
+ @clock.save
32
+ end
33
+
34
+ context "before creating the document" do
35
+ it "should call Observer#before_create" do
36
+ @observer.should_receive(:before_create)
37
+ @clock.save
38
+ end
39
+
40
+ it "should call Observer#before_save" do
41
+ @observer.should_receive(:before_save)
42
+ @clock.save
43
+ end
44
+
45
+ it "should call Observer#before_validation" do
46
+ @observer.should_receive(:before_validation)
47
+ @clock.save
48
+ end
49
+ end
50
+
51
+ context "after creating the document" do
52
+ it "should call Observer#after_create" do
53
+ @observer.should_receive(:after_create)
54
+ @clock.save
55
+ end
56
+
57
+ it "should call Observer#after_save" do
58
+ @observer.should_receive(:after_save)
59
+ @clock.save
60
+ end
61
+
62
+ it "should call Observer#after_validation" do
63
+ @observer.should_receive(:after_validation)
64
+ @clock.save
65
+ end
66
+ end
67
+ end
68
+
69
+ context "given a document is updated" do
70
+ before(:each) do
71
+ @clock.stub!(:new?).and_return(false)
72
+ end
73
+
74
+ it "should notify all observers twice" do
75
+ Clock.should_receive(:notify_observers).exactly(6).times
76
+ @clock.save
77
+ end
78
+
79
+ context "before updating the document" do
80
+ it "should call Observer#before_update" do
81
+ @observer.should_receive(:before_update)
82
+ @clock.save
83
+ end
84
+
85
+ it "should call Observer#before_save" do
86
+ @observer.should_receive(:before_save)
87
+ @clock.save
88
+ end
89
+
90
+ it "should call Observer#before_validation" do
91
+ @observer.should_receive(:before_validation)
92
+ @clock.save
93
+ end
94
+ end
95
+
96
+ context "after updating the document" do
97
+ it "should call Observer#after_update" do
98
+ @observer.should_receive(:after_update)
99
+ @clock.save
100
+ end
101
+
102
+ it "should call Observer#after_save" do
103
+ @observer.should_receive(:after_save)
104
+ @clock.save
105
+ end
106
+
107
+ it "should call Observer#after_validation" do
108
+ @observer.should_receive(:after_validation)
109
+ @clock.save
110
+ end
111
+ end
112
+ end
113
+
114
+ context "given a document is destroyed" do
115
+ it "should notify all observers twice" do
116
+ Clock.should_receive(:notify_observers).twice
117
+ @clock.destroy
118
+ end
119
+
120
+ context "before destroying the document" do
121
+ it "should call Observer#before_destroy" do
122
+ @observer.should_receive(:before_destroy)
123
+ @clock.destroy
124
+ end
125
+ end
126
+
127
+ context "after destroy the document" do
128
+ it "should call Observer#after_destroy" do
129
+ @observer.should_receive(:after_destroy)
130
+ @clock.destroy
131
+ end
132
+ end
133
+ end
134
+ end
@@ -68,7 +68,7 @@ describe Ripple::Document::Persistence do
68
68
  end
69
69
 
70
70
  it "should instantiate and save a new object to riak" do
71
- json = @widget.attributes.merge(:size => 10, :shipped_at => "Sat, 01 Jan 2000 20:15:01 -0000", :_type => 'Widget').to_json
71
+ json = @widget.attributes.merge(:size => 10, :shipped_at => "2000-01-01T20:15:01Z", :_type => 'Widget').to_json
72
72
  @backend.should_receive(:store_object) do |obj, _, _, _|
73
73
  obj.raw_data.should == json
74
74
  obj.key.should be_nil
@@ -96,6 +96,28 @@ describe Ripple::Document::Persistence do
96
96
  @widget.should_not be_a_new_record
97
97
  end
98
98
 
99
+ it "should save the attributes not having a corresponding property" do
100
+ attrs = @widget.attributes.merge("_type" => "Widget", "unknown_property" => "a_value")
101
+ @backend.should_receive(:store_object) do |obj, _, _, _|
102
+ obj.data.should == attrs
103
+ obj.key.should be_nil
104
+ # Simulate loading the response with the key
105
+ obj.key = "new_widget"
106
+ end
107
+ @widget["unknown_property"] = "a_value"
108
+ @widget.save
109
+ @widget.key.should == "new_widget"
110
+ @widget.should_not be_a_new_record
111
+ @widget.changes.should be_blank
112
+ end
113
+
114
+ it "should allow unexpected exceptions to be raised" do
115
+ robject = mock("robject", :key => @widget.key, "data=" => true)
116
+ robject.should_receive(:store).and_raise(Riak::HTTPFailedRequest.new(:post, 200, 404, {}, "404 not found"))
117
+ @widget.stub!(:robject).and_return(robject)
118
+ lambda { @widget.save }.should raise_error(Riak::FailedRequest)
119
+ end
120
+
99
121
  it "should reload a saved object" do
100
122
  json = @widget.attributes.merge(:_type => "Widget").to_json
101
123
  @backend.should_receive(:store_object) do |obj, _, _, _|
@@ -34,32 +34,51 @@ describe Ripple do
34
34
  Ripple.client = client
35
35
  Ripple.client.should == client
36
36
  end
37
-
37
+
38
38
  it "should reset the client when the configuration changes" do
39
39
  c = Ripple.client
40
40
  Ripple.config = {:port => 9000}
41
41
  Ripple.client.should_not == c
42
42
  Ripple.client.port.should == 9000
43
43
  end
44
-
44
+
45
45
  it "should raise No Such File or Directory when given a bad configuration file" do
46
46
  lambda { Ripple.load_config('not-here') }.should raise_error(Ripple::MissingConfiguration)
47
47
  end
48
-
48
+
49
49
  it "should pass an empty hash into configure if the configuration file is missing the key" do
50
50
  Ripple.should_receive(:config=).with({})
51
51
  Ripple.load_config(File.join(File.dirname(__FILE__), '..', 'fixtures', 'config.yml'), [:ripple, 'not-here'])
52
52
  end
53
-
53
+
54
54
  it "should select the configuration hash from the config keys provided" do
55
55
  Ripple.load_config(File.join(File.dirname(__FILE__), '..', 'fixtures', 'config.yml'), ['ripple_rails', 'development'])
56
56
  Ripple.client.port.should == 9001
57
57
  Ripple.client.host.should == '127.0.0.1'
58
58
  end
59
-
59
+
60
60
  it "should apply the configuration under the ripple key" do
61
61
  Ripple.load_config(File.join(File.dirname(__FILE__), '..', 'fixtures', 'config.yml'))
62
62
  Ripple.client.port.should == 9000
63
63
  Ripple.client.host.should == 'localhost'
64
64
  end
65
+
66
+ describe "date format" do
67
+ before { @date_format = Ripple.date_format }
68
+ after { Ripple.date_format = @date_format }
69
+
70
+ it "should default to :iso8601" do
71
+ Ripple.date_format.should == :iso8601
72
+ end
73
+
74
+ it "should allow setting via the config" do
75
+ Ripple.config = {"date_format" => "rfc822"}
76
+ Ripple.date_format.should == :rfc822
77
+ end
78
+
79
+ it "should allow setting manually" do
80
+ Ripple.date_format = "rfc822"
81
+ Ripple.date_format.should == :rfc822
82
+ end
83
+ end
65
84
  end
@@ -41,20 +41,20 @@ describe Ripple::Validations do
41
41
  @box.should_receive(:valid?).and_return(false)
42
42
  @box.save.should be_false
43
43
  end
44
-
44
+
45
45
  it "should allow skipping validations by passing save :validate => false" do
46
46
  Ripple.client.http.stub!(:perform).and_return(mock_response)
47
47
  @box.should_not_receive(:valid?)
48
48
  @box.save(:validate => false).should be_true
49
49
  end
50
-
50
+
51
51
  describe "when using save! on an invalid record" do
52
52
  before(:each) { @box.stub!(:valid?).and_return(false) }
53
-
53
+
54
54
  it "should raise DocumentInvalid" do
55
55
  lambda { @box.save! }.should raise_error(Ripple::DocumentInvalid)
56
56
  end
57
-
57
+
58
58
  it "should raise an exception that has the invalid document" do
59
59
  begin
60
60
  @box.save!
@@ -63,26 +63,34 @@ describe Ripple::Validations do
63
63
  end
64
64
  end
65
65
  end
66
-
66
+
67
67
  it "should not raise an error when save! is called and the document is valid" do
68
68
  @box.stub!(:save).and_return(true)
69
69
  @box.stub!(:valid?).and_return(true)
70
70
  lambda { @box.save! }.should_not raise_error(Ripple::DocumentInvalid)
71
71
  end
72
-
72
+
73
73
  it "should return true from save! when no exception is raised" do
74
74
  @box.stub!(:save).and_return(true)
75
75
  @box.stub!(:valid?).and_return(true)
76
76
  @box.save!.should be_true
77
77
  end
78
-
78
+
79
+ it "should allow unexpected exceptions to be raised" do
80
+ robject = mock("robject", :key => @box.key, "data=" => true)
81
+ robject.should_receive(:store).and_raise(Riak::HTTPFailedRequest.new(:post, 200, 404, {}, "404 not found"))
82
+ @box.stub!(:robject).and_return(robject)
83
+ @box.stub!(:valid?).and_return(true)
84
+ lambda { @box.save! }.should raise_error(Riak::FailedRequest)
85
+ end
86
+
79
87
  it "should not raise an error when creating a box with create! succeeds" do
80
88
  @box.stub!(:new?).and_return(false)
81
89
  Box.stub(:create).and_return(@box)
82
90
  lambda { @new_box = Box.create! }.should_not raise_error(Ripple::DocumentInvalid)
83
91
  @new_box.should == @box
84
92
  end
85
-
93
+
86
94
  it "should raise an error when creating a box with create! fails" do
87
95
  @box.stub!(:new?).and_return(true)
88
96
  Box.stub(:create).and_return(@box)
@@ -102,8 +110,8 @@ describe Ripple::Validations do
102
110
  @box.should be_valid
103
111
  Box.properties.delete :size
104
112
  end
105
-
113
+
106
114
  after :each do
107
115
  Box.reset_callbacks(:validate)
108
- end
116
+ end
109
117
  end
metadata CHANGED
@@ -1,14 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ripple
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31098121
5
- prerelease: true
6
- segments:
7
- - 0
8
- - 9
9
- - 0
10
- - beta
11
- version: 0.9.0.beta
4
+ prerelease: 6
5
+ version: 0.9.0.beta2
12
6
  platform: ruby
13
7
  authors:
14
8
  - Sean Cribbs
@@ -16,7 +10,7 @@ autorequire:
16
10
  bindir: bin
17
11
  cert_chain: []
18
12
 
19
- date: 2010-12-29 00:00:00 -06:00
13
+ date: 2011-03-28 00:00:00 -04:00
20
14
  default_executable:
21
15
  dependencies:
22
16
  - !ruby/object:Gem::Dependency
@@ -27,12 +21,7 @@ dependencies:
27
21
  requirements:
28
22
  - - ~>
29
23
  - !ruby/object:Gem::Version
30
- hash: 15
31
- segments:
32
- - 2
33
- - 0
34
- - 0
35
- version: 2.0.0
24
+ version: 2.4.0
36
25
  type: :development
37
26
  version_requirements: *id001
38
27
  - !ruby/object:Gem::Dependency
@@ -43,13 +32,7 @@ dependencies:
43
32
  requirements:
44
33
  - - ~>
45
34
  - !ruby/object:Gem::Version
46
- hash: 31098121
47
- segments:
48
- - 0
49
- - 9
50
- - 0
51
- - beta
52
- version: 0.9.0.beta
35
+ version: 0.9.0.beta2
53
36
  type: :runtime
54
37
  version_requirements: *id002
55
38
  - !ruby/object:Gem::Dependency
@@ -60,11 +43,6 @@ dependencies:
60
43
  requirements:
61
44
  - - ~>
62
45
  - !ruby/object:Gem::Version
63
- hash: 7
64
- segments:
65
- - 3
66
- - 0
67
- - 0
68
46
  version: 3.0.0
69
47
  type: :runtime
70
48
  version_requirements: *id003
@@ -76,11 +54,6 @@ dependencies:
76
54
  requirements:
77
55
  - - ~>
78
56
  - !ruby/object:Gem::Version
79
- hash: 7
80
- segments:
81
- - 3
82
- - 0
83
- - 0
84
57
  version: 3.0.0
85
58
  type: :runtime
86
59
  version_requirements: *id004
@@ -98,9 +71,12 @@ files:
98
71
  - lib/rails/generators/ripple/configuration/templates/ripple.yml
99
72
  - lib/rails/generators/ripple/js/js_generator.rb
100
73
  - lib/rails/generators/ripple/js/templates/js/contrib.js
74
+ - lib/rails/generators/ripple/js/templates/js/iso8601.js
101
75
  - lib/rails/generators/ripple/js/templates/js/ripple.js
102
76
  - lib/rails/generators/ripple/model/model_generator.rb
103
77
  - lib/rails/generators/ripple/model/templates/model.rb
78
+ - lib/rails/generators/ripple/observer/observer_generator.rb
79
+ - lib/rails/generators/ripple/observer/templates/observer.rb
104
80
  - lib/rails/generators/ripple/test/templates/test_server.rb
105
81
  - lib/rails/generators/ripple/test/test_generator.rb
106
82
  - lib/rails/generators/ripple_generator.rb
@@ -136,6 +112,7 @@ files:
136
112
  - lib/ripple/inspection.rb
137
113
  - lib/ripple/locale/en.yml
138
114
  - lib/ripple/nested_attributes.rb
115
+ - lib/ripple/observable.rb
139
116
  - lib/ripple/properties.rb
140
117
  - lib/ripple/property_type_mismatch.rb
141
118
  - lib/ripple/railtie.rb
@@ -168,6 +145,7 @@ files:
168
145
  - spec/ripple/finders_spec.rb
169
146
  - spec/ripple/inspection_spec.rb
170
147
  - spec/ripple/key_spec.rb
148
+ - spec/ripple/observable_spec.rb
171
149
  - spec/ripple/persistence_spec.rb
172
150
  - spec/ripple/properties_spec.rb
173
151
  - spec/ripple/ripple_spec.rb
@@ -215,25 +193,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
215
193
  requirements:
216
194
  - - ">="
217
195
  - !ruby/object:Gem::Version
218
- hash: 3
219
- segments:
220
- - 0
221
196
  version: "0"
222
197
  required_rubygems_version: !ruby/object:Gem::Requirement
223
198
  none: false
224
199
  requirements:
225
200
  - - ">"
226
201
  - !ruby/object:Gem::Version
227
- hash: 25
228
- segments:
229
- - 1
230
- - 3
231
- - 1
232
202
  version: 1.3.1
233
203
  requirements: []
234
204
 
235
205
  rubyforge_project:
236
- rubygems_version: 1.3.7
206
+ rubygems_version: 1.6.1
237
207
  signing_key:
238
208
  specification_version: 3
239
209
  summary: ripple is an object-mapper library for Riak, the distributed database by Basho.
@@ -259,6 +229,7 @@ test_files:
259
229
  - spec/ripple/finders_spec.rb
260
230
  - spec/ripple/inspection_spec.rb
261
231
  - spec/ripple/key_spec.rb
232
+ - spec/ripple/observable_spec.rb
262
233
  - spec/ripple/persistence_spec.rb
263
234
  - spec/ripple/properties_spec.rb
264
235
  - spec/ripple/ripple_spec.rb