spyke 1.5.0 → 1.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
  SHA1:
3
- metadata.gz: 0d5dfe590d65f64f97fda8760b3c75ea3900d494
4
- data.tar.gz: be9546662e362944f6ea66373c76821e23d1acb1
3
+ metadata.gz: d8c05691c5a62ac3b717844d0c3f87890ab7c902
4
+ data.tar.gz: 7edc244c8975b0ec3c5f1887e53866fafb8dde04
5
5
  SHA512:
6
- metadata.gz: af83b406e410df06ea8fcb0ab4eee9c811ec1a38e3ebaefefd0d83bcac4ced8436130b4f49ed370264795d21a11bdfe32f6abc0bad3443d25d4fcc061f5f68a5
7
- data.tar.gz: 10a68a38089bf195ace08b6a9e90010e383113dba3e6c6b11e7bf49079bdbde93fb94367a3e8333400ce269b967b3a096ebab641f038b7a9d30294aeb99c9c49
6
+ metadata.gz: 05a0f43e35a3411bfab96a7825ad75a9721d3177fc90d1c6b26a29c9d68e43e5476448c14bbba8972ac4d7458efd64a89a04acac929340551d0378f64717b5cb
7
+ data.tar.gz: e1a53e75a003f0a7dba3c0ecf5151a7b40477b97ab5cc85ddce8e1535ca875ba79c00a04ab679dd3d1904d70049ddf29163a9c2cac6c22ddbd6fffd21ca8a991
@@ -15,8 +15,19 @@ module Spyke
15
15
  find_one # Override for plural associations that return an association object
16
16
  end
17
17
 
18
+ def find_one
19
+ result = super
20
+ update_parent(result) if result
21
+ end
22
+
23
+ def find_some
24
+ result = super
25
+ update_parent(result) if result.any?
26
+ result
27
+ end
28
+
18
29
  def assign_nested_attributes(attributes)
19
- parent.attributes[name] = new(attributes).attributes
30
+ update_parent new(attributes)
20
31
  end
21
32
 
22
33
  def create(attributes = {})
@@ -27,15 +38,12 @@ module Spyke
27
38
  add_to_parent super
28
39
  end
29
40
 
30
- def build(*args)
31
- new(*args)
32
- end
41
+ alias :build :new
33
42
 
34
43
  private
35
44
 
36
45
  def add_to_parent(record)
37
- parent.attributes[name] = record.attributes
38
- record
46
+ update_parent record
39
47
  end
40
48
 
41
49
  def foreign_key
@@ -47,15 +55,19 @@ module Spyke
47
55
  end
48
56
 
49
57
  def fetch_embedded
50
- if embedded_attributes
51
- Result.new(data: embedded_attributes)
58
+ if embedded_params
59
+ Result.new(data: embedded_params)
52
60
  elsif !uri
53
61
  Result.new(data: nil)
54
62
  end
55
63
  end
56
64
 
57
- def embedded_attributes
58
- parent.attributes[name]
65
+ def embedded_params
66
+ @embedded_params ||= parent.attributes.to_params[name]
67
+ end
68
+
69
+ def update_parent(value)
70
+ parent.attributes[name] = value
59
71
  end
60
72
  end
61
73
  end
@@ -11,36 +11,44 @@ module Spyke
11
11
  self
12
12
  end
13
13
 
14
- def assign_nested_attributes(collection)
15
- collection = collection.values if collection.is_a?(Hash)
16
- replace_existing! unless primary_keys_present?
17
-
18
- collection.each do |attributes|
19
- if existing = find_existing_attributes(attributes.with_indifferent_access[:id])
20
- existing.merge!(attributes)
21
- else
22
- build(attributes)
23
- end
14
+ def assign_nested_attributes(incoming)
15
+ incoming = incoming.values if incoming.is_a?(Hash)
16
+ combined_attributes = combine_with_existing(incoming)
17
+ clear_existing!
18
+ combined_attributes.each do |attributes|
19
+ build(attributes)
24
20
  end
25
21
  end
26
22
 
27
23
  private
28
24
 
29
- def find_existing_attributes(id)
30
- embedded_attributes.to_a.find { |attr| attr[:id] && attr[:id].to_s == id.to_s }
25
+ def combine_with_existing(incoming)
26
+ return incoming unless primary_keys_present_in_existing?
27
+ combined = embedded_params + incoming
28
+ group_by_primary_key(combined).flat_map do |primary_key, hashes|
29
+ if primary_key.present?
30
+ hashes.reduce(:merge)
31
+ else
32
+ hashes
33
+ end
34
+ end
35
+ end
36
+
37
+ def group_by_primary_key(array)
38
+ array.group_by { |h| h.with_indifferent_access[:id].to_s }
31
39
  end
32
40
 
33
- def primary_keys_present?
34
- embedded_attributes && embedded_attributes.any? { |attr| attr.has_key?(:id) }
41
+ def primary_keys_present_in_existing?
42
+ embedded_params && embedded_params.any? { |attr| attr.has_key?('id') }
35
43
  end
36
44
 
37
- def replace_existing!
38
- parent.attributes[name] = []
45
+ def clear_existing!
46
+ update_parent []
39
47
  end
40
48
 
41
49
  def add_to_parent(record)
42
50
  parent.attributes[name] ||= []
43
- parent.attributes[name] << record.attributes
51
+ parent.attributes[name] << record
44
52
  record
45
53
  end
46
54
  end
@@ -0,0 +1,111 @@
1
+ require 'spyke/collection'
2
+ require 'spyke/attributes'
3
+
4
+ module Spyke
5
+ module AttributeAssignment
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ attr_reader :attributes
10
+ end
11
+
12
+ module ClassMethods
13
+ def attributes(*args)
14
+ args.each do |attr|
15
+ define_method attr do
16
+ attribute(attr)
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def initialize(attributes = {})
23
+ self.attributes = attributes
24
+ @uri_template = scope.uri
25
+ end
26
+
27
+ def attributes=(new_attributes)
28
+ @attributes ||= Attributes.new(scope.params)
29
+ use_setters(new_attributes) if new_attributes
30
+ end
31
+
32
+ def id
33
+ attributes[:id]
34
+ end
35
+
36
+ def id=(value)
37
+ attributes[:id] = value if value.present?
38
+ end
39
+
40
+ def ==(other)
41
+ other.is_a?(Spyke::Base) && id == other.id
42
+ end
43
+
44
+ def inspect
45
+ "#<#{self.class}(#{uri}) id: #{id.inspect} #{inspect_attributes}>"
46
+ end
47
+
48
+ private
49
+
50
+ def use_setters(attributes)
51
+ attributes.each do |key, value|
52
+ send "#{key}=", value
53
+ end
54
+ end
55
+
56
+ def method_missing(name, *args, &block)
57
+ case
58
+ when association?(name) then association(name).load
59
+ when attribute?(name) then attribute(name)
60
+ when predicate?(name) then predicate(name)
61
+ when setter?(name) then set_attribute(name, args.first)
62
+ else super
63
+ end
64
+ end
65
+
66
+ def respond_to_missing?(name, include_private = false)
67
+ association?(name) || attribute?(name) || predicate?(name) || super
68
+ end
69
+
70
+ def association?(name)
71
+ associations.has_key?(name)
72
+ end
73
+
74
+ def association(name)
75
+ options = associations[name]
76
+ options[:type].new(self, name, options)
77
+ end
78
+
79
+ def attribute?(name)
80
+ attributes.has_key?(name)
81
+ end
82
+
83
+ def attribute(name)
84
+ attributes[name]
85
+ end
86
+
87
+ def predicate?(name)
88
+ name.to_s.end_with?('?')
89
+ end
90
+
91
+ def predicate(name)
92
+ !!attribute(depredicate(name))
93
+ end
94
+
95
+ def depredicate(name)
96
+ name.to_s.chomp('?').to_sym
97
+ end
98
+
99
+ def setter?(name)
100
+ name.to_s.end_with?('=')
101
+ end
102
+
103
+ def set_attribute(name, value)
104
+ attributes[name.to_s.chomp('=')] = value
105
+ end
106
+
107
+ def inspect_attributes
108
+ attributes.except(:id).map { |k, v| "#{k}: #{v.inspect}" }.join(' ')
109
+ end
110
+ end
111
+ end
@@ -1,126 +1,20 @@
1
- require 'spyke/collection'
2
-
3
1
  module Spyke
4
- module Attributes
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- attr_reader :attributes
9
- end
10
-
11
- module ClassMethods
12
- def attributes(*args)
13
- args.each do |attr|
14
- define_method attr do
15
- attribute(attr)
16
- end
17
- end
18
- end
19
- end
20
-
21
- def initialize(attributes = {})
22
- self.attributes = attributes
23
- @uri_template = current_scope.uri
24
- end
25
-
26
- def attributes=(new_attributes)
27
- @attributes ||= current_scope.params.with_indifferent_access
28
- use_setters parse(new_attributes) if new_attributes
29
- end
30
-
31
- def id
32
- attributes[:id]
33
- end
34
-
35
- def id=(value)
36
- attributes[:id] = value if value.present?
37
- end
38
-
39
- def ==(other)
40
- other.is_a?(Spyke::Base) && id == other.id
41
- end
42
-
43
- def inspect
44
- "#<#{self.class}(#{uri}) id: #{id.inspect} #{inspect_attributes}>"
2
+ class Attributes < HashWithIndifferentAccess
3
+ def to_params
4
+ each_with_object({}) do |(key, value), parameters|
5
+ parameters[key] = parse_value(value)
6
+ end.with_indifferent_access
45
7
  end
46
8
 
47
9
  private
48
10
 
49
- def parse(attributes)
50
- attributes.each_with_object({}) do |(key, value), parameters|
51
- parameters[key] = parse_value(value)
52
- end
53
- end
54
-
55
11
  def parse_value(value)
56
12
  case
57
- when value.is_a?(Spyke::Base) then parse(value.attributes)
58
- when value.is_a?(Hash) then parse(value)
13
+ when value.is_a?(Spyke::Base) then value.attributes.to_params
59
14
  when value.is_a?(Array) then value.map { |v| parse_value(v) }
60
15
  when value.respond_to?(:content_type) then Faraday::UploadIO.new(value.path, value.content_type)
61
16
  else value
62
17
  end
63
18
  end
64
-
65
- def use_setters(attributes)
66
- attributes.each do |key, value|
67
- send "#{key}=", value
68
- end
69
- end
70
-
71
- def method_missing(name, *args, &block)
72
- case
73
- when association?(name) then association(name).load
74
- when attribute?(name) then attribute(name)
75
- when predicate?(name) then predicate(name)
76
- when setter?(name) then set_attribute(name, args.first)
77
- else super
78
- end
79
- end
80
-
81
- def respond_to_missing?(name, include_private = false)
82
- association?(name) || attribute?(name) || predicate?(name) || super
83
- end
84
-
85
- def association?(name)
86
- associations.has_key?(name)
87
- end
88
-
89
- def association(name)
90
- options = associations[name]
91
- options[:type].new(self, name, options)
92
- end
93
-
94
- def attribute?(name)
95
- attributes.has_key?(name)
96
- end
97
-
98
- def attribute(name)
99
- attributes[name]
100
- end
101
-
102
- def predicate?(name)
103
- name.to_s.end_with?('?')
104
- end
105
-
106
- def predicate(name)
107
- !!attribute(depredicate(name))
108
- end
109
-
110
- def depredicate(name)
111
- name.to_s.chomp('?').to_sym
112
- end
113
-
114
- def setter?(name)
115
- name.to_s.end_with?('=')
116
- end
117
-
118
- def set_attribute(name, value)
119
- attributes[name.to_s.chomp('=')] = value
120
- end
121
-
122
- def inspect_attributes
123
- attributes.except(:id).map { |k, v| "#{k}: #{v.inspect}" }.join(' ')
124
- end
125
19
  end
126
20
  end
@@ -1,9 +1,10 @@
1
1
  require 'active_model'
2
2
  require 'spyke/associations'
3
- require 'spyke/attributes'
3
+ require 'spyke/attribute_assignment'
4
4
  require 'spyke/orm'
5
5
  require 'spyke/http'
6
- require 'spyke/scopes'
6
+ require 'spyke/scoping'
7
+
7
8
 
8
9
  module Spyke
9
10
  class Base
@@ -17,9 +18,9 @@ module Spyke
17
18
 
18
19
  # Spyke
19
20
  include Associations
20
- include Attributes
21
+ include AttributeAssignment
21
22
  include Http
22
23
  include Orm
23
- include Scopes
24
+ include Scoping
24
25
  end
25
26
  end
@@ -8,9 +8,6 @@ module Spyke
8
8
  extend ActiveSupport::Concern
9
9
  METHODS = %i{ get post put patch delete }
10
10
 
11
- included do
12
- end
13
-
14
11
  module ClassMethods
15
12
  METHODS.each do |method|
16
13
  define_method(method) do |path, params = {}|
@@ -50,9 +50,9 @@ module Spyke
50
50
 
51
51
  def to_params
52
52
  if include_root?
53
- { self.class.model_name.param_key => attributes.except(*uri.variables) }
53
+ { self.class.model_name.param_key => attributes.to_params.except(*uri.variables)}
54
54
  else
55
- attributes.except(*uri.variables)
55
+ attributes.to_params.except(*uri.variables)
56
56
  end
57
57
  end
58
58
 
@@ -5,19 +5,17 @@ module Spyke
5
5
  include Enumerable
6
6
 
7
7
  attr_reader :klass, :params
8
+ attr_writer :params
8
9
  delegate :to_ary, :[], :empty?, :last, :size, :metadata, to: :find_some
9
10
 
10
11
  def initialize(klass, options = {})
11
12
  @klass, @options, @params = klass, options, {}
12
13
  end
13
14
 
14
- def all
15
- where
16
- end
17
-
18
15
  def where(conditions = {})
19
- @params.merge!(conditions)
20
- self
16
+ relation = clone
17
+ relation.params = params.merge(conditions)
18
+ relation
21
19
  end
22
20
 
23
21
  # Overrides Enumerable find
@@ -53,10 +51,10 @@ module Spyke
53
51
 
54
52
  # Keep hold of current scope while running a method on the class
55
53
  def scoping
56
- klass.current_scope = self
54
+ previous, klass.current_scope = klass.current_scope, self
57
55
  yield
58
56
  ensure
59
- klass.current_scope = nil
57
+ klass.current_scope = previous
60
58
  end
61
59
  end
62
60
  end
@@ -2,11 +2,15 @@ require 'spyke/relation'
2
2
  require 'spyke/scope_registry'
3
3
 
4
4
  module Spyke
5
- module Scopes
5
+ module Scoping
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  module ClassMethods
9
- delegate :all, :where, to: :current_scope
9
+ delegate :where, :build, to: :all
10
+
11
+ def all
12
+ current_scope || Relation.new(self, uri: uri)
13
+ end
10
14
 
11
15
  def scope(name, code)
12
16
  define_singleton_method name, code
@@ -17,14 +21,14 @@ module Spyke
17
21
  end
18
22
 
19
23
  def current_scope
20
- ScopeRegistry.value_for(:current_scope, name) || Relation.new(self, uri: uri)
24
+ ScopeRegistry.value_for(:current_scope, name)
21
25
  end
22
26
  end
23
27
 
24
28
  private
25
29
 
26
- def current_scope
27
- self.class.current_scope
30
+ def scope
31
+ @scope ||= self.class.all
28
32
  end
29
33
  end
30
34
  end
@@ -1,3 +1,3 @@
1
1
  module Spyke
2
- VERSION = '1.5.0'
2
+ VERSION = '1.6.0'
3
3
  end
@@ -118,12 +118,37 @@ module Spyke
118
118
  assert_equal 1, recipe.groups.first.recipe_id
119
119
  end
120
120
 
121
+ def test_multiple_builds
122
+ recipe = Recipe.new
123
+ recipe.groups.build(name: 'Condiments')
124
+ recipe.groups.build(name: 'Tools')
125
+ assert_equal %w{ Condiments Tools }, recipe.groups.map(&:name)
126
+ end
127
+
121
128
  def test_new_has_many_association
122
129
  recipe = Recipe.new(id: 1)
123
130
  recipe.groups.new
124
131
  assert_equal 1, recipe.groups.first.recipe_id
125
132
  end
126
133
 
134
+ def test_changing_attributes_directly_after_build_on_has_many_association
135
+ recipe = Recipe.new(id: 1)
136
+ recipe.groups.build(name: 'Dessert')
137
+ recipe.groups.first.name = 'Starter'
138
+
139
+ assert_equal 'Starter', recipe.groups.first.name
140
+ assert_equal({ 'recipe' => { 'groups' => [{ 'recipe_id' => 1, 'name' => 'Starter' }] } }, recipe.to_params)
141
+ end
142
+
143
+ def test_changing_attributes_on_reference_after_build_on_has_many_association
144
+ recipe = Recipe.new(id: 1)
145
+ group = recipe.groups.build(name: 'Dessert')
146
+ group.name = 'Starter'
147
+
148
+ assert_equal 'Starter', recipe.groups.first.name
149
+ assert_equal({ 'recipe' => { 'groups' => [{ 'recipe_id' => 1, 'name' => 'Starter' }] } }, recipe.to_params)
150
+ end
151
+
127
152
  def test_deep_build_has_many_association
128
153
  recipe = Recipe.new(id: 1)
129
154
  recipe.groups.build(ingredients: [Ingredient.new(name: 'Salt')])
@@ -132,6 +157,16 @@ module Spyke
132
157
  assert_equal({ 'recipe' => { 'groups' => [{ 'recipe_id' => 1, 'ingredients' => [{ 'name' => 'Salt' }] }] } }, recipe.to_params)
133
158
  end
134
159
 
160
+ def test_sequential_deep_build_has_many_association
161
+ recipe = Recipe.new(id: 1)
162
+ recipe.groups.build
163
+ recipe.groups.first.ingredients.build(name: 'Salt')
164
+
165
+ assert_equal %w{ Salt }, recipe.ingredients.map(&:name)
166
+ assert_equal({ 'recipe' => { 'groups' => [{ 'recipe_id' => 1, 'ingredients' => [{ 'group_id' => nil, 'name' => 'Salt' }] }] } }, recipe.to_params)
167
+ assert_equal({ 'group' => { 'recipe_id' => 1, 'ingredients' => [{ 'group_id' => nil, 'name' => 'Salt' }] } }, recipe.groups.first.to_params)
168
+ end
169
+
135
170
  def test_deep_build_has_many_association_with_scope
136
171
  recipe = User.new(id: 1).recipes.published.build
137
172
 
@@ -168,7 +203,7 @@ module Spyke
168
203
  assert_equal Image, recipe.background_image.class
169
204
  end
170
205
 
171
- def test_cached_result
206
+ def test_cached_result_for_associations
172
207
  endpoint_1 = stub_request(:get, 'http://sushi.com/recipes/1/groups?per_page=3')
173
208
  endpoint_2 = stub_request(:get, 'http://sushi.com/recipes/1/groups')
174
209
 
@@ -250,9 +285,15 @@ module Spyke
250
285
 
251
286
  def test_nested_attributes_merging_with_existing_when_ids_present?
252
287
  recipe = Recipe.new(groups_attributes: [{ id: 1, title: 'starter', description: 'nice' }, { id: 2, title: 'sauce', description: 'spicy' }])
253
- recipe.attributes = { groups_attributes: [{ 'id' => '2', 'title' => 'flavor' }] }
254
- assert_equal %w{ starter flavor }, recipe.groups.map(&:title)
255
- assert_equal %w{ nice spicy }, recipe.groups.map(&:description)
288
+ recipe.attributes = { groups_attributes: [{ 'id' => '2', 'title' => 'flavor' }, { 'title' => 'spices', 'description' => 'lovely' }, { 'title' => 'sweetener', 'description' => 'sweet' }] }
289
+ assert_equal %w{ starter flavor spices sweetener }, recipe.groups.map(&:title)
290
+ assert_equal %w{ nice spicy lovely sweet }, recipe.groups.map(&:description)
291
+ end
292
+
293
+ def test_nested_attributes_appending_to_existing_when_ids_present?
294
+ recipe = Recipe.new(groups_attributes: [{ id: 1, title: 'starter' }, { id: 2, title: 'sauce' }])
295
+ recipe.attributes = { groups_attributes: [{ title: 'flavor' }] }
296
+ assert_equal %w{ starter sauce flavor }, recipe.groups.map(&:title)
256
297
  end
257
298
 
258
299
  def test_nested_attributes_has_many_using_hash_syntax
@@ -307,5 +348,14 @@ module Spyke
307
348
  assert_equal [], Group.new.ingredients.to_a
308
349
  assert_equal [1], Group.new(ingredients: [{ id: 1 }]).ingredients.map(&:id)
309
350
  end
351
+
352
+ def test_class_methods_for_associations
353
+ recipe = Recipe.new
354
+ recipe.groups.build_default
355
+
356
+ assert_equal({ 'recipe' => { 'groups' => [{ 'recipe_id' => nil, 'name' => 'Condiments', 'ingredients' => [{ 'group_id' => nil, 'name' => 'Salt' }] }, { 'recipe_id' => nil, 'name' => 'Tools', 'ingredients' => [{ 'group_id' => nil, 'name' => 'Spoon' }] }] } }, recipe.to_params)
357
+ assert_equal %w{ Condiments Tools }, recipe.groups.map(&:name)
358
+ assert_equal %w{ Salt Spoon }, recipe.ingredients.map(&:name)
359
+ end
310
360
  end
311
361
  end
@@ -2,6 +2,12 @@ require 'test_helper'
2
2
 
3
3
  module Spyke
4
4
  class AttributesTest < MiniTest::Test
5
+
6
+ def test_basics
7
+ attr = Attributes.new(id: 3, 'title' => 'Fish', groups: [ Group.new(name: 'Starter'), { name: 'Dessert' } ])
8
+ assert_equal({ 'id' => 3 , 'title' => 'Fish', 'groups' => [{ 'name' => 'Starter' }, { 'name' => 'Dessert' }] }, attr.to_params)
9
+ end
10
+
5
11
  def test_predicate_methods
6
12
  stub_request(:get, 'http://sushi.com/recipes/1').to_return_json(result: { id: 1, title: 'Sushi' })
7
13
 
@@ -12,6 +12,32 @@ module Spyke
12
12
  assert_equal 'meta', recipes.metadata
13
13
  end
14
14
 
15
+ def test_scope_independence
16
+ endpoint = stub_request(:get, 'http://sushi.com/recipes?query=chicken')
17
+ wrong_endpoint = stub_request(:get, 'http://sushi.com/recipes?query=chicken&page=1')
18
+
19
+ search = Search.new('chicken')
20
+ variant = search.recipes.where(page: 1)
21
+ original = search.recipes
22
+
23
+ refute_same variant, original
24
+
25
+ original.to_a
26
+
27
+ assert_not_requested wrong_endpoint
28
+ assert_requested endpoint, times: 1
29
+ end
30
+
31
+ def test_scope_not_firing_twice_for_duplicate_scope
32
+ endpoint = stub_request(:get, 'http://sushi.com/recipes?query=chicken')
33
+
34
+ search = Search.new('chicken')
35
+ search.recipes.page.to_a
36
+ search.suggestions
37
+
38
+ assert_requested endpoint, times: 1
39
+ end
40
+
15
41
  def test_scope_with_find
16
42
  endpoint = stub_request(:get, 'http://sushi.com/recipes/1?status=published').to_return_json(result: { id: 1 })
17
43
 
@@ -15,12 +15,14 @@ class Recipe < Spyke::Base
15
15
 
16
16
  accepts_nested_attributes_for :image, :user, :groups
17
17
 
18
- def self.page(number)
19
- where(page: number)
18
+ def self.page(number = nil)
19
+ result = all
20
+ result = result.where(page: number) if number
21
+ result
20
22
  end
21
23
 
22
24
  def ingredients
23
- groups.first.ingredients
25
+ groups.flat_map(&:ingredients)
24
26
  end
25
27
 
26
28
  private
@@ -47,6 +49,13 @@ end
47
49
  class Group < Spyke::Base
48
50
  has_many :ingredients, uri: nil
49
51
  accepts_nested_attributes_for :ingredients
52
+
53
+ def self.build_default
54
+ group_1 = build(name: 'Condiments')
55
+ group_1.ingredients.build(name: 'Salt')
56
+ group_2 = build(name: 'Tools')
57
+ group_2.ingredients.build(name: 'Spoon')
58
+ end
50
59
  end
51
60
 
52
61
  class Ingredient < Spyke::Base
@@ -64,3 +73,17 @@ end
64
73
  class Comment < Spyke::Base
65
74
  scope :approved, -> { where(comment_approved: true) }
66
75
  end
76
+
77
+ class Search
78
+ def initialize(query)
79
+ @query = query
80
+ end
81
+
82
+ def recipes
83
+ @recipes ||= Recipe.where(query: @query)
84
+ end
85
+
86
+ def suggestions
87
+ recipes.metadata[:suggestions]
88
+ end
89
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spyke
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jens Balvig
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-09 00:00:00.000000000 Z
11
+ date: 2015-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -270,6 +270,7 @@ files:
270
270
  - lib/spyke/associations/belongs_to.rb
271
271
  - lib/spyke/associations/has_many.rb
272
272
  - lib/spyke/associations/has_one.rb
273
+ - lib/spyke/attribute_assignment.rb
273
274
  - lib/spyke/attributes.rb
274
275
  - lib/spyke/base.rb
275
276
  - lib/spyke/collection.rb
@@ -284,7 +285,7 @@ files:
284
285
  - lib/spyke/relation.rb
285
286
  - lib/spyke/result.rb
286
287
  - lib/spyke/scope_registry.rb
287
- - lib/spyke/scopes.rb
288
+ - lib/spyke/scoping.rb
288
289
  - lib/spyke/version.rb
289
290
  - spyke.gemspec
290
291
  - test/associations_test.rb