paraphrase 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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