- Fix bug that broke saving associated objects when declaring the
idattribute with Virtus.
- Invoke identity map when using
mapper.selectandmapper.findwith a block. - When finding objects with an array of ids, if they are all contained in the identity map, we don't issue a query.
- Allow indexes on multiple attributes.
- Add support to
Perpetuity::RailsModelfor ActiveModel'shumanclass method.
- Don't stringify ids in
IdentityMap. This should result in a little better performance. To be honest, I'm not even sure anymore why I put that in there. - Use the IdentityMap when retrieving multiple objects by id.
- Remove in-memory updating of objects using the
Mapper#updatemethod. - Separate dirty tracking from
IdentityMapand return to a real Identity Map. - Pass IdentityMap around when loading associations
- Add
Perpetuity.register_adaptermethod to allow various data-source adapters to register without Perpetuity knowing about them.
- Fix title-case -> snake-case support to convert something like
UserRegistrationtouser_registration. Previously, it would returnuserregistration.
- Allow data source to be configured with a URI. This lets you say
Perpetuity.data_source "postgres://user:password@postgres.example.com:5432/my_database", keeping you from having to split up the URI yourself. - Remove overreaching rescue clauses to let exceptions get rescued inside the adapters
- Allow AttributeSet to be initialized w/ attributes
- Remove Mongo-specific code
- Duplicate objects properly for the identity map. The identity map holds references to objects pulled out of the DB. We need to duplicate these references on insertion and retrieval from the identity map to make sure that modifications to an object do not pollute the version in the identity map.
- Add support for the Amazon DynamoDB adapter by Cardspring. This adapter is still in very early development.
- Allow passing in the type of the
idattribute for databases that enforce column/field types. This allows us to sayid(String) { ... }, telling the database thatidneeds to be a String. - Use hashes for AttributeSets to reduce serialization time.
- Extract all database-specific logic to their own gems. The existing MongoDB adapter has been moved to the
perpetuity-mongodbgem and there is a PostgreSQL adapter that lives underperpetuity-postgres. - Allow specs to be run on top of
perpetuity-postgres - Remove validations.
- Only save attributes which have changed
- Add license to gemspec for the benefit of Rubygems.org
- Only unmarshal attributes that we marshaled to begin with. This disallows the use of false marshaled objects. — with Kevin Sjöberg
- Allow insertion of multiple objects in
Mapper#insert - Alias
Retrieval#limitasRetrieval#takeforEnumerablecompatibility - Leave result cache when branching to new retrievals if previous retrieval had triggered a query
- Silence warnings (some still exist in Moped, unfortunately)
- Add finding based on attribute truthiness. For example:
mapper.find { |obj| obj.name }finds objects whosenameis neithernilnorfalse. - When you remove an index call from the mapper DSL,
Mapper#reindex!now removes that index from the DB - Previously activated indexes in the DB are converted to
Perpetuity::Attributes rather than stored in the format specific to the DB driver
- Add
Perpetuity::RailsModel, an ActiveModel-compliant mixin - Check Rails app directory for mappers dynamically if the mapper registry is missing a particular model class
- Make sure
Retrieval#firstlimits the query to a single item - Add
Mapper#sample/Retrieval#sample - Add
Retrieval#dropto allow skipping a specific number of objects
- Fix reference equality bug
- Stop extending persisted/retrieved objects with
Perpetuity::PersistedObject. Extending these objects invalidates method caches inside the VM, which degrades performance. - Cache all objects returned from
Mapper#find(id)by default into the mapper object. This can be bypassed withMapper#find(id, false) - Do not store uninitialized attributes with the MongoDB serializer. This shrinks the size of documents when possible.
- Allow querying based on referenced class/id or embedded-object data
- Remove duplicate references when loading associations on referenced objects
- Optimize loading associations with zero/one/many objects. It is similar to
Array#detectvsArray#select.detectis faster if you only need one. - Fixed a bug in defining methods on generated mapper classes which would mistakenly define them on the class instead of the mapper objects
- Add
none?/one?/all?/any?methods to mappers. - Add block functionality to
Mapper#count, similar toEnumerable#count - Alias
Mapper#find_alltoMapper#select - Alias
Mapper#detecttoMapper#find - Add
Mapper#rejectmethod to negate queries - Allow
Mapper#findto take a block likeMapper#select - Add atomic incrementation
- Provide configuration one-liner ability for simple configs
- Memoize results for Retrieval objects
Retrieval#countsends a count query rather than retrieving the result set and returning the count of the array- Allow updating of objects that contain
Perpetuity::References to other persisted objects without first loading the association - Fix bug preventing objects with an array of referenced objects from being updated
- Move serialization into the MongoDB adapter, allowing future adapters to implement their own serializations
- Use instance variables rather than attr_readers in IdentityMap (avoids calling methods during
load_association!). - Fixed a bug with MongoDB authentication.
- Use attribute names rather than a stringified attribute for MongoDB indexes.
- Fixed a bug with deserializing attributes of namespaced classes. — Jaap Groeneveld
- Fixed serialization of
Perpetuity::Referenceattributes caused by resaving an object that did not have all of its referenced associations loaded.
- Fix an inconsistency between
mongoandmopedgems. Previously, the MongoDB adapter relied on the fail-fast behavior of themongogem so we had no need to check for errors. Moped does not do that by default, which resulted in incorrect behavior of the gem when an object was not persisted. - The
Mapper#selectDSL now allows the use of!=as criteria. Not all supported Ruby implementations allowed that operator to be overridden when the DSL was created, but they do now.
- Move from the
mongogem from 10gen to themopedgem for talking to MongoDB. This resulted in performance gains of 30-80%, depending on query size. - Make persisted objects marshalable.
- Previously, the
idmethod was defined on individual objects that were either persisted to or retrieved from the DB. This made them unable to be marshaled withMarshal.dump. - Now we extend the objects with
Perpetuity::PersistedObjectto keep them marshalable while still providingid. This keeps them marshalable (unmarshalled objects will still be extended withPerpetuity::PersistedObject).
- Previously, the
- Provided a partial fix for a bug that kept us from being able to persist hash attributes properly. See the first comments in the linked GitHub issue for an explanation of why it is only a partial fix.
- Stopped testing on MRI 1.9.2 with Travis CI. Moped requires 1.9.3 or higher.
- Automatically persist all referenced objects if they are not already persisted. Previously, referenced objects were required to be persisted before persisting the referencing object.
- Made
Mapper#load_association!more friendly. It now loads the associated objects for all objects passed in and works with arrays of referenced objects. Mapper#load_association!is also now more efficient — the N+1 queries have been optimized. The number of queries it fires off is now equal to the quantity of different classes of associated objects.- For example, if a user can have either a
UserProfileor anAdminProfileas itsprofileattribute, Perpetuity will use two queries in#load_association!if and only if both types of profiles are used. - In that example, if you only query users with a
UserProfile, only one DB query will be triggered.
- For example, if a user can have either a
New query example:
user_mapper = Perpetuity[User]
users = user_mapper.all.to_a
user_mapper.load_association! users, :profileEach of the users in the DB will have their profiles loaded with a single DB query per profile type and stored in their profile attributes.
- Improved speed and stability of
Mapper#firstandMapper#all
- Add
Mapper#remove_index!to remove DB indexes - Fix index declarations in mappers to take unique/order options
- These were intended to be there from the beginning, but the API wasn't made available in the mapper
- Mapper select DSL now more closely resembles
Enumerablesyntax- Instead of
mapper.select { published_at < Time.now }you would writemapper.select { |article| article.published_at < Time.now } - It's a little more typing, but it eliminates a lot of problems that came from calling instance_exec on the block. It meant we couldn't call methods on the current object (they would be invoked on the
Queryobject) or use instance variables from the current object. - Explained more in issue #19
- Instead of
- Access object state via instance methods to store actual object state, rather than treating all objects as value objects
- Use
Object.allocaterather thanObject.newwhen restoring state to an object from the database
- Use
Perpetuity[]instead ofPerpetuity::Mapper[]to get mapper instances - Allow subclassing of
Perpetuity::Mapperwith map macro - Fix
selectcalls usingidas criteria from returning invalid or missing data - Make MongoDB reads and writes fail fast
- Add indexing API to mappers
- Raise an exception when calling
Perpetuity[]with a class that has no mapper - Add unions and intersections to select queries for MongoDB adapter
- This allows for queries like
Perpetuity[Article].select { (created_at < Time.now) & (published == true) }
- This allows for queries like
- Update object in memory when calling
Mapper#update - Add
Mapper#saveto update an object's current state in the DB. Previously, we only had#update(primarily forupdateactions in Rails controllers). - Silenced some ugly warnings
Version 0.2 and 0.1 have no changelog because I am a terrible developer