minimapper 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,7 +2,10 @@ source 'https://rubygems.org'
2
2
 
3
3
  # We don't require active_record to use minimapper, only to
4
4
  # use minimapper/mapper/ar. We do require it for the tests though :)
5
- gem "activerecord"
5
+ #
6
+ # Also locked to below rails 4.0 as our specs use rails 3 features. Need to look into
7
+ # if there are any issues with rails 4.
8
+ gem "activerecord", "< 4.0"
6
9
  gem "rspec"
7
10
 
8
11
  platforms :ruby do
data/README.md CHANGED
@@ -113,7 +113,7 @@ Repository = Minimapper::Repository.build({
113
113
 
114
114
  user = User.new(:name => "Joe")
115
115
  Repository.users.create(user)
116
- p repository.users.find(user.id).name # => Joe
116
+ p Repository.users.find(user.id).name # => Joe
117
117
  Repository.users.delete_all
118
118
 
119
119
  ## Using ActiveModel validations
@@ -168,7 +168,7 @@ end
168
168
 
169
169
  `entity_for` returns nil for nil.
170
170
 
171
- It takes an optional second argument if you want a different entity class than the mapper's:
171
+ `entity_for` and `entities_for` take an optional second argument if you want a different entity class than the mapper's:
172
172
 
173
173
  ```
174
174
  class ProjectMapper < Minimapper::AR
@@ -186,15 +186,15 @@ If you specify type, Minimapper will only allow values of that type, or strings
186
186
  The latter means that it can accept e.g. string integers directly from a form.
187
187
  Minimapper aims to be much less of a form value parser than ActiveRecord, but we'll allow ourselves conveniences like this.
188
188
 
189
- Supported types: Integer and DateTime (`:integer` and `:date_time`).
189
+ Supported types: Integer and DateTime.
190
190
 
191
191
  ``` ruby
192
192
  class User
193
193
  include Minimapper::Entity
194
- attributes [ :profile_id, :integer ]
194
+ attributes [ :profile_id, Integer ]
195
195
 
196
196
  # Or for single attributes:
197
- # attribute :profile_id, :integer
197
+ # attribute :profile_id, Integer
198
198
  end
199
199
 
200
200
  User.new(:profile_id => "10").profile_id # => 10
@@ -226,6 +226,8 @@ User.new(:reminder_on => "2012-01-01").reminder # => #<Date: 2012-01-01 ...>
226
226
 
227
227
  Minimapper only calls #convert on non-empty strings. When the value is blank or nil, the attribute is set to nil.
228
228
 
229
+ (FIXME? We're considering changing this so Minimapper core can only enforce type, and there's some `Minimapper::FormObject` mixin to parse string values.)
230
+
229
231
  ### Overriding attribute accessors
230
232
 
231
233
  Attribute readers and writers are implemented so that you can override them with inheritance:
@@ -277,6 +279,35 @@ class ProjectMapper < Minimapper::AR
277
279
  end
278
280
  ```
279
281
 
282
+ ### Deletion
283
+
284
+ When you do `mapper.delete(entity)`, it will use [ActiveRecord's `delete`](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-destroy), which means that no destroy callbacks or `:dependent` association options are honored.
285
+
286
+ (FIXME?: Should we support `destroy` instead or as well?)
287
+
288
+ ### Exceptions and status 404
289
+
290
+ Code like `UserMapper.find(123)` will raise `Minimapper::EntityNotFound` if there's no such record.
291
+
292
+ Rails treats the similar `ActiveRecord::RecordNotFound` exception as a 404 error, using that status code with the error backtrace in development and test, and showing the 404 page in production.
293
+
294
+ If you want the same for Minimapper, you can add a `config/initializers/minimapper.rb` containing:
295
+
296
+ ``` ruby
297
+ # For 404 status with the dev/test backtrace, and a 404 page in production.
298
+ ActionDispatch::ExceptionWrapper.rescue_responses.merge!(
299
+ "Minimapper::EntityNotFound" => :not_found
300
+ )
301
+ ```
302
+
303
+ You may also want to ignore those errors in your error logger. With [Honeybadger](https://www.honeybadger.io), you do:
304
+
305
+ ``` ruby
306
+ Honeybadger.configure do |config|
307
+ config.ignore << "Minimapper::EntityNotFound"
308
+ end
309
+ ```
310
+
280
311
  ### Custom entity class
281
312
 
282
313
  [Minimapper::Entity](https://github.com/joakimk/minimapper/blob/master/lib/minimapper/entity.rb) adds some convenience methods for when a model is used within a Rails application. If you don't need that you can just include the core API from the [Minimapper::Entity::Core](https://github.com/joakimk/minimapper/blob/master/lib/minimapper/entity/core.rb) module (or implement your own version that behaves like [Minimapper::Entity::Core](https://github.com/joakimk/minimapper/blob/master/lib/minimapper/entity/core.rb)).
@@ -21,9 +21,9 @@ module Minimapper
21
21
  klass.send(:include, Minimapper::Entity::Validation)
22
22
  klass.send(:include, Minimapper::Entity::Rails)
23
23
  klass.attributes(
24
- [ :id, :integer ],
25
- [ :created_at, :date_time ],
26
- [ :updated_at, :date_time ]
24
+ [ :id, Integer ],
25
+ [ :created_at, DateTime ],
26
+ [ :updated_at, DateTime ]
27
27
  )
28
28
  end
29
29
  end
@@ -14,8 +14,8 @@ module Minimapper
14
14
  @@converters[type] = converter
15
15
  end
16
16
 
17
- register_converter :integer, ToInteger.new
18
- register_converter :date_time, ToDateTime.new
17
+ register_converter Integer, ToInteger.new
18
+ register_converter DateTime, ToDateTime.new
19
19
 
20
20
  def to(type)
21
21
  return nil if value != false && value.blank?
@@ -30,6 +30,18 @@ module Minimapper
30
30
  @mapper_errors = list
31
31
  end
32
32
 
33
+ def persisted?
34
+ @entity_is_persisted
35
+ end
36
+
37
+ def mark_as_persisted
38
+ @entity_is_persisted = true
39
+ end
40
+
41
+ def mark_as_not_persisted
42
+ @entity_is_persisted = false
43
+ end
44
+
33
45
  private
34
46
 
35
47
  def symbolize_keys(hash)
@@ -9,12 +9,13 @@ module Minimapper
9
9
  id
10
10
  end
11
11
 
12
+ # Implemented in core.
12
13
  def persisted?
13
- id
14
+ super
14
15
  end
15
16
 
16
17
  def new_record?
17
- !id
18
+ !persisted?
18
19
  end
19
20
 
20
21
  def to_model
@@ -14,6 +14,7 @@ module Minimapper
14
14
 
15
15
  if entity.valid?
16
16
  record.save!
17
+ entity.mark_as_persisted
17
18
  entity.id = record.id
18
19
  entity.id
19
20
  else
@@ -67,7 +68,7 @@ module Minimapper
67
68
 
68
69
  def delete(entity)
69
70
  delete_by_id(entity.id)
70
- entity.id = nil
71
+ entity.mark_as_not_persisted
71
72
  end
72
73
 
73
74
  def delete_by_id(id)
@@ -122,14 +123,15 @@ module Minimapper
122
123
  raise(EntityNotFound, entity.inspect)
123
124
  end
124
125
 
125
- def entities_for(records)
126
- records.map { |record| entity_for(record) }
126
+ def entities_for(records, klass = entity_class)
127
+ records.map { |record| entity_for(record, klass) }
127
128
  end
128
129
 
129
130
  def entity_for(record, klass = entity_class)
130
131
  if record
131
132
  entity = klass.new
132
133
  entity.id = record.id
134
+ entity.mark_as_persisted
133
135
  entity.attributes = record.attributes.symbolize_keys
134
136
 
135
137
  if klass == entity_class
@@ -1,3 +1,3 @@
1
1
  module Minimapper
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.0"
3
3
  end
@@ -18,6 +18,13 @@ shared_examples :mapper do
18
18
  entity2.id.should == entity1.id + 1
19
19
  end
20
20
 
21
+ it "marks the entity as persisted" do
22
+ entity1 = build_valid_entity
23
+ entity1.should_not be_persisted
24
+ mapper.create(entity1)
25
+ entity1.should be_persisted
26
+ end
27
+
21
28
  it "returns the id" do
22
29
  id = mapper.create(build_valid_entity)
23
30
  id.should be_kind_of(Fixnum)
@@ -70,6 +77,13 @@ shared_examples :mapper do
70
77
  found_entity = mapper.find(entity.id)
71
78
  end
72
79
 
80
+ it "returns an entity marked as persisted" do
81
+ entity = build_valid_entity
82
+ mapper.create(entity)
83
+ found_entity = mapper.find(entity.id)
84
+ found_entity.should be_persisted
85
+ end
86
+
73
87
  it "fails when an entity can not be found" do
74
88
  lambda { mapper.find(-1) }.should raise_error(Minimapper::EntityNotFound)
75
89
  end
@@ -228,12 +242,12 @@ shared_examples :mapper do
228
242
  mapper.first.id.should_not == removed_entity_id
229
243
  end
230
244
 
231
- it "clears the entity id" do
245
+ it "marks the entity as no longer persisted" do
232
246
  entity = build_valid_entity
233
247
  mapper.create(entity)
234
- entity.id.should_not be_nil
248
+ entity.should be_persisted
235
249
  mapper.delete(entity)
236
- entity.id.should be_nil
250
+ entity.should_not be_persisted
237
251
  end
238
252
 
239
253
  it "fails when the entity does not have an id" do
@@ -5,7 +5,7 @@ module Attribute
5
5
  class User
6
6
  include Minimapper::Entity::Core
7
7
  include Minimapper::Entity::Attributes
8
- attribute :id, :integer
8
+ attribute :id, Integer
9
9
  attribute :name
10
10
  end
11
11
 
@@ -23,7 +23,7 @@ module Attribute
23
23
  include Minimapper::Entity::Core
24
24
  include Minimapper::Entity::Attributes
25
25
 
26
- attribute :due_at, :date_time
26
+ attribute :due_at, DateTime
27
27
  end
28
28
 
29
29
  class OverridingUser
@@ -1,34 +1,34 @@
1
1
  require 'minimapper/entity/convert'
2
2
 
3
3
  describe Minimapper::Entity::Convert do
4
- describe ":integer" do
4
+ describe "Integer" do
5
5
  it "allows integers" do
6
- described_class.new(10).to(:integer).should == 10
6
+ described_class.new(10).to(Integer).should == 10
7
7
  end
8
8
 
9
9
  it "converts strings into integers" do
10
- described_class.new('10').to(:integer).should == 10
11
- described_class.new(' 10 ').to(:integer).should == 10
10
+ described_class.new('10').to(Integer).should == 10
11
+ described_class.new(' 10 ').to(Integer).should == 10
12
12
  end
13
13
 
14
14
  it "makes it nil when it can't convert" do
15
- described_class.new(' ').to(:integer).should be_nil
16
- described_class.new('garbage').to(:integer).should be_nil
15
+ described_class.new(' ').to(Integer).should be_nil
16
+ described_class.new('garbage').to(Integer).should be_nil
17
17
  end
18
18
  end
19
19
 
20
- describe ":date_time" do
20
+ describe "DateTime" do
21
21
  it "allows DateTimes" do
22
- described_class.new(DateTime.new(2013, 6, 1)).to(:date_time).should == DateTime.new(2013, 6, 1)
22
+ described_class.new(DateTime.new(2013, 6, 1)).to(DateTime).should == DateTime.new(2013, 6, 1)
23
23
  end
24
24
 
25
25
  it "converts datetime strings into datetimes" do
26
- described_class.new('2012-01-01 20:57').to(:date_time).should == DateTime.new(2012, 01, 01, 20, 57)
26
+ described_class.new('2012-01-01 20:57').to(DateTime).should == DateTime.new(2012, 01, 01, 20, 57)
27
27
  end
28
28
 
29
29
  it "makes it nil when it can't convert" do
30
- described_class.new(' ').to(:date_time).should be_nil
31
- described_class.new('garbage').to(:date_time).should be_nil
30
+ described_class.new(' ').to(DateTime).should be_nil
31
+ described_class.new('garbage').to(DateTime).should be_nil
32
32
  end
33
33
  end
34
34
 
@@ -9,20 +9,21 @@ end
9
9
  describe Minimapper::Entity::Rails do
10
10
  it "responds to new_record?" do
11
11
  entity = RailsEntity.new
12
- entity.should be_new_record
13
- entity.id = 5
14
- entity.should_not be_new_record
12
+ entity.new_record?.should be_true
13
+ entity.mark_as_persisted
14
+ entity.new_record?.should be_false
15
15
  end
16
16
 
17
- it "resonds to to_model" do
17
+ it "responds to to_model" do
18
18
  entity = RailsEntity.new
19
19
  entity.to_model.should == entity
20
20
  end
21
21
 
22
22
  it "responds to to_key" do
23
23
  entity = RailsEntity.new
24
- entity.to_key.should be_nil
25
24
  entity.id = 5
25
+ entity.to_key.should be_nil
26
+ entity.mark_as_persisted
26
27
  entity.to_key.should == [ 5 ]
27
28
  end
28
29
 
@@ -37,7 +38,7 @@ describe Minimapper::Entity::Rails do
37
38
  it "responds to persisted?" do
38
39
  entity = RailsEntity.new
39
40
  entity.should_not be_persisted
40
- entity.id = 5
41
+ entity.mark_as_persisted
41
42
  entity.should be_persisted
42
43
  end
43
44
  end
@@ -25,8 +25,8 @@ describe Minimapper::Repository, "self.build" do
25
25
  end
26
26
 
27
27
  it "does not leak between instances" do
28
- mapper1 = mock.as_null_object
29
- mapper2 = mock.as_null_object
28
+ mapper1 = double.as_null_object
29
+ mapper2 = double.as_null_object
30
30
  repository1 = described_class.build(:projects => mapper1)
31
31
  repository2 = described_class.build(:projects => mapper2)
32
32
  repository1.projects.should == mapper1
@@ -36,8 +36,8 @@ end
36
36
 
37
37
  describe Minimapper::Repository, "#delete_all!" do
38
38
  it "removes all records by calling delete_all on all mappers" do
39
- project_mapper = mock.as_null_object
40
- user_mapper = mock.as_null_object
39
+ project_mapper = double.as_null_object
40
+ user_mapper = double.as_null_object
41
41
 
42
42
  project_mapper.should_receive(:delete_all)
43
43
  user_mapper.should_receive(:delete_all)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minimapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-09 00:00:00.000000000 Z
12
+ date: 2013-10-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &70270060752600 !ruby/object:Gem::Requirement
16
+ requirement: &70096190311420 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70270060752600
24
+ version_requirements: *70096190311420
25
25
  description: A minimalistic way of separating your models from ActiveRecord.
26
26
  email:
27
27
  - joakim.kolsjo@gmail.com
@@ -75,12 +75,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
+ segments:
79
+ - 0
80
+ hash: 2287659495149187599
78
81
  required_rubygems_version: !ruby/object:Gem::Requirement
79
82
  none: false
80
83
  requirements:
81
84
  - - ! '>='
82
85
  - !ruby/object:Gem::Version
83
86
  version: '0'
87
+ segments:
88
+ - 0
89
+ hash: 2287659495149187599
84
90
  requirements: []
85
91
  rubyforge_project:
86
92
  rubygems_version: 1.8.5