spyke 1.5.0 → 1.6.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.
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