mince 2.0.0.pre.4 → 2.0.1

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.
@@ -8,7 +8,7 @@ require_relative 'config'
8
8
  module Mince # :nodoc:
9
9
  # = DataModel
10
10
  #
11
- # Mince::DataModel is used as a mixin to easily mixin behavior into an object that
11
+ # Mince::DataModel is used as a mixin to easily mixin behavior into an object that
12
12
  # you wish to act as a data model and interact with mince data interfaces.
13
13
  #
14
14
  # Simply mixin this module in order to get a wrapper class to interact with a mince
@@ -103,7 +103,7 @@ module Mince # :nodoc:
103
103
 
104
104
  # Increments a field by a given amount
105
105
  #
106
- # Some databases provide very efficient algorithms for incrementing or decrementing a
106
+ # Some databases provide very efficient algorithms for incrementing or decrementing a
107
107
  # value.
108
108
  #
109
109
  # @param [id] id the id of the record to update
@@ -119,7 +119,7 @@ module Mince # :nodoc:
119
119
  # @param [Symbol] field the field to update
120
120
  # @param [*] value the value to update the field with
121
121
  def remove_from_array(id, field, value)
122
- interface.remove_from_array(data_collection, interface.primary_key, id, field, value)
122
+ interface.remove_from_array(data_collection, id, field, value)
123
123
  end
124
124
 
125
125
  # Pushes a value to an array field
@@ -128,7 +128,7 @@ module Mince # :nodoc:
128
128
  # @param [Symbol] field the field to update
129
129
  # @param [*] value the value to update the field with
130
130
  def push_to_array(id, field, value)
131
- interface.push_to_array(data_collection, interface.primary_key, id, field, value)
131
+ interface.push_to_array(data_collection, id, field, value)
132
132
  end
133
133
 
134
134
  # Returns a record that has the given id
@@ -138,7 +138,7 @@ module Mince # :nodoc:
138
138
  # @param [id] id the id of the record to find
139
139
  # @returns [HashWithIndifferentAccess, nil] a hash with the data for the record
140
140
  def find(id)
141
- translate_from_interface interface.find(data_collection, interface.primary_key, id)
141
+ translate_from_interface interface.find(data_collection, id)
142
142
  end
143
143
 
144
144
  # Deletes a field from all records in the collection
@@ -149,7 +149,7 @@ module Mince # :nodoc:
149
149
  end
150
150
 
151
151
 
152
- # Deletes a field from all records that matches the field / value key pairs in the
152
+ # Deletes all records that matches the field / value key pairs in the
153
153
  # params provided in the collection
154
154
  #
155
155
  # This will only delete records that match all key/value pairs in the params hash.
@@ -225,11 +225,23 @@ module Mince # :nodoc:
225
225
  interface.delete_collection(data_collection)
226
226
  end
227
227
 
228
- private
228
+ # Generates a new id to be used for a primary key
229
+ def generate_unique_id(seed)
230
+ interface.generate_unique_id(seed)
231
+ end
232
+
233
+ # Adds a new record with provided data hash
234
+ #
235
+ # @param [Hash] data to add to the data collection
236
+ # @returns [Hash] the data that was added to the data collection, including the uniquely generated id
237
+ def add(hash)
238
+ hash = HashWithIndifferentAccess.new(hash.merge(primary_key => generate_unique_id(hash)))
239
+ interface.add(data_collection, hash).first
240
+ end
229
241
 
230
242
  def translate_from_interface(hash)
231
243
  if hash
232
- hash["id"] = hash[primary_key] if hash[primary_key]
244
+ hash["id"] = hash[primary_key] if hash[primary_key] && (primary_key != :id || primary_key != 'id')
233
245
  HashWithIndifferentAccess.new hash
234
246
  end
235
247
  end
@@ -238,6 +250,8 @@ module Mince # :nodoc:
238
250
  data.collect {|d| translate_from_interface(d) }
239
251
  end
240
252
 
253
+ private
254
+
241
255
  def primary_key
242
256
  @primary_key ||= interface.primary_key
243
257
  end
@@ -293,7 +307,7 @@ module Mince # :nodoc:
293
307
  end
294
308
 
295
309
  def generated_id
296
- interface.generate_unique_id(model)
310
+ self.class.generate_unique_id(model)
297
311
  end
298
312
 
299
313
  def model_has_id?
data/lib/mince/model.rb CHANGED
@@ -1,9 +1,9 @@
1
- require 'active_support'
2
- require 'active_model'
3
- require 'active_support/core_ext/module/delegation'
4
- require 'active_support/core_ext/object/instance_variables'
5
-
6
1
  module Mince
2
+ require_relative 'model/fields'
3
+ require_relative 'model/persistence'
4
+ require_relative 'model/finders'
5
+ require_relative 'model/data_model'
6
+
7
7
  # = Model
8
8
  #
9
9
  # The mince model is a module that provides standard model to data behavior to the Mince data model mixing for a specific model.
@@ -31,131 +31,29 @@ module Mince
31
31
  # book = Book.new title: 'The World In Photographs', publisher: 'National Geographic'
32
32
  # book.save
33
33
  #
34
- # View the docs for each method available
34
+ # By including this module, you are including DataModel, Fields, Persistence, and Finders.
35
+ #
36
+ # However, you can choose which modules you would like by including those modules individually
37
+ # so that you can have flexibility an lighter weight help to implement your models.
38
+ #
39
+ # class AvailableBook
40
+ # include Mince::Model::DataModel
41
+ #
42
+ # data_collection :books
43
+ #
44
+ # def self.all
45
+ # data_collection.all_by_fields(library: "St. Louis - Downtown", available: true).map{ |a| new(a) }
46
+ # end
47
+ # end
48
+ #
35
49
  module Model
36
50
  extend ActiveSupport::Concern
37
51
 
38
52
  included do
39
- include ActiveModel::Conversion
40
- extend ActiveModel::Naming
41
-
42
- attr_accessor :id
43
- end
44
-
45
- module ClassMethods
46
- # Sets or returns the data model class for the model
47
- def data_model(model=nil)
48
- @data_model = model if model
49
- @data_model
50
- end
51
-
52
- # Returns all models from the data model
53
- def all
54
- data_model.all.map{|a| new a }
55
- end
56
-
57
- # Returns a model that matches a given id, returns nil if none found
58
- def find(id)
59
- a = data_model.find(id)
60
- new a if a
61
- end
62
-
63
- # Adds a field to the object. Takes options to indicate assignability. If `assignable`
64
- # is set, the field will be assignable via
65
- # model.field = 'foo'
66
- # model.attributes = { field: 'foo' }
67
- #
68
- def field(field_name, options={})
69
- if options[:assignable]
70
- add_assignable_field(field_name)
71
- else
72
- add_readonly_field(field_name)
73
- end
74
- end
75
-
76
- # Adds a read only field, values for these fields can only be set in the class itself
77
- # or from the hash sent in to the initializer
78
- def add_readonly_field(field_name)
79
- fields << field_name
80
- readonly_fields << field_name
81
- attr_reader field_name
82
- end
83
-
84
- # Adds an assignable field, values for these fields can be set using the field writer
85
- # or from the `attributes=` method.
86
- def add_assignable_field(field_name)
87
- fields << field_name
88
- assignable_fields << field_name
89
- attr_accessor field_name
90
- end
91
-
92
- # Adds multiple readonly fields to the fields array, and returns the current list
93
- # of fields. If no fields are given, it just returns the current list of fields
94
- def fields(*field_names)
95
- @fields ||= []
96
- field_names.each {|field_name| field(field_name) }
97
- @fields
98
- end
99
-
100
- # Returns the list of assignable fields
101
- def assignable_fields
102
- @assignable_fields ||= []
103
- end
104
-
105
- # Returns the list of readonly fields
106
- def readonly_fields
107
- @readonly_fields ||= []
108
- end
109
- end
110
-
111
- delegate :data_model, :assignable_fields, :readonly_fields, :fields, to: 'self.class'
112
-
113
- # Sets values (for fields defined by calling .field or .fields) in the hash to the object
114
- # includes assignable and non-assignable fields
115
- def initialize(hash={})
116
- @id = hash[:id]
117
- readonly_fields.each do |field_name|
118
- self.instance_variable_set("@#{field_name}", hash[field_name]) if hash[field_name]
119
- end
120
- self.attributes = hash
121
- end
122
-
123
- # Returns true if the record indicates that it has been persisted to a data model.
124
- # Returns false otherwise.
125
- def persisted?
126
- !!id
127
- end
128
-
129
- # Saves the object to the data model. Stores if new, updates previous entry if it has already
130
- # been saved.
131
- def save
132
- ensure_no_extra_fields
133
- if persisted?
134
- data_model.update(self)
135
- else
136
- @id = data_model.store(self)
137
- end
138
- end
139
-
140
- # Sets values (for assignable fields only, defined by calling .field or .fields) in the hash
141
- # to the object.
142
- #
143
- # Allows the proxy to have whitelisted attributes to be assigned from http requests.
144
- def attributes=(hash={})
145
- assignable_fields.each do |field|
146
- send("#{field}=", hash[field]) if hash[field]
147
- end
148
- end
149
-
150
- private
151
-
152
- # Ensures that the data model has all of the fields that are trying to be saved. Raises an
153
- # exception if the data model does not.
154
- def ensure_no_extra_fields
155
- extra_fields = (fields - data_model.data_fields)
156
- if extra_fields.any?
157
- raise "Tried to save a #{self.class.name} with fields not specified in #{data_model.name}: #{extra_fields.join(', ')}"
158
- end
53
+ include DataModel
54
+ include Fields
55
+ include Persistence
56
+ include Finders
159
57
  end
160
58
  end
161
59
  end
@@ -0,0 +1,31 @@
1
+ module Mince
2
+ module Model
3
+ require 'active_support'
4
+
5
+ module DataModel
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ # Sets or returns the data model class for the model
10
+ def data_model(model=nil)
11
+ @data_model = model if model
12
+ @data_model
13
+ end
14
+ end
15
+
16
+ protected
17
+
18
+ # Ensures that the data model has all of the fields that are trying to be saved. Raises an
19
+ # exception if the data model does not.
20
+ #
21
+ # Not sure if this is where this method should live, it requires both
22
+ # Mince::Model::DataModel and Mince::Model::Fields.
23
+ def ensure_no_extra_fields
24
+ extra_fields = (fields - data_model.data_fields)
25
+ if extra_fields.any?
26
+ raise "Tried to save a #{self.class.name} with fields not specified in #{data_model.name}: #{extra_fields.join(', ')}"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,89 @@
1
+ module Mince
2
+ module Model
3
+ require 'active_support'
4
+ require 'active_support/core_ext/module/delegation'
5
+ require 'active_support/core_ext/object/instance_variables'
6
+ require_relative 'data_model'
7
+
8
+ module Fields
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include Mince::Model::DataModel
13
+
14
+ attr_accessor :id
15
+ end
16
+
17
+ module ClassMethods
18
+ # Adds a field to the object. Takes options to indicate assignability. If `assignable`
19
+ # is set, the field will be assignable via
20
+ # model.field = 'foo'
21
+ # model.attributes = { field: 'foo' }
22
+ #
23
+ def field(field_name, options={})
24
+ if options[:assignable]
25
+ add_assignable_field(field_name)
26
+ else
27
+ add_readonly_field(field_name)
28
+ end
29
+ end
30
+
31
+ # Adds a read only field, values for these fields can only be set in the class itself
32
+ # or from the hash sent in to the initializer
33
+ def add_readonly_field(field_name)
34
+ fields << field_name
35
+ readonly_fields << field_name
36
+ attr_reader field_name
37
+ end
38
+
39
+ # Adds an assignable field, values for these fields can be set using the field writer
40
+ # or from the `attributes=` method.
41
+ def add_assignable_field(field_name)
42
+ fields << field_name
43
+ assignable_fields << field_name
44
+ attr_accessor field_name
45
+ end
46
+
47
+ # Adds multiple readonly fields to the fields array, and returns the current list
48
+ # of fields. If no fields are given, it just returns the current list of fields
49
+ def fields(*field_names)
50
+ @fields ||= []
51
+ field_names.each {|field_name| field(field_name) }
52
+ @fields
53
+ end
54
+
55
+ # Returns the list of assignable fields
56
+ def assignable_fields
57
+ @assignable_fields ||= []
58
+ end
59
+
60
+ # Returns the list of readonly fields
61
+ def readonly_fields
62
+ @readonly_fields ||= []
63
+ end
64
+ end
65
+
66
+ delegate :assignable_fields, :readonly_fields, :fields, to: 'self.class'
67
+
68
+ # Sets values (for fields defined by calling .field or .fields) in the hash to the object
69
+ # includes assignable and non-assignable fields
70
+ def initialize(hash={})
71
+ @id = hash[:id]
72
+ readonly_fields.each do |field_name|
73
+ self.instance_variable_set("@#{field_name}", hash[field_name]) if hash[field_name]
74
+ end
75
+ self.attributes = hash
76
+ end
77
+
78
+ # Sets values (for assignable fields only, defined by calling .field or .fields) in the hash
79
+ # to the object.
80
+ #
81
+ # Allows the proxy to have whitelisted attributes to be assigned from http requests.
82
+ def attributes=(hash={})
83
+ assignable_fields.each do |field|
84
+ send("#{field}=", hash[field]) if hash[field]
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,32 @@
1
+ module Mince
2
+ module Model
3
+ require 'active_support'
4
+ require_relative 'data_model'
5
+
6
+ module Finders
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ include Mince::Model::DataModel
11
+ end
12
+
13
+ module ClassMethods
14
+ # Sets or returns the data model class for the model
15
+ def find_by_fields(*fields)
16
+ raise 'not implemented'
17
+ end
18
+
19
+ # Returns all models from the data model
20
+ def all
21
+ data_model.all.map{|a| new a }
22
+ end
23
+
24
+ # Returns a model that matches a given id, returns nil if none found
25
+ def find(id)
26
+ a = data_model.find(id)
27
+ new a if a
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ module Mince
2
+ module Model
3
+ require 'active_support'
4
+ require 'active_model'
5
+ require 'active_support/core_ext/module/delegation'
6
+ require_relative 'data_model'
7
+
8
+ module Persistence
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include Mince::Model::DataModel
13
+ include ActiveModel::Conversion
14
+ extend ActiveModel::Naming
15
+ end
16
+
17
+ module ClassMethods
18
+ # Creates a record with the given field values
19
+ def create(data)
20
+ new(data).tap(&:save)
21
+ end
22
+ end
23
+
24
+ delegate :data_model, to: 'self.class'
25
+
26
+ # Returns true if the record indicates that it has been persisted to a data model.
27
+ # Returns false otherwise.
28
+ def persisted?
29
+ !!id
30
+ end
31
+
32
+ # Saves the object to the data model. Stores if new, updates previous entry if it has already
33
+ # been saved.
34
+ def save
35
+ ensure_no_extra_fields if self.respond_to?(:ensure_no_extra_fields)
36
+
37
+ if persisted?
38
+ data_model.update(self)
39
+ else
40
+ @id = data_model.store(self)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -103,24 +103,19 @@ shared_examples_for 'a mince interface' do
103
103
  data2[:field_1] = 'value modified'
104
104
  interface.replace(:some_collection, data2)
105
105
 
106
- convert(interface.find(:some_collection, primary_key, 2))[:field_1].should == 'value modified'
106
+ convert(interface.find(:some_collection, 2))[:field_1].should == 'value modified'
107
107
  end
108
108
 
109
109
  it 'can update a field with a value on a specific record' do
110
110
  interface.update_field_with_value(:some_collection, 3, :field_2, '10')
111
111
 
112
- convert(interface.find(:some_collection, primary_key, 3))[:field_2].should == '10'
112
+ convert(interface.find(:some_collection, 3))[:field_2].should == '10'
113
113
  end
114
114
 
115
115
  it 'can increment a field with a given amount for a specific field' do
116
116
  interface.increment_field_by_amount(:some_collection, 1, :field_2, 3)
117
117
 
118
- convert(interface.find(:some_collection, primary_key, 1))[:field_2].should == 6
119
- end
120
-
121
- it 'can get one document' do
122
- convert(interface.find(:some_collection, :field_1, 'value 1')).should == convert(data1)
123
- convert(interface.find(:some_collection, :field_2, 6)).should == convert(data2)
118
+ convert(interface.find(:some_collection, 1))[:field_2].should == 6
124
119
  end
125
120
 
126
121
  it 'can clear the data store' do
@@ -145,18 +140,18 @@ shared_examples_for 'a mince interface' do
145
140
  end
146
141
 
147
142
  it 'can push a value to an array for a specific record' do
148
- interface.push_to_array(:some_collection, primary_key, 1, :field_3, 'add to existing array')
149
- interface.push_to_array(:some_collection, primary_key, 1, :new_field, 'add to new array')
143
+ interface.push_to_array(:some_collection, 1, :field_3, 'add to existing array')
144
+ interface.push_to_array(:some_collection, 1, :new_field, 'add to new array')
150
145
 
151
- record = convert(interface.find(:some_collection, primary_key, 1))
146
+ record = convert(interface.find(:some_collection, 1))
152
147
  record[:field_3].should include('add to existing array')
153
148
  record[:new_field].should == ['add to new array']
154
149
  end
155
150
 
156
151
  it 'can remove a value from an array for a specific record' do
157
- interface.remove_from_array(:some_collection, primary_key, 1, :field_3, 2)
152
+ interface.remove_from_array(:some_collection, 1, :field_3, 2)
158
153
 
159
- convert(interface.find(:some_collection, primary_key, 1))[:field_3].should_not include(2)
154
+ convert(interface.find(:some_collection, 1))[:field_3].should_not include(2)
160
155
  end
161
156
 
162
157
  it 'can get all records that match a given set of keys and values' do
data/lib/mince/version.rb CHANGED
@@ -9,7 +9,7 @@ module Mince
9
9
  end
10
10
 
11
11
  def self.patch
12
- '0.pre.4'
12
+ 1
13
13
  end
14
14
  end
15
15
 
@@ -0,0 +1,42 @@
1
+ require 'mince'
2
+ require 'hashy_db'
3
+
4
+ describe 'A mince data model integration spec' do
5
+ let(:attributes) { { brand: brand, price: price, type: type, color: color } }
6
+ let(:brand) { mock }
7
+ let(:price) { mock }
8
+ let(:type) { mock }
9
+ let(:color) { mock }
10
+ let(:primary_key) { Mince::HashyDb::Interface.primary_key}
11
+
12
+ let(:data_model_klass) do
13
+ Class.new do
14
+ include Mince::DataModel
15
+
16
+ data_collection :guitars
17
+ data_fields :brand, :price, :type, :color
18
+ end
19
+ end
20
+
21
+ before do
22
+ Mince::Config.interface = Mince::HashyDb::Interface
23
+ Mince::HashyDb::Interface.clear
24
+ end
25
+
26
+ after do
27
+ Mince::HashyDb::Interface.clear
28
+ end
29
+
30
+ it 'can insert data directly to the data collection' do
31
+ result = data_model_klass.add attributes
32
+
33
+ all = data_model_klass.all
34
+ all.size.should == 1
35
+ [all.first, result].each do |object|
36
+ %w(brand price type color).each do |field|
37
+ object[field.to_sym].should == attributes[field.to_sym]
38
+ end
39
+ object[primary_key].should_not be_nil
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,106 @@
1
+ require 'mince'
2
+ require 'hashy_db'
3
+
4
+ describe 'A mince model integration spec' do
5
+ subject { model_klass.new attributes }
6
+
7
+ let(:attributes) { { brand: brand, price: price, type: type, color: color } }
8
+ let(:brand) { mock }
9
+ let(:price) { mock }
10
+ let(:type) { mock }
11
+ let(:color) { mock }
12
+
13
+ before do
14
+ Mince::Config.interface = Mince::HashyDb::Interface
15
+ Mince::HashyDb::Interface.clear
16
+ end
17
+
18
+ after do
19
+ Mince::HashyDb::Interface.clear
20
+ end
21
+
22
+ describe 'a model with a limited set of mince model mixins' do
23
+ let(:model_klass) do
24
+ Class.new do
25
+ include Mince::Model::Fields
26
+
27
+ data_model(
28
+ Class.new do
29
+ include Mince::DataModel
30
+
31
+ data_collection :guitars
32
+ data_fields :brand, :price, :type, :color
33
+ end
34
+ )
35
+ fields :brand, :price, :type, :color
36
+ end
37
+ end
38
+
39
+ it 'is initialized with the correct data' do
40
+ subject.brand.should == brand
41
+ subject.price.should == price
42
+ subject.type.should == type
43
+ subject.color.should == color
44
+ end
45
+
46
+ it 'cannot be persisted to the mince data interface' do
47
+ subject.respond_to?(:save).should be_false
48
+ end
49
+ end
50
+
51
+ describe 'a model with all mince model mixins' do
52
+ let(:model_klass) do
53
+ Class.new do
54
+ include Mince::Model
55
+
56
+ data_model(
57
+ Class.new do
58
+ include Mince::DataModel
59
+
60
+ data_collection :guitars
61
+ data_fields :brand, :price, :type, :color
62
+ end
63
+ )
64
+ fields :brand, :price, :type, :color
65
+ end
66
+ end
67
+
68
+ it 'is initialized with the correct data' do
69
+ subject.brand.should == brand
70
+ subject.price.should == price
71
+ subject.type.should == type
72
+ subject.color.should == color
73
+ end
74
+
75
+ it 'can be persisted to the mince data interface' do
76
+ subject.save
77
+
78
+ raw_record = Mince::Config.interface.find(:guitars, subject.id)
79
+ model_record = model_klass.find(subject.id)
80
+ raw_record[:brand].should == brand
81
+ model_record.brand.should == brand
82
+ end
83
+
84
+ context 'when not all fields are defined in the data model' do
85
+ let(:model_klass) do
86
+ Class.new do
87
+ include Mince::Model
88
+
89
+ data_model(
90
+ Class.new do
91
+ include Mince::DataModel
92
+
93
+ data_collection :guitars
94
+ data_fields :brand, :price, :type
95
+ end
96
+ )
97
+ fields :brand, :price, :type, :color
98
+ end
99
+ end
100
+
101
+ it 'raises an exception to provide feedback about the missing field' do
102
+ expect { subject.save }.to raise_exception(RuntimeError, "Tried to save a with fields not specified in : color")
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,16 @@
1
+ shared_examples_for 'a model using mince model data model' do
2
+ before do
3
+ begin
4
+ klass
5
+ rescue NameError
6
+ raise "You must define a `klass` spec variable to use the mince model finders shared example"
7
+ end
8
+ end
9
+
10
+ it 'can set and get the data model' do
11
+ data_model = mock 'data model'
12
+ klass.data_model(data_model)
13
+ klass.data_model.should == data_model
14
+ end
15
+ end
16
+
@@ -0,0 +1,59 @@
1
+ shared_examples_for 'a model using mince model finders' do
2
+ before do
3
+ begin
4
+ klass
5
+ rescue NameError
6
+ raise "You must define a `klass` spec variable to use the mince model finders shared example"
7
+ end
8
+ end
9
+
10
+ describe 'getting all models' do
11
+ subject { klass.all }
12
+
13
+ let(:model) { mock }
14
+ let(:models) { [model] }
15
+ let(:data) { [datum] }
16
+ let(:datum) { mock }
17
+
18
+ before do
19
+ klass.data_model.stub(all: data)
20
+ klass.stub(:new).with(datum).and_return(model)
21
+ end
22
+
23
+ it 'returns an array of all models' do
24
+ subject.should == models
25
+ end
26
+ end
27
+
28
+ describe 'finding a model by id' do
29
+ subject { klass.find(id) }
30
+
31
+ let(:id) { mock 'id' }
32
+
33
+ before do
34
+ klass.data_model.stub(:find).with(id).and_return(data)
35
+ end
36
+
37
+ context 'when it exists' do
38
+ let(:data) { mock 'data' }
39
+ let(:model) { mock 'model' }
40
+
41
+ before do
42
+ klass.stub(:new).with(data).and_return(model)
43
+ end
44
+
45
+ it 'returns the model' do
46
+ subject.should == model
47
+ end
48
+ end
49
+
50
+ context 'when it does not exist' do
51
+ let(:data) { nil }
52
+
53
+ it 'returns nothing' do
54
+ subject.should be_nil
55
+ end
56
+ end
57
+ end
58
+ end
59
+
@@ -31,6 +31,21 @@ describe Mince::DataModel, 'Mixin' do
31
31
  Mince::Config.stub(:interface => interface)
32
32
  end
33
33
 
34
+ describe "inserting data" do
35
+ let(:expected_hash) { data_field_attributes.merge(primary_key => unique_id) }
36
+
37
+ before do
38
+ interface.stub(:add).and_return([expected_hash])
39
+ interface.stub(:generate_unique_id).with(data_field_attributes).and_return(unique_id)
40
+ end
41
+
42
+ it 'adds the data to the db store with the generated id' do
43
+ interface.should_receive(:add).with(collection_name, HashWithIndifferentAccess.new(expected_hash)).and_return([expected_hash])
44
+
45
+ described_class.add(data_field_attributes).should == expected_hash
46
+ end
47
+ end
48
+
34
49
  describe "storing a data model" do
35
50
  let(:model) { mock 'a model', instance_values: data_field_attributes }
36
51
 
@@ -53,7 +68,7 @@ describe Mince::DataModel, 'Mixin' do
53
68
 
54
69
  it 'can delete the collection' do
55
70
  interface.should_receive(:delete_collection).with(collection_name)
56
-
71
+
57
72
  described_class.delete_collection
58
73
  end
59
74
 
@@ -90,7 +105,7 @@ describe Mince::DataModel, 'Mixin' do
90
105
 
91
106
  describe 'updating a specific field for a data model' do
92
107
  let(:data_model_id) { '1234567' }
93
-
108
+
94
109
  it 'has the data store update the field' do
95
110
  interface.should_receive(:update_field_with_value).with(collection_name, data_model_id, :some_field, 'some value')
96
111
 
@@ -112,7 +127,7 @@ describe Mince::DataModel, 'Mixin' do
112
127
  let(:data_model_id) { '1234567' }
113
128
 
114
129
  it 'replaces the data model in the db store' do
115
- interface.should_receive(:push_to_array).with(collection_name, primary_key, data_model_id, :array_field, 'some value')
130
+ interface.should_receive(:push_to_array).with(collection_name, data_model_id, :array_field, 'some value')
116
131
 
117
132
  described_class.push_to_array(data_model_id, :array_field, 'some value')
118
133
  end
@@ -135,7 +150,7 @@ describe Mince::DataModel, 'Mixin' do
135
150
  let(:data_model_id) { '1234567' }
136
151
 
137
152
  it 'removes the value from the array' do
138
- interface.should_receive(:remove_from_array).with(collection_name, primary_key, data_model_id, :array_field, 'some value')
153
+ interface.should_receive(:remove_from_array).with(collection_name, data_model_id, :array_field, 'some value')
139
154
 
140
155
  described_class.remove_from_array(data_model_id, :array_field, 'some value')
141
156
  end
@@ -220,7 +235,7 @@ describe Mince::DataModel, 'Mixin' do
220
235
  let(:data_model) { {primary_key => 'id', :id => 'id' } }
221
236
 
222
237
  it 'returns the data model from the data store' do
223
- interface.should_receive(:find).with(collection_name, primary_key, 'id').and_return(data_model)
238
+ interface.should_receive(:find).with(collection_name, 'id').and_return(data_model)
224
239
 
225
240
  described_class.find(data_model[:id]).should == HashWithIndifferentAccess.new(data_model)
226
241
  end
@@ -0,0 +1,14 @@
1
+ require_relative '../../../../lib/mince/model/data_model'
2
+ require_relative '../../../support/shared_examples/model_data_model_example'
3
+
4
+ describe Mince::Model::DataModel do
5
+ let(:klass) do
6
+ Class.new do
7
+ include Mince::Model::DataModel
8
+
9
+ data_model Class.new
10
+ end
11
+ end
12
+
13
+ it_behaves_like 'a model using mince model data model'
14
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../../../../lib/mince/model/finders'
2
+ require_relative '../../../support/shared_examples/model_finders_example'
3
+
4
+ describe Mince::Model::Finders do
5
+ let(:klass) do
6
+ Class.new do
7
+ include Mince::Model::Finders
8
+
9
+ data_model Class.new
10
+ end
11
+ end
12
+
13
+ it_behaves_like 'a model using mince model finders'
14
+ end
@@ -94,6 +94,15 @@ describe Mince::Model do
94
94
  end
95
95
 
96
96
  describe "Query Methods:" do
97
+ it 'provides a way to easily create a new record' do
98
+ model = mock 'model'
99
+ data = mock 'data'
100
+ klass.stub(:new).with(data).and_return(model)
101
+ model.should_receive(:save)
102
+
103
+ klass.create(data)
104
+ end
105
+
97
106
  describe 'finding a model by id' do
98
107
  subject { klass.find(id) }
99
108
 
@@ -126,3 +135,4 @@ describe Mince::Model do
126
135
  end
127
136
  end
128
137
  end
138
+
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mince
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.4
5
- prerelease: 6
4
+ version: 2.0.1
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Matt Simpson
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-11-02 00:00:00.000000000 Z
13
+ date: 2013-02-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -145,17 +145,17 @@ dependencies:
145
145
  requirement: !ruby/object:Gem::Requirement
146
146
  none: false
147
147
  requirements:
148
- - - '='
148
+ - - ~>
149
149
  - !ruby/object:Gem::Version
150
- version: 2.0.0.pre
150
+ version: '2.0'
151
151
  type: :development
152
152
  prerelease: false
153
153
  version_requirements: !ruby/object:Gem::Requirement
154
154
  none: false
155
155
  requirements:
156
- - - '='
156
+ - - ~>
157
157
  - !ruby/object:Gem::Version
158
- version: 2.0.0.pre
158
+ version: '2.0'
159
159
  - !ruby/object:Gem::Dependency
160
160
  name: rb-fsevent
161
161
  requirement: !ruby/object:Gem::Requirement
@@ -180,16 +180,25 @@ extensions: []
180
180
  extra_rdoc_files: []
181
181
  files:
182
182
  - lib/mince.rb
183
- - lib/mince/version.rb
184
183
  - lib/mince/config.rb
185
184
  - lib/mince/data_model.rb
186
185
  - lib/mince/model.rb
186
+ - lib/mince/version.rb
187
187
  - lib/mince/shared_examples/interface_example.rb
188
+ - lib/mince/model/data_model.rb
189
+ - lib/mince/model/fields.rb
190
+ - lib/mince/model/finders.rb
191
+ - lib/mince/model/persistence.rb
192
+ - spec/integration/mince_data_model_spec.rb
193
+ - spec/integration/mince_model_spec.rb
194
+ - spec/support/shared_examples/modeL_data_model_example.rb
195
+ - spec/support/shared_examples/model_finders_example.rb
196
+ - spec/units/mince/model/data_model_spec.rb
197
+ - spec/units/mince/model/finders_spec.rb
188
198
  - spec/units/mince/config_spec.rb
189
199
  - spec/units/mince/interface_example_spec.rb
190
200
  - spec/units/mince/data_model_spec.rb
191
201
  - spec/units/mince/model_spec.rb
192
- - spec/integration/simple_mince_data_model_spec.rb
193
202
  homepage: https://github.com/coffeencoke/mince
194
203
  licenses: []
195
204
  post_install_message:
@@ -205,19 +214,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
205
214
  required_rubygems_version: !ruby/object:Gem::Requirement
206
215
  none: false
207
216
  requirements:
208
- - - ! '>'
217
+ - - ! '>='
209
218
  - !ruby/object:Gem::Version
210
- version: 1.3.1
219
+ version: '0'
211
220
  requirements: []
212
221
  rubyforge_project: mince
213
- rubygems_version: 1.8.24
222
+ rubygems_version: 1.8.25
214
223
  signing_key:
215
224
  specification_version: 3
216
225
  summary: Library to interact with mince interfacing data libraries
217
226
  test_files:
227
+ - spec/integration/mince_data_model_spec.rb
228
+ - spec/integration/mince_model_spec.rb
229
+ - spec/support/shared_examples/modeL_data_model_example.rb
230
+ - spec/support/shared_examples/model_finders_example.rb
231
+ - spec/units/mince/model/data_model_spec.rb
232
+ - spec/units/mince/model/finders_spec.rb
218
233
  - spec/units/mince/config_spec.rb
219
234
  - spec/units/mince/interface_example_spec.rb
220
235
  - spec/units/mince/data_model_spec.rb
221
236
  - spec/units/mince/model_spec.rb
222
- - spec/integration/simple_mince_data_model_spec.rb
223
237
  has_rdoc: true
@@ -1,55 +0,0 @@
1
- require 'mince'
2
- require 'hashy_db'
3
-
4
- describe 'A simple mince data model integration spec' do
5
- before do
6
- Mince::Config.interface = Mince::HashyDb::Interface
7
- Mince::HashyDb::Interface.clear
8
- end
9
-
10
- after do
11
- Mince::HashyDb::Interface.clear
12
- end
13
-
14
- describe 'a model' do
15
- subject { model_klass.new attributes }
16
-
17
- let(:model_klass) do
18
- Class.new do
19
- include Mince::Model
20
-
21
- data_model(
22
- Class.new do
23
- include Mince::DataModel
24
-
25
- data_collection :guitars
26
- data_fields :brand, :price, :type, :color
27
- end
28
- )
29
- fields :brand, :price, :type, :color
30
- end
31
- end
32
-
33
- let(:attributes) { { brand: brand, price: price, type: type, color: color } }
34
- let(:brand) { mock }
35
- let(:price) { mock }
36
- let(:type) { mock }
37
- let(:color) { mock }
38
-
39
- it 'is initialized with the correct data' do
40
- subject.brand.should == brand
41
- subject.price.should == price
42
- subject.type.should == type
43
- subject.color.should == color
44
- end
45
-
46
- it 'can be persisted to the mince data interface' do
47
- subject.save
48
-
49
- raw_record = Mince::Config.interface.find(:guitars, Mince::HashyDb::Interface.primary_key, subject.id)
50
- model_record = model_klass.find(subject.id)
51
- raw_record[:brand].should == brand
52
- model_record.brand.should == brand
53
- end
54
- end
55
- end