pluck_map 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -2
- data/README.md +127 -2
- data/lib/pluck_map/attribute.rb +11 -2
- data/lib/pluck_map/attributes.rb +6 -0
- data/lib/pluck_map/presenter.rb +2 -1
- data/lib/pluck_map/version.rb +1 -1
- data/pluck_map.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b299dd06b71f709f45a8b9df4e52b20c70785976a3502f5b2402f0f340da8160
|
4
|
+
data.tar.gz: d4d4e2f78031b5fe3fa8c6492885bc2bfa17b73f30825c60fede8f10fec2e13c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6da4c576698798f98ac790f81a8dd4ff4f4b07b27212ef3c43f4d54966d04d139ff082f79b86a163abcaf3d3d64a27119c5cd84705baa32c7c39a7b3c369979
|
7
|
+
data.tar.gz: 9862dd28a87a7e82385f14eeb3a055672aac462cf0f2496ec8a189fa476d51c74a24711780ab1c84640c568f92053cb872d75c88834f094a6dd7399ca948e836
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
## v0.6.0 (2019 May 5)
|
2
|
+
|
3
|
+
* REFACTOR: Deprecated `Presenter#no_map?` and introduced `Attributes#will_map?` to replace it (@boblail)
|
4
|
+
* REFACTOR: Deprecated passing strings to `:select` (Known-safe values can be wrapped in `Arel.sql`) (@boblail)
|
5
|
+
|
1
6
|
## v0.5.0 (2019 May 1)
|
2
7
|
|
3
|
-
* REFACTOR: Introduced a new syntax for defining PluckMap Presenters and deprecated
|
4
|
-
calling `PluckMap::Presenter.new` with a block
|
8
|
+
* REFACTOR: Introduced a new syntax for defining PluckMap Presenters and deprecated calling `PluckMap::Presenter.new` with a block (@boblail)
|
5
9
|
* FEATURE: Add `to_json` presenter method (@boblail)
|
6
10
|
* FEATURE: Add `to_csv` presenter method (@boblail)
|
7
11
|
|
data/README.md
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
|
6
6
|
This library provides a DSL for presenting ActiveRecord::Relations without instantiating ActiveRecord models. It is useful when a Rails controller action does little more than fetch several records from the database and present them in some other data format (like JSON or CSV).
|
7
7
|
|
8
|
+
### Why?
|
9
|
+
|
8
10
|
Suppose you have an action like this:
|
9
11
|
|
10
12
|
```ruby
|
@@ -18,9 +20,9 @@ Suppose you have an action like this:
|
|
18
20
|
end
|
19
21
|
```
|
20
22
|
|
21
|
-
This instantiates a `Message` for every result, gets the attributes out of it, and then immediately discards it.
|
23
|
+
:point_up: This instantiates a `Message` for every result, gets the attributes out of it, and then immediately discards it.
|
22
24
|
|
23
|
-
We can skip that unnecessary instantiation by using `pluck
|
25
|
+
We can skip that unnecessary instantiation by using [`pluck`](https://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-pluck):
|
24
26
|
|
25
27
|
```ruby
|
26
28
|
def index
|
@@ -86,6 +88,114 @@ This DSL also makes it easy to make fields optional:
|
|
86
88
|
end
|
87
89
|
```
|
88
90
|
|
91
|
+
### How is this different from [Jbuilder](https://github.com/rails/jbuilder)?
|
92
|
+
|
93
|
+
Jbuilder gives you a similar DSL for defining JSON to be presented but it operators on instances of ActiveRecord objects rather than producing a query to pluck just the values we need from the database.
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
## Usage
|
98
|
+
|
99
|
+
### Attributes
|
100
|
+
|
101
|
+
#### Syntax
|
102
|
+
|
103
|
+
Define attributes using either of these syntaxes:
|
104
|
+
|
105
|
+
1. Without the block variable
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
presenter = PluckMap[Book].define do
|
109
|
+
title
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
113
|
+
2. With the block variable
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
presenter = PluckMap[Book].define do |q|
|
117
|
+
q.title
|
118
|
+
end
|
119
|
+
```
|
120
|
+
|
121
|
+
Apart from the repetition of the block variable, the difference between the two styles is the value of `self` within the block. In the first case, `self` will be `PluckMap::AttributesBuilder`. In the second, `self` will be the containing object. The former is less repetitious but the latter can be useful if you want to refer to local methods or instance variables in the context.
|
122
|
+
|
123
|
+
#### `:as` and `:select`
|
124
|
+
|
125
|
+
:point_down: This will construct a query to select `books.title` from the database and present the value of each title with the key (or column name) `"title"`:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
presenter = PluckMap[Book].define do
|
129
|
+
title
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
There are two ways to change the name of the key that is presented. Both of the following examples will select `authors.first_name` from the database and present it as `"firstName"`:
|
134
|
+
|
135
|
+
|
136
|
+
1. Using `:as`
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
presenter = PluckMap[Author].define do
|
140
|
+
first_name as: "firstName"
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
2. Using `:select`
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
presenter = PluckMap[Author].define do
|
148
|
+
firstName select: :first_name
|
149
|
+
end
|
150
|
+
```
|
151
|
+
|
152
|
+
You can also pass raw SQL expressions to `:select`:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
presenter = PluckMap[Person].define do
|
156
|
+
name select: Arel.sql("CONCAT(first_name, ' ', last_name)")
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
#### `:map`
|
161
|
+
|
162
|
+
In the example above, we constructed `name` from `first_name` and `last_name` with a SQL expression. There are many reasons why we might want to process values before presenting them. When possible, it's usually more efficient to do this work in the query itself, but there are times when it's necessary or expedient to do it in Ruby. Use `:map` to process values returned from the query before they are presented.
|
163
|
+
|
164
|
+
Here are a couple of examples:
|
165
|
+
|
166
|
+
- Constructing `"name"` with `:map`:
|
167
|
+
```ruby
|
168
|
+
presenter = PluckMap[Person].define do
|
169
|
+
name select: %i[ first_name last_name ], map: ->(first, last) { "#{first} #{last}" }
|
170
|
+
end
|
171
|
+
```
|
172
|
+
|
173
|
+
- Formatting phone numbers with `:map`:
|
174
|
+
```ruby
|
175
|
+
presenter = PluckMap[Person].define do
|
176
|
+
phoneNumber select: %i[ phone_number ], map: ->(number) { PhoneNumberFormatter.format(number) }
|
177
|
+
end
|
178
|
+
```
|
179
|
+
|
180
|
+
#### `:value`
|
181
|
+
|
182
|
+
You can also hard-code a value to be used and it won't be queried from the database. There are two ways of expressing this:
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
presenter = PluckMap[Person].define do
|
186
|
+
id
|
187
|
+
type "Person"
|
188
|
+
end
|
189
|
+
```
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
presenter = PluckMap[Person].define do
|
193
|
+
id
|
194
|
+
type value: "Person"
|
195
|
+
end
|
196
|
+
```
|
197
|
+
|
198
|
+
|
89
199
|
|
90
200
|
## Installation
|
91
201
|
|
@@ -104,6 +214,20 @@ Or install it yourself as:
|
|
104
214
|
$ gem install pluck_map
|
105
215
|
|
106
216
|
|
217
|
+
### Requirements
|
218
|
+
|
219
|
+
The gem's only runtime requirement is:
|
220
|
+
|
221
|
+
- [activerecord](https://rubygems.org/gems/activerecord) 4.2+
|
222
|
+
|
223
|
+
It supports these databases out of the box:
|
224
|
+
|
225
|
+
- PostgreSQL
|
226
|
+
- MySQL
|
227
|
+
- SQLite
|
228
|
+
|
229
|
+
|
230
|
+
|
107
231
|
## Development
|
108
232
|
|
109
233
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -111,6 +235,7 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
111
235
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
112
236
|
|
113
237
|
|
238
|
+
|
114
239
|
## Contributing
|
115
240
|
|
116
241
|
Bug reports and pull requests are welcome on GitHub at https://github.com/boblail/pluck_map.
|
data/lib/pluck_map/attribute.rb
CHANGED
@@ -17,6 +17,15 @@ module PluckMap
|
|
17
17
|
raise ArgumentError, "You must select at least one column" if selects.empty?
|
18
18
|
raise ArgumentError, "You must define a block if you are going to select " <<
|
19
19
|
"more than one expression from the database" if selects.length > 1 && !block
|
20
|
+
|
21
|
+
@selects = @selects.map do |select|
|
22
|
+
if select.is_a?(String) && !select.is_a?(Arel::Nodes::SqlLiteral)
|
23
|
+
puts "DEPRECATION WARNING: Passing raw SQL as a String to :select is deprecated. Known-safe values can be passed by wrapping them in Arel.sql()."
|
24
|
+
Arel.sql(select)
|
25
|
+
else
|
26
|
+
select
|
27
|
+
end
|
28
|
+
end
|
20
29
|
end
|
21
30
|
end
|
22
31
|
|
@@ -24,8 +33,8 @@ module PluckMap
|
|
24
33
|
block.call(*object)
|
25
34
|
end
|
26
35
|
|
27
|
-
def
|
28
|
-
block.nil?
|
36
|
+
def will_map?
|
37
|
+
!block.nil?
|
29
38
|
end
|
30
39
|
|
31
40
|
# When the PluckMapPresenter performs the query, it will
|
data/lib/pluck_map/attributes.rb
CHANGED
data/lib/pluck_map/presenter.rb
CHANGED
data/lib/pluck_map/version.rb
CHANGED
data/pluck_map.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_dependency "activerecord"
|
20
|
+
spec.add_dependency "activerecord", ">= 4.2"
|
21
21
|
|
22
22
|
spec.add_development_dependency "appraisal"
|
23
23
|
spec.add_development_dependency "bundler"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pluck_map
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Lail
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-05-
|
11
|
+
date: 2019-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '4.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '4.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: appraisal
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|