active_remote 1.6.1 → 1.7.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b484c875f2b7f6e8dd9b3ba72d802c80ebd923c
4
- data.tar.gz: 29194830e6f79902050b17ce78c7494b56cfce85
3
+ metadata.gz: a53038e5bd4f39ffbba6356eaeeb8de9c55ee2aa
4
+ data.tar.gz: 694f516e1adb22e5fd3ed9c68395b6081a54d389
5
5
  SHA512:
6
- metadata.gz: 0664c1c11685b5260104c8f0eefc96bda16195b69e0aa8de185a4540f854a8ea1b273e1ea8b5e18fbd5b24951c84078ed88e03f86eb0aacf1686cf44395cf1d7
7
- data.tar.gz: 1169cb3e752f32648903e8e8d3d1c97e3264230b73bfabc7a4870200f58ad3d9aa385df0193edaac9795894221ebcedff63bb3df2ac26b60f901a6a91c22b824
6
+ metadata.gz: 179ff3825b682860f3600cf90735a783c49f175f764ed56779d859b230da021961f7124faac2561fbc029d0ee9924f37c00532b2190a11d4495f1e5525c25fd9
7
+ data.tar.gz: 1f3d111e0cc746926899f9aba30f2c82e32caeb4eddca8250debdcf1830c877588d4e0c29cc3a36352e253c98562d21ea5ee34de1ed8aa8831ebbef34116f8f8
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  .DS_Store
4
4
  .bundle
5
5
  .config
6
+ .ruby-*
6
7
  .rvmrc
7
8
  .yardoc
8
9
  .idea
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
20
20
  # Dependencies
21
21
  #
22
22
  s.add_dependency "active_attr"
23
+ s.add_dependency "activesupport"
23
24
  s.add_dependency "protobuf", ">= 2.0"
24
25
 
25
26
  ##
@@ -1,15 +1,29 @@
1
1
  require 'active_attr'
2
2
  require 'active_model'
3
+ require 'protobuf'
4
+
3
5
  require 'active_support/core_ext/array'
4
6
  require 'active_support/core_ext/hash'
5
7
  require 'active_support/inflector'
6
8
  require 'active_support/json'
7
9
 
8
- require 'core_ext/date_time'
9
- require 'core_ext/date'
10
- require 'core_ext/integer'
10
+ require 'active_remote/core_ext/date_time'
11
+ require 'active_remote/core_ext/date'
12
+ require 'active_remote/core_ext/integer'
11
13
 
12
14
  require 'active_remote/base'
15
+ require 'active_remote/config'
13
16
  require 'active_remote/errors'
14
17
 
15
18
  require 'active_remote/version'
19
+
20
+ module ActiveRemote
21
+ def self.config
22
+ @config ||= ::ActiveRemote::Config.new
23
+ end
24
+
25
+ # Initialize the config
26
+ config
27
+ end
28
+
29
+ require 'active_remote/railtie' if defined?(Rails)
@@ -6,7 +6,7 @@ module ActiveRemote
6
6
  name = name.to_s
7
7
 
8
8
  if respond_to? name
9
- @attributes[name]
9
+ attribute(name)
10
10
  else
11
11
  raise ::ActiveAttr::UnknownAttributeError, "unknown attribute: #{name}"
12
12
  end
@@ -19,7 +19,7 @@ module ActiveRemote
19
19
  name = name.to_s
20
20
 
21
21
  if respond_to? "#{name}="
22
- @attributes[name] = typecast_attribute(_attribute_typecaster(name), value)
22
+ __send__("attribute=", name, value)
23
23
  else
24
24
  raise ::ActiveAttr::UnknownAttributeError, "unknown attribute: #{name}"
25
25
  end
@@ -1,6 +1,7 @@
1
1
  require 'active_remote/association'
2
2
  require 'active_remote/attributes'
3
3
  require 'active_remote/bulk'
4
+ require 'active_remote/config'
4
5
  require 'active_remote/dirty'
5
6
  require 'active_remote/dsl'
6
7
  require 'active_remote/integration'
@@ -104,7 +104,12 @@ module ActiveRemote
104
104
  #
105
105
  def parse_records(*records)
106
106
  records.flatten!
107
- records.collect!(&:to_hash)
107
+
108
+ if records.first.respond_to?(:attributes)
109
+ records.collect!(&:attributes)
110
+ else
111
+ records.collect!(&:to_hash)
112
+ end
108
113
 
109
114
  return records.first if records.first.has_key?(:records)
110
115
 
@@ -0,0 +1,23 @@
1
+ require 'active_support/ordered_options'
2
+
3
+ module ActiveRemote
4
+ class Config < ::ActiveSupport::OrderedOptions
5
+
6
+ def initialize(options = {})
7
+ super
8
+
9
+ self.default_cache_key_updated_at = false
10
+ self.include_root_in_json = true
11
+ end
12
+
13
+ def default_cache_key_updated_at?
14
+ self[:default_cache_key_updated_at]
15
+ end
16
+
17
+ def include_root_in_json=(true_or_false)
18
+ self[:include_root_in_json] = !!true_or_false
19
+ ::ActiveRemote::Base.include_root_in_json = self[:include_root_in_json]
20
+ end
21
+
22
+ end
23
+ end
@@ -46,7 +46,7 @@ module ActiveRemote
46
46
  @publishable_attributes
47
47
  end
48
48
 
49
- # Set the RPC service class directly. By default, ActiveRemove determines
49
+ # Set the RPC service class directly. By default, ActiveRemote determines
50
50
  # the RPC service by constantizing the namespace and service name.
51
51
  #
52
52
  # ====Examples
@@ -34,14 +34,14 @@ module ActiveRemote
34
34
  # ==== Examples
35
35
  #
36
36
  # Product.new.cache_key # => "products/new"
37
- # Product.search(:guid => "derp-5").cache_key # => "products/derp-5" (updated_at not available)
38
- # Person.search(:guid => "derp-5").cache_key # => "people/derp-5-20071224150000" (updated_at available)
37
+ # Person.search(:guid => "derp-5").cache_key # => "people/derp-5-20071224150000" (include updated_at)
38
+ # Product.search(:guid => "derp-5").cache_key # => "products/derp-5"
39
39
  #
40
40
  def cache_key
41
41
  case
42
42
  when new_record? then
43
43
  "#{self.class.name.underscore}/new"
44
- when timestamp = self[:updated_at] then
44
+ when ::ActiveRemote.config.default_cache_key_updated_at? && (timestamp = self[:updated_at]) then
45
45
  timestamp = timestamp.utc.to_s(self.class.cache_timestamp_format)
46
46
  "#{self.class.name.underscore}/#{self.to_param}-#{timestamp}"
47
47
  else
@@ -10,7 +10,7 @@ module ActiveRemote
10
10
 
11
11
  # Allow users to create callbacks around a `save` call.
12
12
  #
13
- define_model_callbacks :save
13
+ define_model_callbacks :save, :create, :update
14
14
 
15
15
  # Before a save occurs, ensure that we
16
16
  # clear out the errors list.
@@ -75,7 +75,7 @@ module ActiveRemote
75
75
  #
76
76
  def delete
77
77
  raise ReadOnlyRemoteRecord if readonly?
78
- execute(:delete, @attributes.slice("guid"))
78
+ execute(:delete, "guid" => read_attribute("guid"))
79
79
 
80
80
  return success? ? freeze : false
81
81
  end
@@ -98,7 +98,7 @@ module ActiveRemote
98
98
  #
99
99
  def destroy
100
100
  raise ReadOnlyRemoteRecord if readonly?
101
- execute(:destroy, @attributes.slice("guid"))
101
+ execute(:destroy, "guid" => read_attribute("guid"))
102
102
 
103
103
  return success? ? freeze : false
104
104
  end
@@ -197,16 +197,18 @@ module ActiveRemote
197
197
  # errors from the response.
198
198
  #
199
199
  def create
200
- # Use the getter here so we get the type casting.
201
- new_attributes = attributes
202
- new_attributes.delete("guid")
200
+ run_callbacks :create do
201
+ # Use the getter here so we get the type casting.
202
+ new_attributes = attributes
203
+ new_attributes.delete("guid")
203
204
 
204
- execute(:create, new_attributes)
205
+ execute(:create, new_attributes)
205
206
 
206
- assign_attributes(last_response.to_hash)
207
- add_errors_from_response
207
+ assign_attributes(last_response.to_hash)
208
+ add_errors_from_response
208
209
 
209
- success?
210
+ success?
211
+ end
210
212
  end
211
213
 
212
214
  # Deterines whether the record should be created or updated. New records
@@ -223,17 +225,19 @@ module ActiveRemote
223
225
  # (plus :guid) will be updated. Defaults to all attributes.
224
226
  #
225
227
  def update(attribute_names = @attributes.keys)
226
- # Use the getter here so we get the type casting.
227
- updated_attributes = attributes
228
- updated_attributes.slice!(*attribute_names)
229
- updated_attributes.merge!("guid" => self[:guid])
228
+ run_callbacks :update do
229
+ # Use the getter here so we get the type casting.
230
+ updated_attributes = attributes
231
+ updated_attributes.slice!(*attribute_names)
232
+ updated_attributes.merge!("guid" => self[:guid])
230
233
 
231
- execute(:update, updated_attributes)
234
+ execute(:update, updated_attributes)
232
235
 
233
- assign_attributes(last_response.to_hash)
234
- add_errors_from_response
236
+ assign_attributes(last_response.to_hash)
237
+ add_errors_from_response
235
238
 
236
- success?
239
+ success?
240
+ end
237
241
  end
238
242
  end
239
243
  end
@@ -6,7 +6,7 @@ module ActiveRemote
6
6
  keys = _publishable_attributes_or_attribute_keys
7
7
 
8
8
  attributes_hash = keys.inject({}) do |publishable_hash, key|
9
- value = respond_to?(key) ? __send__(key) : @attributes[key]
9
+ value = respond_to?(key) ? __send__(key) : read_attribute(key)
10
10
 
11
11
  publishable_hash[key] = case
12
12
  when value.respond_to?(:map) then
@@ -0,0 +1,5 @@
1
+ module ActiveRemote
2
+ class Railtie < ::Rails::Railtie
3
+ config.active_remote = ::ActiveRemote.config
4
+ end
5
+ end
@@ -1,5 +1,3 @@
1
- require 'protobuf_extensions/base_field'
2
-
3
1
  module ActiveRemote
4
2
  module Serializers
5
3
  module Protobuf
@@ -1,3 +1,3 @@
1
1
  module ActiveRemote
2
- VERSION = "1.6.1"
2
+ VERSION = "1.7.0"
3
3
  end
@@ -42,12 +42,24 @@ describe ActiveRemote::Bulk do
42
42
 
43
43
  describe ".parse_records" do
44
44
  let(:records) { [ Hash.new ] }
45
+ let(:attribute_record) {
46
+ record = double(Hash)
47
+ record.stub(:attributes) { {} }
48
+ record
49
+ }
50
+ let(:records) { [ Hash.new ] }
45
51
 
46
52
  it "preps records to be built into a bulk request" do
47
53
  parsed_records = { :records => records }
48
54
  Tag.parse_records(records).should eq parsed_records
49
55
  end
50
56
 
57
+ it "preps records to be built into a bulk request (prioritizing :attributes over :to_hash)" do
58
+ attribute_record.should_receive(:attributes)
59
+ parsed_records = { :records => [ {} ] }
60
+ Tag.parse_records([ attribute_record ]).should eq parsed_records
61
+ end
62
+
51
63
  context "when given a bulk message" do
52
64
  let(:records) { [ tag.to_hash ] }
53
65
  let(:tag) { Generic::Remote::Tag.new }
@@ -71,4 +83,4 @@ describe ActiveRemote::Bulk do
71
83
  Tag.update_all(records)
72
84
  end
73
85
  end
74
- end
86
+ end
@@ -28,10 +28,16 @@ describe ::ActiveRemote::Integration do
28
28
  end
29
29
 
30
30
  it "adds the 'updated_at' attribute to the cache_key if updated_at is present" do
31
+ ::ActiveRemote.config.default_cache_key_updated_at = true
31
32
  twenty_o_one_one = subject[:updated_at] = DateTime.new(2001, 01, 01)
32
33
  subject.should_receive(:new_record?).and_return(false)
33
34
  subject.cache_key.should eq("tag/#{guid}-#{twenty_o_one_one.to_s(:number)}")
34
35
  subject[:updated_at] = nil
36
+ ::ActiveRemote.config.default_cache_key_updated_at = false
37
+ end
38
+
39
+ it "defaults the cache updated_at to false" do
40
+ ::ActiveRemote.config.default_cache_key_updated_at?.should be_false
35
41
  end
36
42
  end
37
43
  end
@@ -9,6 +9,12 @@ describe ActiveRemote::Persistence do
9
9
  before { Tag.any_instance.stub(:execute) }
10
10
  after { Tag.any_instance.unstub(:execute) }
11
11
 
12
+ it "runs create callbacks" do
13
+ Tag.any_instance.should_receive(:after_create_callback)
14
+ Tag.create(:name => 'foo')
15
+ end
16
+
17
+
12
18
  it "initializes and saves a new record" do
13
19
  Tag.any_instance.should_receive(:save)
14
20
  Tag.create(:name => 'foo')
@@ -170,7 +176,7 @@ describe ActiveRemote::Persistence do
170
176
  before { subject.stub(:execute) }
171
177
  after { subject.unstub(:execute) }
172
178
 
173
- it "runs callbacks" do
179
+ it "runs save callbacks" do
174
180
  subject.should_receive(:run_callbacks).with(:save)
175
181
  subject.save
176
182
  end
@@ -257,6 +263,15 @@ describe ActiveRemote::Persistence do
257
263
  describe "#update_attributes" do
258
264
  let(:attributes) { HashWithIndifferentAccess.new(:name => 'bar') }
259
265
 
266
+ before { Tag.any_instance.stub(:execute) }
267
+ after { Tag.any_instance.unstub(:execute) }
268
+
269
+ it "runs update callbacks" do
270
+ tag = Tag.new({:guid => "123"})
271
+ tag.should_receive(:after_update_callback)
272
+ tag.update_attributes({})
273
+ end
274
+
260
275
  before { subject.stub(:save) }
261
276
  after { subject.unstub(:save) }
262
277
 
@@ -7,32 +7,71 @@ describe ActiveRemote::Serializers::JSON do
7
7
 
8
8
  subject { Tag.new(attributes) }
9
9
 
10
- context "when options are nil" do
11
- it "substitutes an empty hash" do
12
- subject.as_json(nil).should eq serializable_attributes
10
+ context "with roots in json" do
11
+ context "when options are nil" do
12
+ it "substitutes an empty hash" do
13
+ subject.as_json(nil).should eq serializable_attributes
14
+ end
13
15
  end
14
- end
15
16
 
16
- it "accepts standard JSON options" do
17
- subject.as_json(:root => false).should eq attributes.stringify_keys
18
- end
17
+ it "accepts standard JSON options" do
18
+ subject.as_json(:root => false).should eq attributes.stringify_keys
19
+ end
19
20
 
20
- context "with publishable attributes defined" do
21
- let(:expected_json) { { :tag => attributes.slice(:name) }.to_json }
21
+ context "with publishable attributes defined" do
22
+ let(:expected_json) { { :tag => attributes.slice(:name) }.to_json }
22
23
 
23
- before { Tag.attr_publishable :name }
24
- after { reset_publishable_attributes(Tag) }
24
+ before { Tag.attr_publishable :name }
25
+ after { reset_publishable_attributes(Tag) }
25
26
 
26
- it "serializes to JSON with only the publishable attributes" do
27
- subject.to_json.should eq expected_json
27
+ it "serializes to JSON with only the publishable attributes" do
28
+ subject.to_json.should eq expected_json
29
+ end
30
+ end
31
+
32
+ context "without publishable attributes defined" do
33
+ let(:expected_json) { { :tag => attributes }.to_json }
34
+
35
+ it "serializes to JSON" do
36
+ subject.to_json.should eq expected_json
37
+ end
28
38
  end
29
39
  end
30
40
 
31
- context "without publishable attributes defined" do
32
- let(:expected_json) { { :tag => attributes }.to_json }
41
+ context "without roots in json" do
42
+ let(:serializable_attributes) { attributes.stringify_keys }
43
+
44
+ before(:each) do
45
+ ::ActiveRemote.config.include_root_in_json = false
46
+ end
47
+
48
+ after(:each) do
49
+ ::ActiveRemote.config.include_root_in_json = true
50
+ end
51
+
52
+ context "when options are nil" do
53
+ it "substitutes an empty hash" do
54
+ subject.as_json(nil).should eq serializable_attributes
55
+ end
56
+ end
57
+
58
+ context "with publishable attributes defined" do
59
+ let(:expected_json) { attributes.slice(:name).to_json }
60
+
61
+ before { Tag.attr_publishable :name }
62
+ after { reset_publishable_attributes(Tag) }
63
+
64
+ it "serializes to JSON with only the publishable attributes" do
65
+ subject.to_json.should eq expected_json
66
+ end
67
+ end
68
+
69
+ context "without publishable attributes defined" do
70
+ let(:expected_json) { attributes.to_json }
33
71
 
34
- it "serializes to JSON" do
35
- subject.to_json.should eq expected_json
72
+ it "serializes to JSON" do
73
+ subject.to_json.should eq expected_json
74
+ end
36
75
  end
37
76
  end
38
77
  end
@@ -10,4 +10,12 @@ class Tag < ::ActiveRemote::Base
10
10
  attribute :name
11
11
  attribute :updated_at
12
12
 
13
+ after_update :after_update_callback
14
+ after_create :after_create_callback
15
+
16
+ def after_create_callback
17
+ end
18
+
19
+ def after_update_callback
20
+ end
13
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_remote
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.1
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Hutchison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-31 00:00:00.000000000 Z
11
+ date: 2013-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_attr
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: protobuf
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -143,22 +157,23 @@ files:
143
157
  - lib/active_remote/attributes.rb
144
158
  - lib/active_remote/base.rb
145
159
  - lib/active_remote/bulk.rb
160
+ - lib/active_remote/config.rb
161
+ - lib/active_remote/core_ext/date.rb
162
+ - lib/active_remote/core_ext/date_time.rb
163
+ - lib/active_remote/core_ext/integer.rb
146
164
  - lib/active_remote/dirty.rb
147
165
  - lib/active_remote/dsl.rb
148
166
  - lib/active_remote/errors.rb
149
167
  - lib/active_remote/integration.rb
150
168
  - lib/active_remote/persistence.rb
151
169
  - lib/active_remote/publication.rb
170
+ - lib/active_remote/railtie.rb
152
171
  - lib/active_remote/rpc.rb
153
172
  - lib/active_remote/search.rb
154
173
  - lib/active_remote/serialization.rb
155
174
  - lib/active_remote/serializers/json.rb
156
175
  - lib/active_remote/serializers/protobuf.rb
157
176
  - lib/active_remote/version.rb
158
- - lib/core_ext/date.rb
159
- - lib/core_ext/date_time.rb
160
- - lib/core_ext/integer.rb
161
- - lib/protobuf_extensions/base_field.rb
162
177
  - spec/core_ext/date_time_spec.rb
163
178
  - spec/lib/active_remote/association_spec.rb
164
179
  - spec/lib/active_remote/base_spec.rb
@@ -211,41 +226,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
226
  version: '0'
212
227
  requirements: []
213
228
  rubyforge_project:
214
- rubygems_version: 2.0.6
229
+ rubygems_version: 2.0.3
215
230
  signing_key:
216
231
  specification_version: 4
217
232
  summary: Active Record for your platform
218
- test_files:
219
- - spec/core_ext/date_time_spec.rb
220
- - spec/lib/active_remote/association_spec.rb
221
- - spec/lib/active_remote/base_spec.rb
222
- - spec/lib/active_remote/bulk_spec.rb
223
- - spec/lib/active_remote/dirty_spec.rb
224
- - spec/lib/active_remote/dsl_spec.rb
225
- - spec/lib/active_remote/integration_spec.rb
226
- - spec/lib/active_remote/persistence_spec.rb
227
- - spec/lib/active_remote/publication_spec.rb
228
- - spec/lib/active_remote/rpc_spec.rb
229
- - spec/lib/active_remote/search_spec.rb
230
- - spec/lib/active_remote/serialization_spec.rb
231
- - spec/lib/active_remote/serializers/json_spec.rb
232
- - spec/lib/active_remote/serializers/protobuf_spec.rb
233
- - spec/spec_helper.rb
234
- - spec/support/definitions/author.proto
235
- - spec/support/definitions/post.proto
236
- - spec/support/definitions/support/protobuf/category.proto
237
- - spec/support/definitions/support/protobuf/error.proto
238
- - spec/support/definitions/tag.proto
239
- - spec/support/helpers.rb
240
- - spec/support/models.rb
241
- - spec/support/models/author.rb
242
- - spec/support/models/category.rb
243
- - spec/support/models/message_with_options.rb
244
- - spec/support/models/post.rb
245
- - spec/support/models/tag.rb
246
- - spec/support/protobuf.rb
247
- - spec/support/protobuf/author.pb.rb
248
- - spec/support/protobuf/category.pb.rb
249
- - spec/support/protobuf/error.pb.rb
250
- - spec/support/protobuf/post.pb.rb
251
- - spec/support/protobuf/tag.pb.rb
233
+ test_files: []
@@ -1,18 +0,0 @@
1
- require 'protobuf'
2
-
3
- # A couple of helper fields.
4
- # Might make sense to create a patch for Protobuf.
5
- #
6
- Protobuf::Field::BaseField.class_eval do
7
- unless respond_to?(:enum?)
8
- def enum?
9
- kind_of?(Protobuf::Field::EnumField)
10
- end
11
- end
12
-
13
- unless respond_to?(:message?)
14
- def message?
15
- kind_of?(Protobuf::Field::MessageField)
16
- end
17
- end
18
- end