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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3316ae636b712a8656e2efce061b2055b6e75f19b59e0265f1139e312e88d7ec
4
- data.tar.gz: bb75083e099c90e38f4b2a92840c197eb93a4c268b8c65917f4172c21e1b9f51
3
+ metadata.gz: b299dd06b71f709f45a8b9df4e52b20c70785976a3502f5b2402f0f340da8160
4
+ data.tar.gz: d4d4e2f78031b5fe3fa8c6492885bc2bfa17b73f30825c60fede8f10fec2e13c
5
5
  SHA512:
6
- metadata.gz: c2801ad881bdc370044fe2c997f7f3d1c137ae757af7aabc4bcc0d3c71e5a412ea136f95a769968aa4972e6d8385ccd6f961c265d8e6946363595bbc3139aae2
7
- data.tar.gz: 1ef71fbbd7f3fcdb4494087fc537db3962fb2529373272edb3c96a0a71481c0b18f69f43201cde511640aa5970f0b7a545dfd96e3dabab32f2e89d07a07c2b87
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.
@@ -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 no_map?
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
@@ -42,6 +42,12 @@ module PluckMap
42
42
 
43
43
 
44
44
 
45
+ def will_map?
46
+ _attributes.any?(&:will_map?)
47
+ end
48
+
49
+
50
+
45
51
  def ==(other)
46
52
  return false if self.class != other.class
47
53
  _attributes == other.send(:_attributes)
@@ -25,7 +25,8 @@ module PluckMap
25
25
  end
26
26
 
27
27
  def no_map?
28
- attributes.all?(&:no_map?)
28
+ puts "DEPRECATION WARNING: `PluckMap::Presenter#no_map?` is deprecated. You can replace it with `!attributes.will_map?`"
29
+ !attributes.will_map?
29
30
  end
30
31
 
31
32
  protected
@@ -1,3 +1,3 @@
1
1
  module PluckMapPresenter
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
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.5.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-02 00:00:00.000000000 Z
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: '0'
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: '0'
26
+ version: '4.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: appraisal
29
29
  requirement: !ruby/object:Gem::Requirement