deserializer 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile +3 -8
  4. data/Gemfile.lock +12 -91
  5. data/README.md +30 -7
  6. data/Rakefile +2 -28
  7. data/deserializer.gemspec +2 -0
  8. data/lib/deserializer/base.rb +4 -4
  9. data/lib/deserializer/version.rb +1 -1
  10. data/test/lib/deserializers/deserializers.rb +75 -0
  11. data/test/minitest_helper.rb +14 -0
  12. data/test/unit/deserializer_error_test.rb +12 -0
  13. data/test/unit/deserializer_test.rb +100 -0
  14. metadata +39 -91
  15. data/test/deserializer_test.rb +0 -7
  16. data/test/dummy/README.rdoc +0 -0
  17. data/test/dummy/Rakefile +0 -6
  18. data/test/dummy/app/assets/images/.keep +0 -0
  19. data/test/dummy/app/assets/javascripts/application.js +0 -13
  20. data/test/dummy/app/assets/stylesheets/application.css +0 -15
  21. data/test/dummy/app/controllers/application_controller.rb +0 -5
  22. data/test/dummy/app/controllers/concerns/.keep +0 -0
  23. data/test/dummy/app/helpers/application_helper.rb +0 -2
  24. data/test/dummy/app/mailers/.keep +0 -0
  25. data/test/dummy/app/models/.keep +0 -0
  26. data/test/dummy/app/models/concerns/.keep +0 -0
  27. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  28. data/test/dummy/bin/bundle +0 -3
  29. data/test/dummy/bin/rails +0 -4
  30. data/test/dummy/bin/rake +0 -4
  31. data/test/dummy/bin/setup +0 -29
  32. data/test/dummy/config.ru +0 -4
  33. data/test/dummy/config/application.rb +0 -26
  34. data/test/dummy/config/boot.rb +0 -5
  35. data/test/dummy/config/database.yml +0 -25
  36. data/test/dummy/config/environment.rb +0 -5
  37. data/test/dummy/config/environments/development.rb +0 -41
  38. data/test/dummy/config/environments/production.rb +0 -79
  39. data/test/dummy/config/environments/test.rb +0 -42
  40. data/test/dummy/config/initializers/assets.rb +0 -11
  41. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  42. data/test/dummy/config/initializers/cookies_serializer.rb +0 -3
  43. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  44. data/test/dummy/config/initializers/inflections.rb +0 -16
  45. data/test/dummy/config/initializers/mime_types.rb +0 -4
  46. data/test/dummy/config/initializers/session_store.rb +0 -3
  47. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  48. data/test/dummy/config/locales/en.yml +0 -23
  49. data/test/dummy/config/routes.rb +0 -4
  50. data/test/dummy/config/secrets.yml +0 -22
  51. data/test/dummy/lib/assets/.keep +0 -0
  52. data/test/dummy/log/.keep +0 -0
  53. data/test/dummy/public/404.html +0 -67
  54. data/test/dummy/public/422.html +0 -67
  55. data/test/dummy/public/500.html +0 -66
  56. data/test/dummy/public/favicon.ico +0 -0
  57. data/test/integration/navigation_test.rb +0 -10
  58. data/test/test_helper.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0dd737dc7e4c34c7238b6dc22a16077e17c22d3
4
- data.tar.gz: 1d3b4c23174de67667241f4dc91109222bc61d41
3
+ metadata.gz: 16497e6608bbeeb126c16fbb2040022ef43c2a2e
4
+ data.tar.gz: de87e7fd93f070278c1b0e3672edbc4363be0560
5
5
  SHA512:
6
- metadata.gz: d9c5cde9d336f5568761d3d91b39cc697dead376ac6d7f3260da7901aaac333961a71fe7ff1fb0eb7e72446de88b9282e3c850b9c3198aa89fbb92404f2713f0
7
- data.tar.gz: bcedd5145f9015da536d2927bed7fcca82d0b39796e78dc7fd6877da719ce2b9f1e5e31a7d5fd2b60c34b4dd5e46fa4d720829046f4eca2c8691a7fdb07e4fa2
6
+ metadata.gz: b0c1582c067f86f892705e7b7fd73f7ae42dc548354a22170c36b64868febc22a27cba2d306f0130f177062ceb84f548028900d7bb2a086c7be19ec953e7b0ae
7
+ data.tar.gz: 4883819b21807f2915d8887688786aa3f0aecdaa8c411b750e482e6db14ca8e2a68ea041848424a86a9253b6d885902a4db8e881b4ba43beed332b094226543d
data/.gitignore CHANGED
@@ -6,3 +6,4 @@ test/dummy/db/*.sqlite3-journal
6
6
  test/dummy/log/*.log
7
7
  test/dummy/tmp/
8
8
  test/dummy/.sass-cache
9
+ coverage
data/Gemfile CHANGED
@@ -5,11 +5,6 @@ source 'https://rubygems.org'
5
5
  # development dependencies will be added by default to the :development group.
6
6
  gemspec
7
7
 
8
- # Declare any dependencies that are still in development here instead of in
9
- # your gemspec. These might include edge Rails or gems from your path or
10
- # Git. Remember to move these dependencies to your gemspec before releasing
11
- # your gem to rubygems.org.
12
-
13
- # To use a debugger
14
- # gem 'byebug', group: [:development, :test]
15
-
8
+ gem 'rake'
9
+ gem 'simplecov', :group => :test
10
+ gem 'minitest', :group => :test
data/Gemfile.lock CHANGED
@@ -1,106 +1,27 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- deserializer (0.0.1)
5
- rails (~> 4.2.1)
4
+ deserializer (0.1.0)
6
5
 
7
6
  GEM
8
7
  remote: https://rubygems.org/
9
8
  specs:
10
- actionmailer (4.2.3)
11
- actionpack (= 4.2.3)
12
- actionview (= 4.2.3)
13
- activejob (= 4.2.3)
14
- mail (~> 2.5, >= 2.5.4)
15
- rails-dom-testing (~> 1.0, >= 1.0.5)
16
- actionpack (4.2.3)
17
- actionview (= 4.2.3)
18
- activesupport (= 4.2.3)
19
- rack (~> 1.6)
20
- rack-test (~> 0.6.2)
21
- rails-dom-testing (~> 1.0, >= 1.0.5)
22
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
23
- actionview (4.2.3)
24
- activesupport (= 4.2.3)
25
- builder (~> 3.1)
26
- erubis (~> 2.7.0)
27
- rails-dom-testing (~> 1.0, >= 1.0.5)
28
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
29
- activejob (4.2.3)
30
- activesupport (= 4.2.3)
31
- globalid (>= 0.3.0)
32
- activemodel (4.2.3)
33
- activesupport (= 4.2.3)
34
- builder (~> 3.1)
35
- activerecord (4.2.3)
36
- activemodel (= 4.2.3)
37
- activesupport (= 4.2.3)
38
- arel (~> 6.0)
39
- activesupport (4.2.3)
40
- i18n (~> 0.7)
41
- json (~> 1.7, >= 1.7.7)
42
- minitest (~> 5.1)
43
- thread_safe (~> 0.3, >= 0.3.4)
44
- tzinfo (~> 1.1)
45
- arel (6.0.2)
46
- builder (3.2.2)
47
- erubis (2.7.0)
48
- globalid (0.3.5)
49
- activesupport (>= 4.1.0)
50
- i18n (0.7.0)
51
- json (1.8.3)
52
- loofah (2.0.2)
53
- nokogiri (>= 1.5.9)
54
- mail (2.6.3)
55
- mime-types (>= 1.16, < 3)
56
- mime-types (2.6.1)
57
- mini_portile (0.6.2)
9
+ docile (1.1.5)
58
10
  minitest (5.7.0)
59
- nokogiri (1.6.6.2)
60
- mini_portile (~> 0.6.0)
61
- rack (1.6.4)
62
- rack-test (0.6.3)
63
- rack (>= 1.0)
64
- rails (4.2.3)
65
- actionmailer (= 4.2.3)
66
- actionpack (= 4.2.3)
67
- actionview (= 4.2.3)
68
- activejob (= 4.2.3)
69
- activemodel (= 4.2.3)
70
- activerecord (= 4.2.3)
71
- activesupport (= 4.2.3)
72
- bundler (>= 1.3.0, < 2.0)
73
- railties (= 4.2.3)
74
- sprockets-rails
75
- rails-deprecated_sanitizer (1.0.3)
76
- activesupport (>= 4.2.0.alpha)
77
- rails-dom-testing (1.0.6)
78
- activesupport (>= 4.2.0.beta, < 5.0)
79
- nokogiri (~> 1.6.0)
80
- rails-deprecated_sanitizer (>= 1.0.1)
81
- rails-html-sanitizer (1.0.2)
82
- loofah (~> 2.0)
83
- railties (4.2.3)
84
- actionpack (= 4.2.3)
85
- activesupport (= 4.2.3)
86
- rake (>= 0.8.7)
87
- thor (>= 0.18.1, < 2.0)
11
+ multi_json (1.11.1)
88
12
  rake (10.4.2)
89
- sprockets (3.2.0)
90
- rack (~> 1.0)
91
- sprockets-rails (2.3.2)
92
- actionpack (>= 3.0)
93
- activesupport (>= 3.0)
94
- sprockets (>= 2.8, < 4.0)
95
- sqlite3 (1.3.10)
96
- thor (0.19.1)
97
- thread_safe (0.3.5)
98
- tzinfo (1.2.2)
99
- thread_safe (~> 0.1)
13
+ simplecov (0.9.2)
14
+ docile (~> 1.1.0)
15
+ multi_json (~> 1.0)
16
+ simplecov-html (~> 0.9.0)
17
+ simplecov-html (0.9.0)
100
18
 
101
19
  PLATFORMS
102
20
  ruby
103
21
 
104
22
  DEPENDENCIES
23
+ bundler (~> 1.6)
105
24
  deserializer!
106
- sqlite3
25
+ minitest
26
+ rake
27
+ simplecov
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Deserializer
2
2
 
3
- Deserialization of complex parameters into a hash that an AR model can take.
3
+ Hash transformation and sanitization. Deserialization of complex parameters into a hash that an AR model can take.
4
4
 
5
5
  Lets you have a reverse ActiveModel::Sereializer-like interface that allows for easy create and update without having to write heavy controllers.
6
6
 
@@ -141,7 +141,7 @@ For example with params of `{"title" => "lorem", "text" => "ipsum"}` this desrer
141
141
 
142
142
  #### has_one
143
143
  NOTE: This is the only association currently supported by `Deserializer`.
144
- `has_one` expects the param and its deserializer. So for params `{"ratings" => {"taste" => "bad", "smell" => "good"}}`
144
+ `has_one` expects the param and its deserializer.
145
145
  ```ruby
146
146
  class DishDeserializer < Deserializer::Base
147
147
  # probably other stuff
@@ -153,7 +153,7 @@ class RatingsDeserializer < Deserializer::Base
153
153
  :smell
154
154
  end
155
155
  ```
156
- you would get `{ratings: {taste: "bad", smell: "good"}}`
156
+ So for params `{"ratings" => {"taste" => "bad", "smell" => "good"}}` you would get `{ratings: {taste: "bad", smell: "good"}}`
157
157
 
158
158
  #### Overriding Attribute Methods
159
159
  So let's say in the example above, your internal representation of ratings inside `Dish` is actually called `scores`, you can do
@@ -166,7 +166,7 @@ class DishDeserializer < Deserializer::Base
166
166
  end
167
167
  end
168
168
  ```
169
- which will give you `{scores: {taste: "bad", smell: "good"}}`
169
+ which will give you `{scores: {taste: "bad", smell: "good"}}` for params `{"ratings" => {"taste" => "bad", "smell" => "good"}}`
170
170
 
171
171
  or, if you want to deserialize `ratings` into your `dish` object, you can use `object`
172
172
 
@@ -179,7 +179,7 @@ class DishDeserializer < Deserializer::Base
179
179
  end
180
180
  end
181
181
  ```
182
- which will give you `{taste: "bad", smell: "good"}`
182
+ which will give you `{taste: "bad", smell: "good"}` for params `{"ratings" => {"taste" => "bad", "smell" => "good"}}`
183
183
 
184
184
  or you can deserialize into another subobject by doing
185
185
  ```ruby
@@ -188,7 +188,7 @@ class DishDeserializer < Deserializer::Base
188
188
  has_one :ratings, deserializer: RatingsDeserializer
189
189
 
190
190
  def colors
191
- object[:ratings]
191
+ :ratings
192
192
  end
193
193
  end
194
194
  ```
@@ -263,6 +263,29 @@ class DishReviewsController < YourApiController::Base
263
263
  end
264
264
  end
265
265
 
266
- # rest of RUD
266
+ # RUD
267
267
  end
268
268
  ```
269
+
270
+ ## Installation
271
+
272
+ Add this line to your application's Gemfile:
273
+
274
+ gem 'deserializer'
275
+
276
+ And then execute:
277
+
278
+ $ bundle
279
+
280
+ Or install it yourself as:
281
+
282
+ $ gem install deserializer
283
+
284
+
285
+ ## Contributing
286
+
287
+ 1. Fork it ( https://github.com/[my-github-username]/deserializer/fork )
288
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
289
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
290
+ 4. Push to the branch (`git push origin my-new-feature`)
291
+ 5. Create a new Pull Request
data/Rakefile CHANGED
@@ -1,31 +1,6 @@
1
- begin
2
- require 'bundler/setup'
3
- rescue LoadError
4
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
- end
6
-
7
- require 'rdoc/task'
8
-
9
- RDoc::Task.new(:rdoc) do |rdoc|
10
- rdoc.rdoc_dir = 'rdoc'
11
- rdoc.title = 'Deserializer'
12
- rdoc.options << '--line-numbers'
13
- rdoc.rdoc_files.include('README.rdoc')
14
- rdoc.rdoc_files.include('lib/**/*.rb')
15
- end
16
-
17
- APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
- load 'rails/tasks/engine.rake'
19
-
20
-
21
- load 'rails/tasks/statistics.rake'
22
-
23
-
24
-
25
- Bundler::GemHelper.install_tasks
26
-
27
1
  require 'rake/testtask'
28
2
 
3
+
29
4
  Rake::TestTask.new(:test) do |t|
30
5
  t.libs << 'lib'
31
6
  t.libs << 'test'
@@ -33,5 +8,4 @@ Rake::TestTask.new(:test) do |t|
33
8
  t.verbose = false
34
9
  end
35
10
 
36
-
37
- task default: :test
11
+ task default: :test
data/deserializer.gemspec CHANGED
@@ -18,4 +18,6 @@ Gem::Specification.new do |s|
18
18
  s.test_files = s.files.grep(%r{^(test|s|features)/})
19
19
  s.require_paths = ["lib"]
20
20
 
21
+ s.add_development_dependency "bundler", "~> 1.6"
22
+ s.add_development_dependency "rake"
21
23
  end
@@ -53,7 +53,7 @@ module Deserializer
53
53
  def deserialize
54
54
  self.class.attrs.each do |param_key, object_key|
55
55
  # don't bother with keys that aren't in params
56
- next unless params[param_key]
56
+ next unless params.has_key? param_key
57
57
 
58
58
  # this checks if the object_key is a class that inherits from Deserializer
59
59
  if object_key.is_a?(Class) && object_key < Deserializer::Base
@@ -76,7 +76,7 @@ module Deserializer
76
76
  raise DeserializerError, class: self.class, message: "params cannot be nil"
77
77
  end
78
78
 
79
- self.params = params.deep_symbolize_keys
79
+ self.params = params
80
80
  self.object = object
81
81
  end
82
82
 
@@ -86,10 +86,10 @@ module Deserializer
86
86
  target = self.send( association )
87
87
 
88
88
  unless target.is_a? Hash
89
- target = object[target] = {}
89
+ target = object[target] ||= {}
90
90
  end
91
91
  else
92
- target = object[association] = {}
92
+ target = object[association] ||= {}
93
93
  end
94
94
 
95
95
  deserializer.new( target, params[association] ).deserialize
@@ -1,3 +1,3 @@
1
1
  module Deserializer
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,75 @@
1
+ class BasicDeserializer < Deserializer::Base
2
+ attributes :user_id,
3
+ :text
4
+ end
5
+
6
+ class AttributeDeserializer < Deserializer::Base
7
+ attribute :user_id, key: :user
8
+ attribute :text
9
+ end
10
+
11
+ class VanillaHasOneDeserializer < Deserializer::Base
12
+ attribute :internal, key: :external
13
+
14
+ has_one :params, deserializer: BasicDeserializer
15
+
16
+ end
17
+
18
+ class HasOneWithTargetDeserializer < Deserializer::Base
19
+ attribute :internal, key: :external
20
+
21
+ has_one :thing, deserializer: ::BasicDeserializer
22
+
23
+ def thing
24
+ :user_info
25
+ end
26
+ end
27
+
28
+ class OtherThingDeserializer < Deserializer::Base
29
+ attributes :attr1,
30
+ :attr2
31
+ end
32
+
33
+ class TricksyDeserializer < Deserializer::Base
34
+ attribute :internal, key: :external
35
+
36
+ has_one :thing, deserializer: ::BasicDeserializer
37
+
38
+ has_one :other_thing, deserializer: ::OtherThingDeserializer
39
+
40
+ def thing
41
+ :user_info
42
+ end
43
+
44
+ def other_thing
45
+ :user_info
46
+ end
47
+ end
48
+
49
+ class ExtraTricksyDeserializer < Deserializer::Base
50
+ attribute :internal, key: :external
51
+
52
+ has_one :thing, deserializer: ::BasicDeserializer
53
+
54
+ has_one :other_thing, deserializer: ::OtherThingDeserializer
55
+
56
+ def other_thing
57
+ :thing
58
+ end
59
+ end
60
+
61
+ class HasOneWithObjectTargetDeserializer < Deserializer::Base
62
+ attribute :internal, key: :external
63
+
64
+ has_one :thing, deserializer: ::BasicDeserializer
65
+
66
+ has_one :other_thing, deserializer: ::OtherThingDeserializer
67
+
68
+ def thing
69
+ object
70
+ end
71
+
72
+ def other_thing
73
+ object
74
+ end
75
+ end
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+
6
+ require 'deserializer'
7
+
8
+ test_libs_path = File.expand_path("../lib", __FILE__)
9
+ Dir[File.join(test_libs_path, "/**/*.rb")].each do |file|
10
+ puts file
11
+ require file
12
+ end
13
+
14
+ require 'minitest/autorun'
@@ -0,0 +1,12 @@
1
+ require 'minitest_helper'
2
+
3
+ class DeserializerErrorTest < Minitest::Test
4
+
5
+ def test_error_contains_message
6
+ begin
7
+ BasicDeserializer.has_one :lolnope
8
+ rescue => e
9
+ assert_equal "BasicDeserializer: has_one associations need a deserilaizer", e.message
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,100 @@
1
+ require 'minitest_helper'
2
+
3
+ class DeserializerTest < Minitest::Test
4
+
5
+ def setup
6
+ @params = { user: 6,
7
+ user_id: 6,
8
+ text: "text",
9
+ i_sholdnt_be_here: :should_i_now}
10
+
11
+ end
12
+
13
+ def test_no_nil_params
14
+ assert_raises Deserializer::DeserializerError do
15
+ BasicDeserializer.from_params nil
16
+ end
17
+ end
18
+
19
+ def test_from_params
20
+ assert_equal ({user_id: 6, text: "text"}) , BasicDeserializer.from_params( @params )
21
+ end
22
+
23
+ def test_permitted_params
24
+ assert_equal [:user_id, :text] , BasicDeserializer.permitted_params
25
+ end
26
+
27
+ def test_does_not_eat_false_or_nil_values
28
+ params = { user_id: nil,
29
+ text: false,
30
+ i_sholdnt_be_here: :should_i_now }
31
+
32
+ assert_equal ({user_id: nil, text: false}) , BasicDeserializer.from_params( params )
33
+ end
34
+
35
+ def test_permitted_params_with_attr_key
36
+ assert_equal [:user, :text] , AttributeDeserializer.permitted_params
37
+ end
38
+
39
+ def test_attribute
40
+ assert_equal "text", AttributeDeserializer.from_params( @params )[:text]
41
+ end
42
+
43
+ def test_attribute_with_key
44
+ assert_equal 6, AttributeDeserializer.from_params( @params )[:user_id]
45
+ end
46
+
47
+ def test_undefined_params_dont_come_through
48
+ assert_equal nil, AttributeDeserializer.from_params( @params )[:i_shouldnt_be_here]
49
+ end
50
+
51
+ def test_has_one
52
+ expected = { internal: :thing, params: { user_id: 6, text: "text" }}
53
+ params = { external: :thing, params: @params }
54
+ assert_equal expected, VanillaHasOneDeserializer.from_params( params )
55
+ end
56
+
57
+ def test_has_one_requires_deserializer
58
+ assert_raises Deserializer::DeserializerError do
59
+ BasicDeserializer.has_one :splosion
60
+ end
61
+ end
62
+
63
+ def test_has_one_with_key_target
64
+ expected = { internal: :thing, user_info: { user_id: 6, text: "text" }}
65
+ params = { external: :thing, thing: @params }
66
+ assert_equal expected, HasOneWithTargetDeserializer.from_params( params )
67
+ end
68
+
69
+ def test_can_combine_two_has_ones_into_a_third_key
70
+ expected = { internal: :thing, user_info: { user_id: 6, text: "text", attr1: :blah, attr2: :blech }}
71
+ params = { external: :thing, thing: @params, other_thing: {attr1: :blah, attr2: :blech} }
72
+ assert_equal expected, TricksyDeserializer.from_params( params )
73
+ end
74
+
75
+
76
+ def test_can_merge_a_has_one_into_another
77
+ expected = { internal: :thing, thing: { user_id: 6, text: "text", attr1: :blah, attr2: :blech }}
78
+ params = { external: :thing, thing: @params, other_thing: {attr1: :blah, attr2: :blech} }
79
+ assert_equal expected, ExtraTricksyDeserializer.from_params( params )
80
+ end
81
+
82
+
83
+ def test_merge_has_one_into_object
84
+ expected = { internal: :thing, user_id: 6, text: "text", attr1: :blah, attr2: :blech }
85
+ params = { external: :thing, thing: @params, other_thing: {attr1: :blah, attr2: :blech} }
86
+ assert_equal expected, HasOneWithObjectTargetDeserializer.from_params( params )
87
+ end
88
+
89
+ def test_has_many_unpermitted
90
+ assert_raises Deserializer::DeserializerError do
91
+ BasicDeserializer.has_many :explodies
92
+ end
93
+ end
94
+
95
+ def test_belongs_to_unpermitted
96
+ assert_raises Deserializer::DeserializerError do
97
+ BasicDeserializer.belongs_to :explody
98
+ end
99
+ end
100
+ end