paraphrase 0.7.0 → 0.8.0

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.
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ module Paraphrase
4
+ describe Scope do
5
+ def build_account_scope(options = {})
6
+ options.reverse_merge!(
7
+ keys: [:name],
8
+ to: :name_like
9
+ )
10
+
11
+ keys = options.delete(:keys)
12
+
13
+ Scope.new(keys, options)
14
+ end
15
+
16
+ describe "#chain" do
17
+ it "applies scope method to relation with values from params hash" do
18
+ scope = build_account_scope
19
+
20
+ expect(Account).to receive(:name_like).with('Jon Snow')
21
+ scope.chain({ name: 'Jon Snow' }, Account)
22
+ end
23
+
24
+ it "does nothing if values are missing" do
25
+ scope = build_account_scope
26
+
27
+ expect(Account).not_to receive(:name_like)
28
+ scope.chain({}, Account)
29
+ end
30
+
31
+ it "passes through blank values if scope has been whitelisted" do
32
+ scope = build_account_scope(whitelist: true)
33
+
34
+ expect(Account).to receive(:name_like).with(nil)
35
+ scope.chain({}, Account)
36
+ end
37
+
38
+ it 'allows whitelisting a subset of keys' do
39
+ scope = build_account_scope(
40
+ keys: [:name, :status],
41
+ to: :with_name_and_status,
42
+ whitelist: true
43
+ )
44
+
45
+ expect(Account).to receive(:with_name_and_status).with('George', nil)
46
+
47
+ scope.chain({ name: 'George' }, Account)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,13 +1,32 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module Paraphrase
4
- module Syntax
5
- describe Base do
6
- describe "#register_mapping" do
7
- it "creates new sublcass of Query" do
8
- Account.register_mapping {}
9
- Account._paraphraser.should_not be_nil
10
- end
4
+ describe Syntax do
5
+ class ::AccountQuery < Paraphrase::Query
6
+ map :name, to: :named
7
+ end
8
+
9
+ describe '.paraphrase' do
10
+ it "passes through results from an initialized query" do
11
+ expect_any_instance_of(AccountQuery).to receive(:result).and_call_original
12
+
13
+ result = Account.paraphrase
14
+ expect(result).to eq Account
15
+ end
16
+
17
+ it 'raises if query class is not defined' do
18
+ expect { User.paraphrase }.to raise_error Paraphrase::NoQueryDefined
19
+ end
20
+
21
+ it "works on instances of `ActiveRecord::Relation`, preserving existing filters" do
22
+ user = User.create!
23
+ Account.create!(user: user)
24
+ Account.create!(name: 'Sophie')
25
+ account = Account.create!(name: 'Sophie', user: user)
26
+
27
+ result = user.accounts.paraphrase(name: 'Sophie')
28
+
29
+ expect(result).to eq [account]
11
30
  end
12
31
  end
13
32
  end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,63 @@
1
1
  require 'rspec'
2
2
  require 'pry'
3
3
  require 'paraphrase'
4
- require 'support/database'
4
+ require 'active_record'
5
+
6
+ I18n.enforce_available_locales = false
7
+
8
+ ActiveRecord::Base.establish_connection(
9
+ adapter: 'sqlite3',
10
+ database: ':memory:'
11
+ )
12
+
13
+ ActiveRecord::Migration.verbose = false
14
+ ActiveRecord::Schema.define do
15
+ create_table :users, force: true do
16
+ end
17
+
18
+ create_table :posts, force: true do |t|
19
+ t.string :title
20
+ t.boolean :published
21
+ t.datetime :published_at
22
+ t.references :user
23
+ end
24
+
25
+ create_table :accounts, force: true do |t|
26
+ t.string :name
27
+ t.references :user
28
+ end
29
+ end
30
+
31
+ ActiveRecord::Base.extend Paraphrase::Syntax
32
+ ActiveRecord::Relation.send(:include, Paraphrase::Syntax)
33
+
34
+ class User < ActiveRecord::Base
35
+ has_many :accounts
36
+ has_many :posts
37
+ end
38
+
39
+ class Post < ActiveRecord::Base
40
+ belongs_to :user
41
+
42
+ scope :titled, ->(title) { where(title: title) }
43
+
44
+ def self.published
45
+ where(published: true)
46
+ end
47
+
48
+ def self.by_users(names)
49
+ joins(:user).where(users: { name: names })
50
+ end
51
+
52
+ def self.published_between(start_date, end_date)
53
+ where(published_at: start_date..end_date)
54
+ end
55
+ end
56
+
57
+ class Account < ActiveRecord::Base
58
+ belongs_to :user
59
+
60
+ def self.named(name)
61
+ where(name: name)
62
+ end
63
+ end
metadata CHANGED
@@ -1,181 +1,222 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paraphrase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eduardo Gutierrez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-26 00:00:00.000000000 Z
11
+ date: 2014-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.0'
20
- - - <
20
+ - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '4.1'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - '>='
27
+ - - ">="
28
28
  - !ruby/object:Gem::Version
29
29
  version: '3.0'
30
- - - <
30
+ - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '4.1'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: activesupport
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - '>='
37
+ - - ">="
38
38
  - !ruby/object:Gem::Version
39
39
  version: '3.0'
40
- - - <
40
+ - - "<"
41
41
  - !ruby/object:Gem::Version
42
42
  version: '4.1'
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - '>='
47
+ - - ">="
48
48
  - !ruby/object:Gem::Version
49
49
  version: '3.0'
50
- - - <
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '4.1'
53
+ - !ruby/object:Gem::Dependency
54
+ name: activemodel
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '3.0'
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '4.1'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '4.1'
73
+ - !ruby/object:Gem::Dependency
74
+ name: actionpack
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '3.0'
80
+ - - "<"
81
+ - !ruby/object:Gem::Version
82
+ version: '4.1'
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ - - "<"
51
91
  - !ruby/object:Gem::Version
52
92
  version: '4.1'
53
93
  - !ruby/object:Gem::Dependency
54
94
  name: bundler
55
95
  requirement: !ruby/object:Gem::Requirement
56
96
  requirements:
57
- - - ~>
97
+ - - "~>"
58
98
  - !ruby/object:Gem::Version
59
99
  version: '1.0'
60
100
  type: :development
61
101
  prerelease: false
62
102
  version_requirements: !ruby/object:Gem::Requirement
63
103
  requirements:
64
- - - ~>
104
+ - - "~>"
65
105
  - !ruby/object:Gem::Version
66
106
  version: '1.0'
67
107
  - !ruby/object:Gem::Dependency
68
108
  name: yard
69
109
  requirement: !ruby/object:Gem::Requirement
70
110
  requirements:
71
- - - ~>
111
+ - - "~>"
72
112
  - !ruby/object:Gem::Version
73
113
  version: '0.7'
74
114
  type: :development
75
115
  prerelease: false
76
116
  version_requirements: !ruby/object:Gem::Requirement
77
117
  requirements:
78
- - - ~>
118
+ - - "~>"
79
119
  - !ruby/object:Gem::Version
80
120
  version: '0.7'
81
121
  - !ruby/object:Gem::Dependency
82
122
  name: rspec
83
123
  requirement: !ruby/object:Gem::Requirement
84
124
  requirements:
85
- - - ~>
125
+ - - "~>"
86
126
  - !ruby/object:Gem::Version
87
- version: '2.10'
127
+ version: '2.14'
88
128
  type: :development
89
129
  prerelease: false
90
130
  version_requirements: !ruby/object:Gem::Requirement
91
131
  requirements:
92
- - - ~>
132
+ - - "~>"
93
133
  - !ruby/object:Gem::Version
94
- version: '2.10'
134
+ version: '2.14'
95
135
  - !ruby/object:Gem::Dependency
96
- name: redcarpet
136
+ name: rake
97
137
  requirement: !ruby/object:Gem::Requirement
98
138
  requirements:
99
- - - ~>
139
+ - - "~>"
100
140
  - !ruby/object:Gem::Version
101
- version: 2.1.1
141
+ version: 0.9.2
102
142
  type: :development
103
143
  prerelease: false
104
144
  version_requirements: !ruby/object:Gem::Requirement
105
145
  requirements:
106
- - - ~>
146
+ - - "~>"
107
147
  - !ruby/object:Gem::Version
108
- version: 2.1.1
148
+ version: 0.9.2
109
149
  - !ruby/object:Gem::Dependency
110
- name: rake
150
+ name: appraisal
111
151
  requirement: !ruby/object:Gem::Requirement
112
152
  requirements:
113
- - - ~>
153
+ - - "~>"
114
154
  - !ruby/object:Gem::Version
115
- version: 0.9.2
155
+ version: '0.4'
116
156
  type: :development
117
157
  prerelease: false
118
158
  version_requirements: !ruby/object:Gem::Requirement
119
159
  requirements:
120
- - - ~>
160
+ - - "~>"
121
161
  - !ruby/object:Gem::Version
122
- version: 0.9.2
162
+ version: '0.4'
123
163
  - !ruby/object:Gem::Dependency
124
- name: sqlite3
164
+ name: pry
125
165
  requirement: !ruby/object:Gem::Requirement
126
166
  requirements:
127
- - - ~>
167
+ - - "~>"
128
168
  - !ruby/object:Gem::Version
129
- version: 1.3.6
169
+ version: '0.9'
130
170
  type: :development
131
171
  prerelease: false
132
172
  version_requirements: !ruby/object:Gem::Requirement
133
173
  requirements:
134
- - - ~>
174
+ - - "~>"
135
175
  - !ruby/object:Gem::Version
136
- version: 1.3.6
176
+ version: '0.9'
137
177
  - !ruby/object:Gem::Dependency
138
- name: appraisal
178
+ name: redcarpet
139
179
  requirement: !ruby/object:Gem::Requirement
140
180
  requirements:
141
- - - ~>
181
+ - - "~>"
142
182
  - !ruby/object:Gem::Version
143
- version: '0.4'
183
+ version: 2.1.1
144
184
  type: :development
145
185
  prerelease: false
146
186
  version_requirements: !ruby/object:Gem::Requirement
147
187
  requirements:
148
- - - ~>
188
+ - - "~>"
149
189
  - !ruby/object:Gem::Version
150
- version: '0.4'
190
+ version: 2.1.1
151
191
  - !ruby/object:Gem::Dependency
152
- name: pry
192
+ name: sqlite3
153
193
  requirement: !ruby/object:Gem::Requirement
154
194
  requirements:
155
- - - ~>
195
+ - - "~>"
156
196
  - !ruby/object:Gem::Version
157
- version: '0.9'
197
+ version: 1.3.6
158
198
  type: :development
159
199
  prerelease: false
160
200
  version_requirements: !ruby/object:Gem::Requirement
161
201
  requirements:
162
- - - ~>
202
+ - - "~>"
163
203
  - !ruby/object:Gem::Version
164
- version: '0.9'
204
+ version: 1.3.6
165
205
  description: "\n Map query params to model scopes, pairing
166
206
  one or\n more keys to a scope. Parameters can be required,
167
207
  or\n whitelisted providing fine tuned control over how\n
168
208
  \ scopes are run.\n "
169
- email: edd_d@mit.edu
209
+ email: eduardo@vermonster.com
170
210
  executables: []
171
211
  extensions: []
172
212
  extra_rdoc_files: []
173
213
  files:
174
- - .gitignore
175
- - .rspec
176
- - .yardopts
214
+ - ".gitignore"
215
+ - ".rspec"
216
+ - ".travis.yml"
217
+ - ".yardopts"
177
218
  - Appraisals
178
- - CHANGELOG
219
+ - CHANGELOG.md
179
220
  - Gemfile
180
221
  - LICENSE.txt
181
222
  - README.md
@@ -189,18 +230,18 @@ files:
189
230
  - gemfiles/4.0.gemfile
190
231
  - gemfiles/4.0.gemfile.lock
191
232
  - lib/paraphrase.rb
233
+ - lib/paraphrase/active_model.rb
192
234
  - lib/paraphrase/errors.rb
193
235
  - lib/paraphrase/query.rb
194
236
  - lib/paraphrase/rails.rb
195
- - lib/paraphrase/scope_mapping.rb
237
+ - lib/paraphrase/scope.rb
196
238
  - lib/paraphrase/syntax.rb
197
239
  - lib/paraphrase/version.rb
198
240
  - paraphrase.gemspec
199
241
  - spec/paraphrase/query_spec.rb
200
- - spec/paraphrase/scope_mapping_spec.rb
242
+ - spec/paraphrase/scope_spec.rb
201
243
  - spec/paraphrase/syntax_spec.rb
202
244
  - spec/spec_helper.rb
203
- - spec/support/database.rb
204
245
  homepage: https://github.com/ecbypi/paraphrase
205
246
  licenses:
206
247
  - MIT
@@ -211,24 +252,23 @@ require_paths:
211
252
  - lib
212
253
  required_ruby_version: !ruby/object:Gem::Requirement
213
254
  requirements:
214
- - - '>='
255
+ - - ">="
215
256
  - !ruby/object:Gem::Version
216
- version: '0'
257
+ version: 1.9.3
217
258
  required_rubygems_version: !ruby/object:Gem::Requirement
218
259
  requirements:
219
- - - '>='
260
+ - - ">="
220
261
  - !ruby/object:Gem::Version
221
262
  version: '0'
222
263
  requirements: []
223
264
  rubyforge_project:
224
- rubygems_version: 2.0.3
265
+ rubygems_version: 2.2.0
225
266
  signing_key:
226
267
  specification_version: 4
227
268
  summary: Map query params to model scopes
228
269
  test_files:
229
270
  - spec/paraphrase/query_spec.rb
230
- - spec/paraphrase/scope_mapping_spec.rb
271
+ - spec/paraphrase/scope_spec.rb
231
272
  - spec/paraphrase/syntax_spec.rb
232
273
  - spec/spec_helper.rb
233
- - spec/support/database.rb
234
274
  has_rdoc:
data/CHANGELOG DELETED
@@ -1,39 +0,0 @@
1
- 0.7.0 / 1-25-2014
2
-
3
- * Add Rails 4 support
4
-
5
- 0.5.0 / 8-7-2012
6
-
7
- * Cleanup ScopeMapping class
8
- * Add ability to query from an existing ActiveRecord::Relation instance
9
- (typically an association).
10
- * Update syntax for generating mappings.
11
-
12
- 0.4.0 / 7-6-2012
13
-
14
- * Setup Query#params to be HashWithIndifferentAccess.
15
- * Gut out Paraphrase module methods. These were for use cases I had planned
16
- for but have yet to encounter.
17
- * Model's query class is now stored on the model itself.
18
-
19
- 0.3.2 / 7-5-2012
20
-
21
- * Cache Query#results
22
- * Setup Query#method_missing to proxy to Query#results
23
- * Setup Query#respond_to? to check Query#results
24
-
25
- 0.3.1 / 7-5-2012
26
-
27
- * Fix for rails 3.0
28
-
29
- 0.3.0 / 7-5-2012
30
-
31
- * Allow nil values to be passed to scoped using :allow_nil option.
32
- * Require/whitelist individual keys of a compound key.
33
- * Update Paraphrase::Syntax.register_mapping to update an existing mapping to
34
- avoid errors when a model class is reloaded during development.
35
-
36
- 0.2.0 / 6-22-2012
37
-
38
- * Initial release
39
-
@@ -1,78 +0,0 @@
1
- require 'active_support/core_ext/object/blank'
2
-
3
- module Paraphrase
4
- class ScopeMapping
5
- # @!attribute [r] keys
6
- # @return [Array<Symbol>] param keys to extract
7
- #
8
- # @!attribute [r] method_name
9
- # @return [Symbol] scope name
10
- #
11
- # @!attribute [r] required
12
- # @return [Array] keys required for query
13
- #
14
- # @!attribute [r] whitelist
15
- # @return [Array] keys allowed to be nil
16
- attr_reader :keys, :method_name, :required, :whitelist
17
-
18
- # @param [Symbol] name name of the scope
19
- # @param [Hash] options options to configure {ScopeMapping ScopeMapping} instance
20
- # @option options [Symbol, Array<Symbol>] :to param key(s) to extract values from
21
- # @option options [true, Symbol, Array<Symbol>] :require lists all or a
22
- # subset of param keys as required
23
- # @option options [true, Symbol, Array<Symbol>] :whitelist lists all or a
24
- # subset of param keys as whitelisted
25
- def initialize(name, options)
26
- @method_name = name
27
- @keys = Array(options.delete(:to))
28
-
29
- @required = register_keys(options[:require])
30
- @whitelist = register_keys(options[:whitelist])
31
-
32
- if @whitelist.empty? && !@required.empty?
33
- @whitelist = @keys - @required
34
- end
35
-
36
- if (whitelist & required).any?
37
- raise ArgumentError, "cannot whitelist and require the same keys"
38
- end
39
- end
40
-
41
- # Sends {#method_name} to `chain`, extracting arguments from `params`. If
42
- # values are missing for any {#keys}, return the `chain` unmodified.
43
- # If {#required? required}, errors are added to the {Query} instance as
44
- # well.
45
- #
46
- # @param [Hash] params hash of query parameters
47
- # @param [ActiveRecord::Relation, ActiveRecord::Base] relation scope chain
48
- # @return [ActiveRecord::Relation]
49
- def chain(params, relation)
50
- scope = relation.respond_to?(:klass) ? relation.klass.method(method_name) : relation.method(method_name)
51
-
52
- inputs = keys.map do |key|
53
- input = params[key]
54
-
55
- if input.nil?
56
- break if required.include?(key)
57
- break [] if !whitelist.include?(key)
58
- end
59
-
60
- input
61
- end
62
-
63
- if inputs.nil?
64
- return
65
- elsif inputs.empty?
66
- return relation
67
- end
68
-
69
- scope.arity == 0 ? relation.send(method_name) : relation.send(method_name, *inputs)
70
- end
71
-
72
- private
73
-
74
- def register_keys(option)
75
- option == true ? Array(keys) : Array(option)
76
- end
77
- end
78
- end
@@ -1,46 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Paraphrase
4
- describe ScopeMapping do
5
-
6
- describe "#chain" do
7
- let(:mapping) { ScopeMapping.new(:name_like, :to => :name) }
8
-
9
- it "applies scope method to relation with values from params hash" do
10
- Account.should_receive(:name_like).with('Jon Snow')
11
-
12
- mapping.chain({ :name => 'Jon Snow' }, Account)
13
- end
14
-
15
- it "does nothing if values are missing" do
16
- Account.should_not_receive(:name_like).with('Jon Snow')
17
-
18
- mapping.chain({}, Account)
19
- end
20
-
21
- it "passes through nil values if scope has been whitelisted" do
22
- mapping = ScopeMapping.new(:name_like, :to => :name, :whitelist => true)
23
-
24
- Account.should_receive(:name_like).with(nil)
25
-
26
- mapping.chain({}, Account)
27
- end
28
- end
29
-
30
- describe "compound keys" do
31
- let(:compound_mapping) do
32
- ScopeMapping.new(:name_like, :to => [:first_name, :last_name], :require => :last_name)
33
- end
34
-
35
- it "can require a subset of a compound key" do
36
- Account.should_receive(:name_like).with(nil, 'Lannister')
37
-
38
- compound_mapping.chain({ :last_name => 'Lannister' }, Account)
39
- end
40
-
41
- it "whitelists the the non-required keys of a compound key" do
42
- compound_mapping.whitelist.include?(:first_name).should be_true
43
- end
44
- end
45
- end
46
- end
@@ -1,38 +0,0 @@
1
- require 'active_record'
2
-
3
- ActiveRecord::Relation.send(:include, Paraphrase::Syntax::Relation)
4
-
5
- ActiveRecord::Base.establish_connection(
6
- :adapter => 'sqlite3',
7
- :database => ':memory:'
8
- )
9
-
10
- ActiveRecord::Migration.verbose = false
11
- ActiveRecord::Schema.define do
12
- create_table :users, :force => true do
13
- end
14
-
15
- create_table :accounts, :force => true do |t|
16
- t.references :user
17
- end
18
- end
19
-
20
- class User < ActiveRecord::Base
21
- has_many :accounts
22
- end
23
-
24
- class Account < ActiveRecord::Base
25
- extend Paraphrase::Syntax::Base
26
- belongs_to :user
27
-
28
- def self.title_like(*args)
29
- ActiveRecord::VERSION::MAJOR > 3 ? all : scoped
30
- end
31
-
32
- def self.name_like(*args)
33
- ActiveRecord::VERSION::MAJOR > 3 ? all : scoped
34
- end
35
- end
36
-
37
- class AccountQuery < Paraphrase::Query
38
- end