active_remote 3.3.3 → 5.0.0.pre

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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +28 -0
  3. data/CHANGES.md +13 -0
  4. data/Gemfile +1 -1
  5. data/Rakefile +7 -3
  6. data/active_remote.gemspec +8 -6
  7. data/lib/active_remote.rb +9 -8
  8. data/lib/active_remote/association.rb +12 -14
  9. data/lib/active_remote/attribute_definition.rb +14 -12
  10. data/lib/active_remote/attributes.rb +6 -6
  11. data/lib/active_remote/base.rb +20 -27
  12. data/lib/active_remote/config.rb +1 -1
  13. data/lib/active_remote/dirty.rb +3 -3
  14. data/lib/active_remote/dsl.rb +3 -4
  15. data/lib/active_remote/errors.rb +1 -11
  16. data/lib/active_remote/persistence.rb +11 -12
  17. data/lib/active_remote/primary_key.rb +0 -1
  18. data/lib/active_remote/query_attributes.rb +13 -13
  19. data/lib/active_remote/rpc.rb +8 -14
  20. data/lib/active_remote/rpc_adapters/protobuf_adapter.rb +18 -17
  21. data/lib/active_remote/scope_keys.rb +1 -2
  22. data/lib/active_remote/search.rb +8 -6
  23. data/lib/active_remote/serializers/protobuf.rb +15 -25
  24. data/lib/active_remote/validations.rb +1 -1
  25. data/lib/active_remote/version.rb +1 -1
  26. data/spec/lib/active_remote/association_spec.rb +23 -23
  27. data/spec/lib/active_remote/attributes_spec.rb +49 -3
  28. data/spec/lib/active_remote/base_spec.rb +1 -1
  29. data/spec/lib/active_remote/dirty_spec.rb +12 -12
  30. data/spec/lib/active_remote/dsl_spec.rb +4 -4
  31. data/spec/lib/active_remote/integration_spec.rb +2 -2
  32. data/spec/lib/active_remote/persistence_spec.rb +26 -33
  33. data/spec/lib/active_remote/primary_key_spec.rb +3 -3
  34. data/spec/lib/active_remote/query_attribute_spec.rb +0 -120
  35. data/spec/lib/active_remote/rpc_adapters/protobuf_adapter_spec.rb +1 -1
  36. data/spec/lib/active_remote/rpc_spec.rb +1 -1
  37. data/spec/lib/active_remote/scope_keys_spec.rb +7 -7
  38. data/spec/lib/active_remote/search_spec.rb +8 -8
  39. data/spec/lib/active_remote/serialization_spec.rb +4 -4
  40. data/spec/lib/active_remote/serializers/protobuf_spec.rb +23 -23
  41. data/spec/lib/active_remote/validations_spec.rb +17 -17
  42. data/spec/spec_helper.rb +9 -9
  43. data/spec/support/helpers.rb +6 -6
  44. data/spec/support/models.rb +8 -8
  45. data/spec/support/models/author.rb +1 -1
  46. data/spec/support/models/category.rb +1 -2
  47. data/spec/support/models/default_author.rb +1 -1
  48. data/spec/support/models/post.rb +4 -4
  49. data/spec/support/models/tag.rb +1 -1
  50. data/spec/support/models/typecasted_author.rb +4 -5
  51. data/spec/support/protobuf.rb +5 -5
  52. metadata +24 -26
  53. data/lib/active_remote/attribute_assignment.rb +0 -53
  54. data/lib/active_remote/type.rb +0 -36
  55. data/lib/active_remote/type/registry.rb +0 -45
  56. data/lib/active_remote/typecasting.rb +0 -51
  57. data/lib/active_remote/typecasting/big_decimal_typecaster.rb +0 -21
  58. data/lib/active_remote/typecasting/boolean.rb +0 -7
  59. data/lib/active_remote/typecasting/boolean_typecaster.rb +0 -18
  60. data/lib/active_remote/typecasting/date_time_typecaster.rb +0 -10
  61. data/lib/active_remote/typecasting/date_typecaster.rb +0 -10
  62. data/lib/active_remote/typecasting/float_typecaster.rb +0 -9
  63. data/lib/active_remote/typecasting/integer_typecaster.rb +0 -10
  64. data/lib/active_remote/typecasting/object_typecaster.rb +0 -9
  65. data/lib/active_remote/typecasting/string_typecaster.rb +0 -9
  66. data/spec/lib/active_remote/errors_spec.rb +0 -31
  67. data/spec/lib/active_remote/typecasting_spec.rb +0 -53
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14b8e2f3b79e43639dcdcb56f75b99674bcd1cb79100e01e79b5b1e5aa4f8494
4
- data.tar.gz: bd0726676290ec68c5f7de7bb0aa5a1d39553bb88c72075f7e9879b31aeb99eb
3
+ metadata.gz: 20c9373eff2820fdfaeb4eefd815a1d4cfb752e9fd388e8fd0e2d4ef2c0c5f7f
4
+ data.tar.gz: 5f66d51af2723950bad69d3870fc83685e253f5fcfd894d6ae19dd6a78c27516
5
5
  SHA512:
6
- metadata.gz: 206c1006067983f39a3944ff67a25dcd7f269f5353e19b3b0e67c3b6aa2b897f52407132e0bfcae6917da9e9b9c041fe17f081a2ae4c05d5f21558ce8ff42daa
7
- data.tar.gz: 00fc6a154121e46f47b7bf57bbc8b51ccee44166189cb289f383a4cd038909792dbe470db7062decf37cb50f4a9b7bb98a47a36ad48c2827709241e01b3d1a0e
6
+ metadata.gz: 07d671953169e1eefc9db8b26d2de3af40a39302e1423fdd7beeb212df913c46db1017aeb2dbc2d02c21cf72f0ae35639732d6af86694f0ecd7be894ae03db04
7
+ data.tar.gz: 98ee4213dcd636baab1def67ba1848469ff8592aff9334b720348830e4fd797f65e2935450fe399fafdc84261a64f2a07197323d38b743c616d4b70475f7890f
data/.rubocop.yml ADDED
@@ -0,0 +1,28 @@
1
+ # Styles are inherited from Mad Rubocop
2
+
3
+ inherit_gem:
4
+ mad_rubocop: .rubocop.yml
5
+
6
+ # Styles that are modified from the defaults
7
+ AllCops:
8
+ TargetRubyVersion: 2.5
9
+ Exclude:
10
+ - "**/*.pb.rb"
11
+
12
+ Style/BlockDelimiters:
13
+ Description: >-
14
+ Avoid using {...} for multi-line blocks (multiline chaining is always ugly).
15
+ Prefer {...} over do...end for single-line blocks.
16
+ Exclude:
17
+ - "spec/**/*"
18
+
19
+ Style/HashSyntax:
20
+ Description: >-
21
+ Prefer Ruby 1.8 hash syntax { :a => 1, :b => 2 } over 1.9 syntax { a: 1, b: 2 }.
22
+ EnforcedStyle: hash_rockets
23
+ Exclude:
24
+ - "Gemfile"
25
+
26
+ Layout/SpaceAroundOperators:
27
+ Exclude:
28
+ - "*.gemspec"
data/CHANGES.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # ActiveRemote Changes
2
2
 
3
+ 5.0.0
4
+ ----------
5
+
6
+ - Use Active Model attributes [#72]
7
+ - Use type casting from Active Model (custom types must be registered) [#71]
8
+ - Use query attributes from Active Record (string values such as 'FALSE', and '0' are now considered present) [#71]
9
+ - Drop support for Rails 4.2 (versions will match Rails version moving forward) [#71]
10
+
11
+ 3.3.1
12
+ ----------
13
+
14
+ - Fix unknown type error in Protobuf serializer [#70]
15
+
3
16
  3.3.0
4
17
  ----------
5
18
 
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in active_remote.gemspec
4
4
  gemspec
data/Rakefile CHANGED
@@ -2,12 +2,16 @@
2
2
  require "bundler/gem_tasks"
3
3
  require "protobuf/tasks"
4
4
  require "rspec/core/rake_task"
5
+ require "rubocop/rake_task"
6
+
7
+ desc "Run cops"
8
+ ::RuboCop::RakeTask.new(:rubocop)
5
9
 
6
10
  desc "Run specs"
7
- RSpec::Core::RakeTask.new(:spec)
11
+ ::RSpec::Core::RakeTask.new(:spec)
8
12
 
9
- desc "Run specs (default)"
10
- task :default, [] => :spec
13
+ desc "Run cops and specs (default)"
14
+ task :default => [:rubocop, :spec]
11
15
 
12
16
  desc "Remove protobuf definitions that have been compiled"
13
17
  task :clean do
@@ -1,5 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ $LOAD_PATH.push File.expand_path("../lib", __FILE__)
3
4
  require "active_remote/version"
4
5
 
5
6
  Gem::Specification.new do |s|
@@ -8,19 +9,19 @@ Gem::Specification.new do |s|
8
9
  s.authors = ["Adam Hutchison"]
9
10
  s.email = ["liveh2o@gmail.com"]
10
11
  s.homepage = "https://github.com/liveh2o/active_remote"
11
- s.summary = %q{Active Record for your platform}
12
- s.description = %q{Active Remote provides Active Record-like object-relational mapping over RPC. It was written for use with Google Protocol Buffers, but could be extended to use any RPC data format.}
12
+ s.summary = "Active Record for your platform"
13
+ s.description = "Active Remote provides Active Record-like object-relational mapping over RPC. It was written for use with Google Protocol Buffers, but could be extended to use any RPC data format."
13
14
 
14
15
  s.files = `git ls-files`.split("\n")
15
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
17
18
  s.require_paths = ["lib"]
18
19
 
19
20
  ##
20
21
  # Dependencies
21
22
  #
22
- s.add_dependency "activemodel", ">= 4.0", "< 5.2"
23
- s.add_dependency "activesupport", ">= 4.0"
23
+ s.add_dependency "activemodel", ">= 5.0", "< 5.2"
24
+ s.add_dependency "activesupport", ">= 5.0"
24
25
  s.add_dependency "protobuf", ">= 3.0"
25
26
 
26
27
  ##
@@ -30,6 +31,7 @@ Gem::Specification.new do |s|
30
31
  s.add_development_dependency "rspec", ">= 3.3.0"
31
32
  s.add_development_dependency "rspec-its"
32
33
  s.add_development_dependency "rspec-pride", ">= 3.1.0"
34
+ s.add_development_dependency "mad_rubocop"
33
35
  s.add_development_dependency "pry"
34
36
  s.add_development_dependency "protobuf-rspec", ">= 1.1.2"
35
37
  s.add_development_dependency "simplecov"
data/lib/active_remote.rb CHANGED
@@ -1,11 +1,12 @@
1
- require 'active_model'
2
- require 'active_support'
3
- require 'protobuf'
1
+ require "active_model"
2
+ require "active_support"
3
+ require "active_support/core_ext"
4
+ require "protobuf"
4
5
 
5
- require 'active_remote/base'
6
- require 'active_remote/config'
7
- require 'active_remote/errors'
8
- require 'active_remote/version'
6
+ require "active_remote/base"
7
+ require "active_remote/config"
8
+ require "active_remote/errors"
9
+ require "active_remote/version"
9
10
 
10
11
  module ActiveRemote
11
12
  def self.config
@@ -16,4 +17,4 @@ module ActiveRemote
16
17
  config
17
18
  end
18
19
 
19
- require 'active_remote/railtie' if defined?(Rails)
20
+ require "active_remote/railtie" if defined?(Rails)
@@ -33,12 +33,12 @@ module ActiveRemote
33
33
  # end
34
34
  # end
35
35
  #
36
- def belongs_to(belongs_to_klass, options={})
36
+ def belongs_to(belongs_to_klass, options = {})
37
37
  perform_association(belongs_to_klass, options) do |klass, object|
38
38
  foreign_key = options.fetch(:foreign_key) { :"#{klass.name.demodulize.underscore}_guid" }
39
39
  search_hash = {}
40
40
  search_hash[:guid] = object.read_attribute(foreign_key)
41
- search_hash[options[:scope]] = object.read_attribute(options[:scope]) if options.has_key?(:scope)
41
+ search_hash[options[:scope]] = object.read_attribute(options[:scope]) if options.key?(:scope)
42
42
 
43
43
  search_hash.values.any?(&:nil?) ? nil : klass.search(search_hash).first
44
44
  end
@@ -74,17 +74,17 @@ module ActiveRemote
74
74
  # end
75
75
  # end
76
76
  #
77
- def has_many(has_many_class, options={})
77
+ def has_many(has_many_class, options = {})
78
78
  perform_association(has_many_class, options) do |klass, object|
79
79
  foreign_key = options.fetch(:foreign_key) { :"#{object.class.name.demodulize.underscore}_guid" }
80
80
  search_hash = {}
81
81
  search_hash[foreign_key] = object.guid
82
- search_hash[options[:scope]] = object.read_attribute(options[:scope]) if options.has_key?(:scope)
82
+ search_hash[options[:scope]] = object.read_attribute(options[:scope]) if options.key?(:scope)
83
83
 
84
84
  search_hash.values.any?(&:nil?) ? [] : klass.search(search_hash)
85
85
  end
86
86
 
87
- options.merge!(:has_many => true)
87
+ options[:has_many] = true
88
88
  create_setter_method(has_many_class, options)
89
89
  end
90
90
 
@@ -115,12 +115,12 @@ module ActiveRemote
115
115
  # end
116
116
  # end
117
117
  #
118
- def has_one(has_one_klass, options={})
118
+ def has_one(has_one_klass, options = {})
119
119
  perform_association(has_one_klass, options) do |klass, object|
120
120
  foreign_key = options.fetch(:foreign_key) { :"#{object.class.name.demodulize.underscore}_guid" }
121
121
  search_hash = {}
122
122
  search_hash[foreign_key] = object.guid
123
- search_hash[options[:scope]] = object.read_attribute(options[:scope]) if options.has_key?(:scope)
123
+ search_hash[options[:scope]] = object.read_attribute(options[:scope]) if options.key?(:scope)
124
124
 
125
125
  search_hash.values.any?(&:nil?) ? nil : klass.search(search_hash).first
126
126
  end
@@ -135,29 +135,27 @@ module ActiveRemote
135
135
 
136
136
  private
137
137
 
138
- def create_setter_method(associated_klass, options={})
138
+ def create_setter_method(associated_klass, options = {})
139
139
  writer_method = "#{associated_klass}=".to_sym
140
140
  define_method(writer_method) do |new_value|
141
141
  raise "New value must be an array" if options[:has_many] == true && new_value.class != Array
142
- klass_name = options.fetch(:class_name){ associated_klass }
143
- klass = klass_name.to_s.classify.constantize
144
142
 
145
143
  instance_variable_set(:"@#{new_value.class.name.demodulize.underscore}", new_value)
146
144
  new_value
147
145
  end
148
146
  end
149
147
 
150
- def perform_association(associated_klass, options={})
148
+ def perform_association(associated_klass, options = {})
151
149
  define_method(associated_klass) do
152
- klass_name = options.fetch(:class_name){ associated_klass }
150
+ klass_name = options.fetch(:class_name) { associated_klass }
153
151
  klass = klass_name.to_s.classify.constantize
154
152
 
155
- self.class.validate_scoped_attributes(klass, self.class, options) if options.has_key?(:scope)
153
+ self.class.validate_scoped_attributes(klass, self.class, options) if options.key?(:scope)
156
154
 
157
155
  value = instance_variable_get(:"@#{associated_klass}")
158
156
 
159
157
  unless value
160
- value = yield( klass, self )
158
+ value = yield(klass, self)
161
159
  instance_variable_set(:"@#{associated_klass}", value)
162
160
  end
163
161
 
@@ -1,4 +1,4 @@
1
- require "active_remote/type"
1
+ require "active_model/type"
2
2
 
3
3
  module ActiveRemote
4
4
  # Represents an attribute for reflection
@@ -55,17 +55,19 @@ module ActiveRemote
55
55
  # @return [ActiveAttr::AttributeDefinition]
56
56
  #
57
57
  # @since 0.2.0
58
- def initialize(name, type = :unknown, **options)
58
+ def initialize(name, type = :value, **options)
59
59
  raise TypeError, "can't convert #{name.class} into Symbol" unless name.respond_to? :to_sym
60
60
  @name = name.to_sym
61
+ @type = ::ActiveModel::Type.lookup(type)
61
62
  @options = options
62
- @options[:typecaster] = ::ActiveRemote::Type.lookup(type) unless type == :unknown
63
+ end
64
+
65
+ def from_rpc(value)
66
+ type.deserialize(value)
67
+ end
63
68
 
64
- if @options[:type]
65
- typecaster = ::ActiveRemote::Typecasting::TYPECASTER_MAP[@options[:type]]
66
- fail ::ActiveRemote::UnknownType unless typecaster
67
- @options[:typecaster] = typecaster
68
- end
69
+ def from_user(value)
70
+ type.cast(value)
69
71
  end
70
72
 
71
73
  # Returns the code that would generate the attribute definition
@@ -88,9 +90,7 @@ module ActiveRemote
88
90
  # @return [String] the attribute name
89
91
  #
90
92
  # @since 0.2.0
91
- def to_s
92
- name.to_s
93
- end
93
+ delegate :to_s, :to => :name
94
94
 
95
95
  # The attribute name
96
96
  #
@@ -101,10 +101,12 @@ module ActiveRemote
101
101
  name
102
102
  end
103
103
 
104
- protected
104
+ protected
105
105
 
106
106
  # The attribute options
107
107
  # @since 0.5.0
108
108
  attr_reader :options, :type
109
109
  end
110
+
111
+ ::ActiveModel::Type.register(:value, ::ActiveModel::Type::Value)
110
112
  end
@@ -68,7 +68,7 @@ module ActiveRemote
68
68
  # Write an attribute to the attributes hash
69
69
  #
70
70
  def attribute=(name, value)
71
- @attributes[name] = value
71
+ @attributes[name] = self.class.attributes[name].from_user(value)
72
72
  end
73
73
 
74
74
  def attribute_method?(attr_name)
@@ -88,9 +88,9 @@ module ActiveRemote
88
88
  # @example Define an attribute.
89
89
  # attribute :name
90
90
  #
91
- def attribute(name, options={})
92
- if dangerous_attribute_method_name = dangerous_attribute?(name)
93
- raise ::ActiveRemote::DangerousAttributeError, %{an attribute method named "#{dangerous_attribute_method_name}" would conflict with an existing method}
91
+ def attribute(name, options = {})
92
+ if (dangerous_attribute_method_name = dangerous_attribute?(name))
93
+ raise ::ActiveRemote::DangerousAttributeError, %(an attribute method named "#{dangerous_attribute_method_name}" would conflict with an existing method)
94
94
  else
95
95
  attribute!(name, options)
96
96
  end
@@ -107,7 +107,7 @@ module ActiveRemote
107
107
  # @example Define a dangerous attribute.
108
108
  # attribute! :timeout
109
109
  #
110
- def attribute!(name, options={})
110
+ def attribute!(name, options = {})
111
111
  ::ActiveRemote::AttributeDefinition.new(name, options).tap do |attribute_definition|
112
112
  attribute_name = attribute_definition.name.to_s
113
113
  # Force active model to generate attribute methods
@@ -164,7 +164,7 @@ module ActiveRemote
164
164
  #
165
165
  def inspect
166
166
  inspected_attributes = attribute_names.sort
167
- attributes_list = "(#{inspected_attributes.join(", ")})" unless inspected_attributes.empty?
167
+ attributes_list = "(#{inspected_attributes.join(', ')})" unless inspected_attributes.empty?
168
168
  "#{name}#{attributes_list}"
169
169
  end
170
170
 
@@ -1,33 +1,28 @@
1
- require 'active_model/callbacks'
2
-
3
- require 'active_remote/association'
4
- require 'active_remote/attribute_assignment'
5
- require 'active_remote/attribute_definition'
6
- require 'active_remote/attributes'
7
- require 'active_remote/config'
8
- require 'active_remote/dirty'
9
- require 'active_remote/dsl'
10
- require 'active_remote/integration'
11
- require 'active_remote/persistence'
12
- require 'active_remote/primary_key'
13
- require 'active_remote/query_attributes'
14
- require 'active_remote/rpc'
15
- require 'active_remote/scope_keys'
16
- require 'active_remote/search'
17
- require 'active_remote/serialization'
18
- require 'active_remote/typecasting'
19
- require 'active_remote/validations'
1
+ require "active_model/callbacks"
2
+
3
+ require "active_remote/association"
4
+ require "active_remote/attribute_definition"
5
+ require "active_remote/attributes"
6
+ require "active_remote/config"
7
+ require "active_remote/dirty"
8
+ require "active_remote/dsl"
9
+ require "active_remote/integration"
10
+ require "active_remote/persistence"
11
+ require "active_remote/primary_key"
12
+ require "active_remote/query_attributes"
13
+ require "active_remote/rpc"
14
+ require "active_remote/scope_keys"
15
+ require "active_remote/search"
16
+ require "active_remote/serialization"
17
+ require "active_remote/validations"
20
18
 
21
19
  module ActiveRemote
22
20
  class Base
23
21
  extend ::ActiveModel::Callbacks
24
- extend ::ActiveModel::Naming
25
22
 
26
- include ::ActiveModel::Conversion
27
- include ::ActiveModel::Validations
23
+ include ::ActiveModel::Model
28
24
 
29
25
  include ::ActiveRemote::Association
30
- include ::ActiveRemote::AttributeAssignment
31
26
  include ::ActiveRemote::Attributes
32
27
  include ::ActiveRemote::DSL
33
28
  include ::ActiveRemote::Integration
@@ -38,7 +33,6 @@ module ActiveRemote
38
33
  include ::ActiveRemote::ScopeKeys
39
34
  include ::ActiveRemote::Search
40
35
  include ::ActiveRemote::Serialization
41
- include ::ActiveRemote::Typecasting
42
36
 
43
37
  # Overrides some methods, providing support for dirty tracking,
44
38
  # so it needs to be included last.
@@ -48,8 +42,6 @@ module ActiveRemote
48
42
  include ::ActiveRemote::Validations
49
43
  include ::ActiveModel::Validations::Callbacks
50
44
 
51
- attr_reader :last_request, :last_response
52
-
53
45
  define_model_callbacks :initialize, :only => :after
54
46
 
55
47
  def initialize(attributes = {})
@@ -78,7 +70,8 @@ module ActiveRemote
78
70
  end
79
71
 
80
72
  def freeze
81
- @attributes.freeze; self
73
+ @attributes.freeze
74
+ self
82
75
  end
83
76
 
84
77
  def frozen?
@@ -1,4 +1,4 @@
1
- require 'active_support/ordered_options'
1
+ require "active_support/ordered_options"
2
2
 
3
3
  module ActiveRemote
4
4
  class Config < ::ActiveSupport::OrderedOptions
@@ -1,4 +1,4 @@
1
- require 'active_model/dirty'
1
+ require "active_model/dirty"
2
2
 
3
3
  # Overrides persistence methods, providing support for dirty tracking.
4
4
  #
@@ -32,7 +32,7 @@ module ActiveRemote
32
32
  # Override #save to store changes as previous changes then clear them.
33
33
  #
34
34
  def save(*)
35
- if status = super
35
+ if (status = super)
36
36
  @previously_changed = changes
37
37
  changed_attributes.clear
38
38
  end
@@ -49,7 +49,7 @@ module ActiveRemote
49
49
  end
50
50
  end
51
51
 
52
- def skip_dirty_tracking(&block)
52
+ def skip_dirty_tracking
53
53
  disable_dirty_tracking
54
54
 
55
55
  yield