scripper 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d752f7cd07c8c414d9bf1d2ee6f15887a70f19b2cbbbe966e45231b004890242
4
- data.tar.gz: c6e5d97ba7e3a3e09632087cdabeefb50e39a483adbbdfec8f2605c5f56cae05
3
+ metadata.gz: 23ae9ed50d0a9424206847fc397358c0e496b45f0ffec8627b0710043fc863de
4
+ data.tar.gz: 7308b47894cf9d3c430fc21586827e00e6a7eaa249cc65ae7a779c4fa8f53a59
5
5
  SHA512:
6
- metadata.gz: 6f413514b8b02f4a227d2768561eaa7539b53fe404fe1695b1539d434f210ad142dfed2168ad0f712ad9b738216067a055a64ee1144a231a5b779174cc9e1fa3
7
- data.tar.gz: ddc16909455ccac6290b39abda1b79429e2147ad5648ff6bef2d1e74e517366dd64434a2fab982572067b4bcae1281850b283e4bcb47f1398fbd4a87f210d601
6
+ metadata.gz: 1810dd1a45876ac927cb652b742fa3b63ecbedbf086ed670a258df9b6707ea539e4dff58f7361f44e13a504cf90e170e40658a6336469776f5f5270abe287278
7
+ data.tar.gz: 24d08010518e9232d7be7ffcc6d261060803e4bf4f5416e836fa514603fe8fd87e6c56080df3a923e135924615bb665a0a0ae4df8e9b2c445405f5b49f687885
data/.gitignore CHANGED
@@ -1,13 +1,14 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
-
10
- # rspec failure tracking
11
- .rspec_status
12
-
13
- /scripper-*.gem
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /Gemfile.lock
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+
14
+ /scripper-*.gem
data/.rspec CHANGED
@@ -1,3 +1,3 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -1,27 +1,27 @@
1
- inherit_gem:
2
- rubocop-config-umbrellio: lib/rubocop.yml
3
- armitage-rubocop:
4
- - lib/rubocop.general.yml
5
- - lib/rubocop.rspec.yml
6
-
7
- AllCops:
8
- TargetRubyVersion: 2.6.3
9
- Include:
10
- - sequel-connection_guard.gemspec
11
- - lib/**/*.rb
12
- - spec/**/*.rb
13
- - Gemfile
14
- - Rakefile
15
- - bin/console
16
-
17
- Style/TrailingCommaInArguments:
18
- EnforcedStyleForMultiline: comma
19
-
20
- Style/TrailingCommaInArrayLiteral:
21
- EnforcedStyleForMultiline: comma
22
-
23
- Style/TrailingCommaInHashLiteral:
24
- EnforcedStyleForMultiline: comma
25
-
26
- RSpec/LeakyConstantDeclaration:
27
- Enabled: false
1
+ inherit_gem:
2
+ rubocop-config-umbrellio: lib/rubocop.yml
3
+ armitage-rubocop:
4
+ - lib/rubocop.general.yml
5
+ - lib/rubocop.rspec.yml
6
+
7
+ AllCops:
8
+ TargetRubyVersion: 2.6.3
9
+ Include:
10
+ - sequel-connection_guard.gemspec
11
+ - lib/**/*.rb
12
+ - spec/**/*.rb
13
+ - Gemfile
14
+ - Rakefile
15
+ - bin/console
16
+
17
+ Style/TrailingCommaInArguments:
18
+ EnforcedStyleForMultiline: comma
19
+
20
+ Style/TrailingCommaInArrayLiteral:
21
+ EnforcedStyleForMultiline: comma
22
+
23
+ Style/TrailingCommaInHashLiteral:
24
+ EnforcedStyleForMultiline: comma
25
+
26
+ RSpec/LeakyConstantDeclaration:
27
+ Enabled: false
@@ -1,20 +1,20 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.5.1
5
- - 2.6
6
- - ruby-head
7
-
8
- services:
9
- - postgresql
10
- addons:
11
- postgresql: 9.6
12
-
13
- before_install: gem install bundler
14
- before_script:
15
- - psql -c 'create database scripper_test;' -U postgres
16
- script:
17
- - bundle exec rspec
18
- - bundle exec rubocop
19
-
20
- cache: bundler
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.1
5
+ - 2.6
6
+ - ruby-head
7
+
8
+ services:
9
+ - postgresql
10
+ addons:
11
+ postgresql: 9.6
12
+
13
+ before_install: gem install bundler
14
+ before_script:
15
+ - psql -c 'create database scripper_test;' -U postgres
16
+ script:
17
+ - bundle exec rspec
18
+ - bundle exec rubocop
19
+
20
+ cache: bundler
data/Gemfile CHANGED
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
- source "https://rubygems.org"
4
-
5
- gemspec
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
data/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2019 Umbrellio
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Umbrellio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,164 +1,164 @@
1
- # Scripper
2
- [![Build Status](https://travis-ci.org/umbrellio/scripper.svg?branch=master)](https://travis-ci.org/umbrellio/scripper)
3
- [![Coverage Status](https://coveralls.io/repos/github/umbrellio/scripper/badge.svg?branch=master)](https://coveralls.io/github/umbrellio/scripper?branch=master)
4
- [![Gem Version](https://badge.fury.io/rb/scripper.svg)](https://badge.fury.io/rb/scripper)
5
-
6
- This gem allows you to strip down your Sequel model instances and hashes returned by dataset queries
7
- to simple Ruby structs.
8
-
9
- **This gem was only tested against PostgreSQL databases.**
10
-
11
- ## Why strip models?
12
-
13
- It's often convenient to simply call methods on model objects everywhere: controllers, views,
14
- serializers, business logic, and so on. But, by doing so, you're making the whole of your codebase
15
- depend on your database!
16
-
17
- This gem is a very basic way to introduce some layer of isolation between your database and the
18
- rest of the codebase. As your application grows, it will be much simpler to transition to more
19
- mature abstractions with such isolation than without it.
20
-
21
- The behaviour is more predictable since:
22
- - There are no unexpected database queries (e.x. when loading associations during view rendering)
23
- - There are no leaking database types like `Sequel::Postgres::JSONBHash` (these are converted to hashes automatically)
24
-
25
- ## Installation
26
-
27
- Add this line to your application's Gemfile:
28
-
29
- ```ruby
30
- gem 'scripper'
31
- ```
32
-
33
- And then execute:
34
- ```sh
35
- $ bundle
36
- ```
37
-
38
- It's recommended to "wrap" this gem into a separate module:
39
- ```ruby
40
- # lib/stripper.rb
41
-
42
- Stripper = Scripper::Sequel
43
- ```
44
-
45
- ## Usage
46
-
47
- It's very simple! Scripper works both with instances of Sequel::Model and hashes returned when
48
- using naked models or datasets.
49
-
50
- ```ruby
51
- # with models
52
- user = User.first
53
- Stripper.strip(user) # => #<struct id=2, email="cow@cow.cow", password_hash="...">
54
- user.email # => "cow@cow.cow"
55
-
56
- # with datasets
57
- user = DB[:users].first # or: User.naked.first
58
- Stripper.strip(user) # => #<struct id=2, email="cow@cow.cow", password_hash="...">
59
- user.email # => "cow@cow.cow"
60
- ```
61
-
62
- ### Loading associations
63
-
64
- If you'd like to also use associations on your struct (works only with models):
65
-
66
- ```ruby
67
- user = User.first
68
- Stripper.strip(user, with_associations: %w[cookies])
69
- # => #<struct id=2, ..., cookies=[#<struct ...>, #<struct ...>, #<struct ...>]>
70
- ```
71
-
72
- Beware that this will load _all_ cookies associated with your user! If you want to impose some
73
- filtering conditions, you can do that:
74
-
75
- ```ruby
76
- user = User.first
77
- Stripper.strip(
78
- user,
79
- with_associations: { cookies: -> (ds) { ds.where(active: true).limit(10) } },
80
- )
81
- ```
82
-
83
- This will only load no more than 10 active cookies.
84
-
85
- ### Providing extra attributes
86
-
87
- Sometimes it's useful to provide some context beyond associations and model/dataset attributes.
88
-
89
- In the example below, we're providing information about user's payment sum, not only user's fields.
90
-
91
- ```ruby
92
- # with a model
93
- user = User
94
- .left_join(:payments)
95
- .select_all(:users)
96
- .select_append(
97
- Sequel.function(:sum, Sequel[:payments][:amount]).as(:payment_sum),
98
- )
99
- .group(Sequel[:users][:id])
100
- .first
101
-
102
- Stripper.strip(user, with_attributes: { payment_sum: user[:payment_sum] })
103
- # => #<struct id=2, ..., payment_sum=418.0>
104
-
105
- # with a dataset, it's nearly identical
106
- user = DB[:users]
107
- .left_join(:payments)
108
- .select_all(:users)
109
- .select_append(
110
- Sequel.function(:sum, Sequel[:payments][:amount]).as(:payment_sum),
111
- )
112
- .group(Sequel[:users][:id])
113
- .first
114
-
115
- Stripper.strip(user, with_attributes: { payment_sum: user[:payment_sum] })
116
- # => #<struct id=2, ..., payment_sum=418.0>
117
- ```
118
-
119
- ## Default value conversions
120
-
121
- `Sequel::Postgres::JSONHashBase` (`JSONBHash`, `JSONHash`, ...) => `Hash`
122
-
123
- `Sequel::Postgres::JSONArrayBase` (`JSONBArray`, `JSONArray`, ...) => `Array`
124
-
125
- `Sequel::Postgres::PGArray` => `Array`
126
-
127
- `BigDecimal` => `Float`
128
-
129
- Currently, these are not extensible.
130
-
131
- ## Roadmap
132
-
133
- It would be lovely to:
134
- - Make value conversions extensible
135
- - Support ActiveRecord
136
- - Test the gem on other databases
137
-
138
- Your contributions and feedback are very welcome!
139
-
140
- ## Development
141
-
142
- To run tests, you need to first create a PostgreSQL database, and then set a `DB_URL` variable.
143
-
144
- Example:
145
- ```sh
146
- DB_URL=postgres://localhost/scripper_test bundle exec rspec
147
- ```
148
-
149
- If you want to enable Sequel's database access logging during spec runs, use `LOG_DB=1`.
150
-
151
- ## Contributing
152
-
153
- Bug reports and pull requests are welcome on GitHub at https://github.com/umbrellio/scripper.
154
-
155
- ## License
156
-
157
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
158
-
159
- ## Authors
160
- Created by [Alexander Komarov](https://github.com/akxcv).
161
-
162
- <a href="https://github.com/umbrellio/">
163
- <img style="float: left;" src="https://umbrellio.github.io/Umbrellio/supported_by_umbrellio.svg" alt="Supported by Umbrellio" width="439" height="72">
164
- </a>
1
+ # Scripper
2
+ [![Build Status](https://travis-ci.org/umbrellio/scripper.svg?branch=master)](https://travis-ci.org/umbrellio/scripper)
3
+ [![Coverage Status](https://coveralls.io/repos/github/umbrellio/scripper/badge.svg?branch=master)](https://coveralls.io/github/umbrellio/scripper?branch=master)
4
+ [![Gem Version](https://badge.fury.io/rb/scripper.svg)](https://badge.fury.io/rb/scripper)
5
+
6
+ This gem allows you to strip down your Sequel model instances and hashes returned by dataset queries
7
+ to simple Ruby structs.
8
+
9
+ **This gem was only tested against PostgreSQL databases.**
10
+
11
+ ## Why strip models?
12
+
13
+ It's often convenient to simply call methods on model objects everywhere: controllers, views,
14
+ serializers, business logic, and so on. But, by doing so, you're making the whole of your codebase
15
+ depend on your database!
16
+
17
+ This gem is a very basic way to introduce some layer of isolation between your database and the
18
+ rest of the codebase. As your application grows, it will be much simpler to transition to more
19
+ mature abstractions with such isolation than without it.
20
+
21
+ The behaviour is more predictable since:
22
+ - There are no unexpected database queries (e.x. when loading associations during view rendering)
23
+ - There are no leaking database types like `Sequel::Postgres::JSONBHash` (these are converted to hashes automatically)
24
+
25
+ ## Installation
26
+
27
+ Add this line to your application's Gemfile:
28
+
29
+ ```ruby
30
+ gem 'scripper'
31
+ ```
32
+
33
+ And then execute:
34
+ ```sh
35
+ $ bundle
36
+ ```
37
+
38
+ It's recommended to "wrap" this gem into a separate module:
39
+ ```ruby
40
+ # lib/stripper.rb
41
+
42
+ Stripper = Scripper::Sequel
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ It's very simple! Scripper works both with instances of Sequel::Model and hashes returned when
48
+ using naked models or datasets.
49
+
50
+ ```ruby
51
+ # with models
52
+ user = User.first
53
+ Stripper.strip(user) # => #<struct id=2, email="cow@cow.cow", password_hash="...">
54
+ user.email # => "cow@cow.cow"
55
+
56
+ # with datasets
57
+ user = DB[:users].first # or: User.naked.first
58
+ Stripper.strip(user) # => #<struct id=2, email="cow@cow.cow", password_hash="...">
59
+ user.email # => "cow@cow.cow"
60
+ ```
61
+
62
+ ### Loading associations
63
+
64
+ If you'd like to also use associations on your struct (works only with models):
65
+
66
+ ```ruby
67
+ user = User.first
68
+ Stripper.strip(user, with_associations: %w[cookies])
69
+ # => #<struct id=2, ..., cookies=[#<struct ...>, #<struct ...>, #<struct ...>]>
70
+ ```
71
+
72
+ Beware that this will load _all_ cookies associated with your user! If you want to impose some
73
+ filtering conditions, you can do that:
74
+
75
+ ```ruby
76
+ user = User.first
77
+ Stripper.strip(
78
+ user,
79
+ with_associations: { cookies: -> (ds) { ds.where(active: true).limit(10) } },
80
+ )
81
+ ```
82
+
83
+ This will only load no more than 10 active cookies.
84
+
85
+ ### Providing extra attributes
86
+
87
+ Sometimes it's useful to provide some context beyond associations and model/dataset attributes.
88
+
89
+ In the example below, we're providing information about user's payment sum, not only user's fields.
90
+
91
+ ```ruby
92
+ # with a model
93
+ user = User
94
+ .left_join(:payments)
95
+ .select_all(:users)
96
+ .select_append(
97
+ Sequel.function(:sum, Sequel[:payments][:amount]).as(:payment_sum),
98
+ )
99
+ .group(Sequel[:users][:id])
100
+ .first
101
+
102
+ Stripper.strip(user, with_attributes: { payment_sum: user[:payment_sum] })
103
+ # => #<struct id=2, ..., payment_sum=418.0>
104
+
105
+ # with a dataset, it's nearly identical
106
+ user = DB[:users]
107
+ .left_join(:payments)
108
+ .select_all(:users)
109
+ .select_append(
110
+ Sequel.function(:sum, Sequel[:payments][:amount]).as(:payment_sum),
111
+ )
112
+ .group(Sequel[:users][:id])
113
+ .first
114
+
115
+ Stripper.strip(user, with_attributes: { payment_sum: user[:payment_sum] })
116
+ # => #<struct id=2, ..., payment_sum=418.0>
117
+ ```
118
+
119
+ ## Default value conversions
120
+
121
+ `Sequel::Postgres::JSONHashBase` (`JSONBHash`, `JSONHash`, ...) => `Hash`
122
+
123
+ `Sequel::Postgres::JSONArrayBase` (`JSONBArray`, `JSONArray`, ...) => `Array`
124
+
125
+ `Sequel::Postgres::PGArray` => `Array`
126
+
127
+ `BigDecimal` => `Float`
128
+
129
+ Currently, these are not extensible.
130
+
131
+ ## Roadmap
132
+
133
+ It would be lovely to:
134
+ - Make value conversions extensible
135
+ - Support ActiveRecord
136
+ - Test the gem on other databases
137
+
138
+ Your contributions and feedback are very welcome!
139
+
140
+ ## Development
141
+
142
+ To run tests, you need to first create a PostgreSQL database, and then set a `DB_URL` variable.
143
+
144
+ Example:
145
+ ```sh
146
+ DB_URL=postgres://localhost/scripper_test bundle exec rspec
147
+ ```
148
+
149
+ If you want to enable Sequel's database access logging during spec runs, use `LOG_DB=1`.
150
+
151
+ ## Contributing
152
+
153
+ Bug reports and pull requests are welcome on GitHub at https://github.com/umbrellio/scripper.
154
+
155
+ ## License
156
+
157
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
158
+
159
+ ## Authors
160
+ Created by [Alexander Komarov](https://github.com/akxcv).
161
+
162
+ <a href="https://github.com/umbrellio/">
163
+ <img style="float: left;" src="https://umbrellio.github.io/Umbrellio/supported_by_umbrellio.svg" alt="Supported by Umbrellio" width="439" height="72">
164
+ </a>
data/Rakefile CHANGED
@@ -1,8 +1,8 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
5
-
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- task default: :spec
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -1,8 +1,8 @@
1
- # frozen_string_literal: true
2
-
3
- require "scripper/sequel"
4
- require "scripper/sequel/dataset_stripper"
5
- require "scripper/sequel/model_stripper"
6
- require "scripper/sequel/value_converter"
7
-
8
- module Scripper; end
1
+ # frozen_string_literal: true
2
+
3
+ require "scripper/sequel"
4
+ require "scripper/sequel/dataset_stripper"
5
+ require "scripper/sequel/model_stripper"
6
+ require "scripper/sequel/value_converter"
7
+
8
+ module Scripper; end
@@ -1,25 +1,25 @@
1
- # frozen_string_literal: true
2
-
3
- module Scripper
4
- module Sequel
5
- class << self
6
- def strip(object, **args)
7
- if object.is_a?(Hash)
8
- strip_dataset(object)
9
- else
10
- strip_model(object, **args)
11
- end
12
- end
13
-
14
- private
15
-
16
- def strip_model(*args)
17
- ModelStripper.strip(*args)
18
- end
19
-
20
- def strip_dataset(ds)
21
- DatasetStripper.strip(ds)
22
- end
23
- end
24
- end
25
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Scripper
4
+ module Sequel
5
+ class << self
6
+ def strip(object, **args)
7
+ if object.is_a?(Hash)
8
+ strip_dataset(object)
9
+ else
10
+ strip_model(object, **args)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def strip_model(*args)
17
+ ModelStripper.strip(*args)
18
+ end
19
+
20
+ def strip_dataset(ds)
21
+ DatasetStripper.strip(ds)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,14 +1,14 @@
1
- # frozen_string_literal: true
2
-
3
- module Scripper
4
- module Sequel
5
- module DatasetStripper
6
- class << self
7
- def strip(hsh)
8
- struct_klass = Struct.new(*hsh.keys)
9
- struct_klass.new(*hsh.transform_values { |v| ValueConverter.convert_value(v) }.values)
10
- end
11
- end
12
- end
13
- end
14
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Scripper
4
+ module Sequel
5
+ module DatasetStripper
6
+ class << self
7
+ def strip(hsh)
8
+ struct_klass = Struct.new(*hsh.keys)
9
+ struct_klass.new(*hsh.transform_values { |v| ValueConverter.convert_value(v) }.values)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,63 +1,69 @@
1
- # frozen_string_literal: true
2
-
3
- module Scripper
4
- module Sequel
5
- module ModelStripper
6
- class << self
7
- def strip(object, with_associations: nil, with_attributes: nil)
8
- association_fields = build_association_fields(object, with_associations)
9
- attribute_fields = build_attribute_fields(object, with_attributes)
10
-
11
- attrs = {
12
- **convert_values(object.values),
13
- **association_fields,
14
- **attribute_fields,
15
- }
16
-
17
- struct_klass = Struct.new(*attrs.keys)
18
- struct_klass.new(*attrs.values)
19
- end
20
-
21
- private
22
-
23
- def build_association_fields(object, associations)
24
- return {} if associations.nil?
25
-
26
- if associations.is_a?(Array)
27
- build_association_fields_from_array(object, associations)
28
- else # consider associations a hash
29
- build_association_fields_from_hash(object, associations)
30
- end
31
- end
32
-
33
- def build_attribute_fields(object, attributes)
34
- return {} if attributes.nil?
35
-
36
- convert_values(attributes)
37
- end
38
-
39
- def convert_values(hsh)
40
- hsh.transform_values { |v| ValueConverter.convert_value(v) }
41
- end
42
-
43
- def build_association_fields_from_array(object, associations)
44
- associations.reduce({}) do |acc, association|
45
- acc.merge(
46
- association.to_sym => object.public_send(association).map { |obj| strip(obj) },
47
- )
48
- end
49
- end
50
-
51
- def build_association_fields_from_hash(object, associations)
52
- associations.entries.reduce({}) do |acc, (association, condition)|
53
- association_ds = object.class.association_reflection(association).associated_dataset
54
-
55
- acc.merge(
56
- association.to_sym => condition.call(association_ds).all.map { |obj| strip(obj) },
57
- )
58
- end
59
- end
60
- end
61
- end
62
- end
63
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Scripper
4
+ module Sequel
5
+ module ModelStripper
6
+ class << self
7
+ def strip(object, with_associations: nil, with_attributes: nil)
8
+ association_fields = build_association_fields(object, with_associations)
9
+ attribute_fields = build_attribute_fields(object, with_attributes)
10
+
11
+ attrs = {
12
+ **convert_values(object.values),
13
+ **association_fields,
14
+ **attribute_fields,
15
+ }
16
+
17
+ struct_klass = Struct.new(*attrs.keys)
18
+ struct_klass.new(*attrs.values)
19
+ end
20
+
21
+ private
22
+
23
+ def build_association_fields(object, associations)
24
+ return {} if associations.nil?
25
+
26
+ if associations.is_a?(Array)
27
+ build_association_fields_from_array(object, associations)
28
+ else # consider associations a hash
29
+ build_association_fields_from_hash(object, associations)
30
+ end
31
+ end
32
+
33
+ def build_attribute_fields(object, attributes)
34
+ return {} if attributes.nil?
35
+
36
+ convert_values(attributes)
37
+ end
38
+
39
+ def convert_values(hsh)
40
+ hsh.transform_values { |v| ValueConverter.convert_value(v) }
41
+ end
42
+
43
+ def build_association_fields_from_array(object, associations)
44
+ associations.reduce({}) do |acc, association|
45
+ association_value = object.public_send(association)
46
+ stripped_association_value =
47
+ if association_value.is_a?(Array)
48
+ association_value.map { |obj| strip(obj) }
49
+ else
50
+ strip(association_value)
51
+ end
52
+
53
+ acc.merge(association.to_sym => stripped_association_value)
54
+ end
55
+ end
56
+
57
+ def build_association_fields_from_hash(object, associations)
58
+ associations.entries.reduce({}) do |acc, (association, condition)|
59
+ association_ds = object.class.association_reflection(association).associated_dataset
60
+
61
+ acc.merge(
62
+ association.to_sym => condition.call(association_ds).all.map { |obj| strip(obj) },
63
+ )
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,23 +1,23 @@
1
- # frozen_string_literal: true
2
-
3
- module Scripper
4
- module Sequel
5
- module ValueConverter
6
- class << self
7
- def convert_value(value)
8
- if value.is_a?(::Sequel::Postgres::JSONHashBase)
9
- value.to_h
10
- elsif value.is_a?(::Sequel::Postgres::JSONArrayBase)
11
- value.to_a
12
- elsif value.is_a?(::Sequel::Postgres::PGArray)
13
- value.to_a
14
- elsif value.is_a?(BigDecimal)
15
- value.to_f
16
- else
17
- value
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Scripper
4
+ module Sequel
5
+ module ValueConverter
6
+ class << self
7
+ def convert_value(value)
8
+ if value.is_a?(::Sequel::Postgres::JSONHashBase)
9
+ value.to_h
10
+ elsif value.is_a?(::Sequel::Postgres::JSONArrayBase)
11
+ value.to_a
12
+ elsif value.is_a?(::Sequel::Postgres::PGArray)
13
+ value.to_a
14
+ elsif value.is_a?(BigDecimal)
15
+ value.to_f
16
+ else
17
+ value
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,35 +1,35 @@
1
- # frozen_string_literal: true
2
-
3
- lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = 'scripper'
8
- spec.version = '0.1.0'
9
- spec.authors = ['Alexander Komarov <ak@akxcv.com>']
10
- spec.email = ['ak@akxcv.com']
11
-
12
- spec.summary = 'A gem that strips Sequel models down to simple value objects'
13
- spec.description = '@see summary'
14
- spec.homepage = 'https://github.com/umbrellio/scripper'
15
- spec.license = 'MIT'
16
-
17
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
- end
20
- spec.bindir = 'exe'
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ['lib']
23
-
24
- spec.add_development_dependency 'bundler', '~> 2.0'
25
- spec.add_development_dependency 'rake', '~> 10.0'
26
- spec.add_development_dependency 'rspec', '~> 3.0'
27
- spec.add_development_dependency 'simplecov'
28
- spec.add_development_dependency 'coveralls'
29
- spec.add_development_dependency 'armitage-rubocop'
30
- spec.add_development_dependency 'rubocop-config-umbrellio'
31
- spec.add_development_dependency 'pry'
32
-
33
- spec.add_development_dependency 'pg'
34
- spec.add_development_dependency 'sequel'
35
- end
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "scripper"
8
+ spec.version = "0.1.1"
9
+ spec.authors = ["Alexander Komarov <ak@akxcv.com>"]
10
+ spec.email = %w[ak@akxcv.com]
11
+
12
+ spec.summary = "A gem that strips Sequel models down to simple value objects"
13
+ spec.description = "@see summary"
14
+ spec.homepage = "https://github.com/umbrellio/scripper"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = %w[lib]
23
+
24
+ spec.add_development_dependency "bundler", "~> 2.0"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ spec.add_development_dependency "simplecov"
28
+ spec.add_development_dependency "coveralls"
29
+ spec.add_development_dependency "armitage-rubocop"
30
+ spec.add_development_dependency "rubocop-config-umbrellio"
31
+ spec.add_development_dependency "pry"
32
+
33
+ spec.add_development_dependency "pg"
34
+ spec.add_development_dependency "sequel"
35
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scripper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Komarov <ak@akxcv.com>
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-12 00:00:00.000000000 Z
11
+ date: 2019-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -162,7 +162,6 @@ files:
162
162
  - ".rubocop.yml"
163
163
  - ".travis.yml"
164
164
  - Gemfile
165
- - Gemfile.lock
166
165
  - LICENSE
167
166
  - README.md
168
167
  - Rakefile
@@ -1,104 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- scripper (0.1.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- armitage-rubocop (0.70.0.110)
10
- rubocop (= 0.70.0)
11
- rubocop-performance (= 1.3.0)
12
- rubocop-rails (= 2.0.0)
13
- rubocop-rspec (= 1.33.0)
14
- ast (2.4.0)
15
- coderay (1.1.2)
16
- coveralls (0.7.2)
17
- multi_json (~> 1.3)
18
- rest-client (= 1.6.7)
19
- simplecov (>= 0.7)
20
- term-ansicolor (= 1.2.2)
21
- thor (= 0.18.1)
22
- diff-lcs (1.3)
23
- docile (1.3.2)
24
- jaro_winkler (1.5.3)
25
- json (2.2.0)
26
- method_source (0.9.2)
27
- mime-types (3.3)
28
- mime-types-data (~> 3.2015)
29
- mime-types-data (3.2019.1009)
30
- multi_json (1.13.1)
31
- parallel (1.18.0)
32
- parser (2.6.5.0)
33
- ast (~> 2.4.0)
34
- pg (1.1.4-x64-mingw32)
35
- pry (0.12.2)
36
- coderay (~> 1.1.0)
37
- method_source (~> 0.9.0)
38
- rack (2.0.7)
39
- rainbow (3.0.0)
40
- rake (10.5.0)
41
- rest-client (1.6.7)
42
- mime-types (>= 1.16)
43
- rspec (3.9.0)
44
- rspec-core (~> 3.9.0)
45
- rspec-expectations (~> 3.9.0)
46
- rspec-mocks (~> 3.9.0)
47
- rspec-core (3.9.0)
48
- rspec-support (~> 3.9.0)
49
- rspec-expectations (3.9.0)
50
- diff-lcs (>= 1.2.0, < 2.0)
51
- rspec-support (~> 3.9.0)
52
- rspec-mocks (3.9.0)
53
- diff-lcs (>= 1.2.0, < 2.0)
54
- rspec-support (~> 3.9.0)
55
- rspec-support (3.9.0)
56
- rubocop (0.70.0)
57
- jaro_winkler (~> 1.5.1)
58
- parallel (~> 1.10)
59
- parser (>= 2.6)
60
- rainbow (>= 2.2.2, < 4.0)
61
- ruby-progressbar (~> 1.7)
62
- unicode-display_width (>= 1.4.0, < 1.7)
63
- rubocop-config-umbrellio (0.70.0.55)
64
- rubocop (= 0.70.0)
65
- rubocop-performance (= 1.3.0)
66
- rubocop-rspec (= 1.33.0)
67
- rubocop-performance (1.3.0)
68
- rubocop (>= 0.68.0)
69
- rubocop-rails (2.0.0)
70
- rack (>= 2.0)
71
- rubocop (>= 0.70.0)
72
- rubocop-rspec (1.33.0)
73
- rubocop (>= 0.60.0)
74
- ruby-progressbar (1.10.1)
75
- sequel (5.25.0)
76
- simplecov (0.17.1)
77
- docile (~> 1.1)
78
- json (>= 1.8, < 3)
79
- simplecov-html (~> 0.10.0)
80
- simplecov-html (0.10.2)
81
- term-ansicolor (1.2.2)
82
- tins (~> 0.8)
83
- thor (0.18.1)
84
- tins (0.13.2)
85
- unicode-display_width (1.6.0)
86
-
87
- PLATFORMS
88
- x64-mingw32
89
-
90
- DEPENDENCIES
91
- armitage-rubocop
92
- bundler (~> 2.0)
93
- coveralls
94
- pg
95
- pry
96
- rake (~> 10.0)
97
- rspec (~> 3.0)
98
- rubocop-config-umbrellio
99
- scripper!
100
- sequel
101
- simplecov
102
-
103
- BUNDLED WITH
104
- 2.0.2