Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

root/tags/rel_0-9-4-1/activerecord/CHANGELOG

Revision 460, 53.3 kB (checked in by david, 4 years ago)

Tagged the 0.9.4.1 release

Line 
1 *1.5.1* (January 18th, 2005)
2
3 * Fixed that the belongs_to and has_one proxy would fail a test like 'if project.manager' -- this unfortunately also means that you can't call methods like project.manager.build unless there already is a manager on the project #492 [Tim Bates]
4
5 * Fixed that the Ruby/MySQL adapter wouldn't connect if the password was empty #503 [Pelle]
6
7
8 *1.5.0* (January 17th, 2005)
9
10 * Fixed that unit tests for MySQL are now run as the "rails" user instead of root #455 [Eric Hodel]
11
12 * Added validates_associated that enables validation of objects in an unsaved association #398 [Tim Bates]. Example:
13
14     class Book < ActiveRecord::Base
15       has_many :pages
16       belongs_to :library
17    
18       validates_associated :pages, :library
19     end
20    
21 * Added support for associating unsaved objects #402 [Tim Bates]. Rules that govern this addition:
22
23     == Unsaved objects and associations
24    
25     You can manipulate objects and associations before they are saved to the database, but there is some special behaviour you should be
26     aware of, mostly involving the saving of associated objects.
27    
28     === One-to-one associations
29    
30     * Assigning an object to a has_one association automatically saves that object, and the object being replaced (if there is one), in
31       order to update their primary keys - except if the parent object is unsaved (new_record? == true).
32     * If either of these saves fail (due to one of the objects being invalid) the assignment statement returns false and the assignment
33       is cancelled.
34     * If you wish to assign an object to a has_one association without saving it, use the #association.build method (documented below).
35     * Assigning an object to a belongs_to association does not save the object, since the foreign key field belongs on the parent. It does
36       not save the parent either.
37    
38     === Collections
39    
40     * Adding an object to a collection (has_many or has_and_belongs_to_many) automatically saves that object, except if the parent object
41       (the owner of the collection) is not yet stored in the database.
42     * If saving any of the objects being added to a collection (via #push or similar) fails, then #push returns false.
43     * You can add an object to a collection without automatically saving it by using the #collection.build method (documented below).
44     * All unsaved (new_record? == true) members of the collection are automatically saved when the parent is saved.
45
46 * Added replace to associations, so you can do project.manager.replace(new_manager) or project.milestones.replace(new_milestones) #402 [Tim Bates]
47
48 * Added build and create methods to has_one and belongs_to associations, so you can now do project.manager.build(attributes) #402 [Tim Bates]
49
50 * Added that if a before_* callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks defined as methods on the model, which are called last. #402 [Tim Bates]
51
52 * Fixed that Base#== wouldn't work for multiple references to the same unsaved object #402 [Tim Bates]
53
54 * Fixed binary support for PostgreSQL #444 [alex@byzantine.no]
55
56 * Added a differenciation between AssociationCollection#size and -length. Now AssociationCollection#size returns the size of the
57   collection by executing a SELECT COUNT(*) query if the collection hasn't been loaded and calling collection.size if it has. If
58   it's more likely than not that the collection does have a size larger than zero and you need to fetch that collection afterwards,
59   it'll take one less SELECT query if you use length.
60
61 * Added Base#attributes that returns a hash of all the attributes with their names as keys and clones of their objects as values #433 [atyp.de]
62
63 * Fixed that foreign keys named the same as the association would cause stack overflow #437 [Eric Anderson]
64
65 * Fixed default scope of acts_as_list from "1" to "1 = 1", so it'll work in PostgreSQL (among other places) #427 [Alexey]
66
67 * Added Base#reload that reloads the attributes of an object from the database #422 [Andreas Schwarz]
68
69 * Added SQLite3 compatibility through the sqlite3-ruby adapter by Jamis Buck #381 [bitsweat]
70
71 * Added support for the new protocol spoken by MySQL 4.1.1+ servers for the Ruby/MySQL adapter that ships with Rails #440 [Matt Mower]
72
73 * Added that Observers can use the observes class method instead of overwriting self.observed_class().
74
75     Before:
76       class ListSweeper < ActiveRecord::Base
77         def self.observed_class() [ List, Item ]
78       end
79    
80     After:
81       class ListSweeper < ActiveRecord::Base
82         observes List, Item
83       end
84
85 * Fixed that conditions in has_many and has_and_belongs_to_many should be interpolated just like the finder_sql is
86
87 * Fixed Base#update_attribute to be indifferent to whether a string or symbol is used to describe the name
88
89 * Added Base#toggle(attribute) and Base#toggle!(attribute) that makes it easier to flip a switch or flag.
90
91     Before: topic.update_attribute(:approved, !approved?)
92     After : topic.toggle!(:approved)
93
94 * Added Base#increment!(attribute) and Base#decrement!(attribute) that also saves the records. Example:
95
96     page.views # => 1
97     page.increment!(:views) # executes an UPDATE statement
98     page.views # => 2
99    
100     page.increment(:views).increment!(:views)
101     page.views # => 4
102
103 * Added Base#increment(attribute) and Base#decrement(attribute) that encapsulates the += 1 and -= 1 patterns.
104
105
106 *1.4.0* (January 4th, 2005)
107
108 * Added automated optimistic locking if the field <tt>lock_version</tt> is present.  Each update to the
109   record increments the lock_version column and the locking facilities ensure that records instantiated twice
110   will let the last one saved raise a StaleObjectError if the first was also updated. Example:
111  
112     p1 = Person.find(1)
113     p2 = Person.find(1)
114    
115     p1.first_name = "Michael"
116     p1.save
117    
118     p2.first_name = "should fail"
119     p2.save # Raises a ActiveRecord::StaleObjectError
120  
121   You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,
122   or otherwise apply the business logic needed to resolve the conflict.
123
124   #384 [Michael Koziarski]
125
126 * Added dynamic attribute-based finders as a cleaner way of getting objects by simple queries without turning to SQL.
127   They work by appending the name of an attribute to <tt>find_by_</tt>, so you get finders like <tt>Person.find_by_user_name,
128   Payment.find_by_transaction_id</tt>. So instead of writing <tt>Person.find_first(["user_name = ?", user_name])</tt>, you just do
129   <tt>Person.find_by_user_name(user_name)</tt>.
130  
131   It's also possible to use multiple attributes in the same find by separating them with "_and_", so you get finders like
132   <tt>Person.find_by_user_name_and_password</tt> or even <tt>Payment.find_by_purchaser_and_state_and_country</tt>. So instead of writing
133   <tt>Person.find_first(["user_name = ? AND password = ?", user_name, password])</tt>, you just do
134   <tt>Person.find_by_user_name_and_password(user_name, password)</tt>.
135
136   While primarily a construct for easier find_firsts, it can also be used as a construct for find_all by using calls like
137   <tt>Payment.find_all_by_amount(50)</tt> that is turned into <tt>Payment.find_all(["amount = ?", 50])</tt>. This is something not as equally useful,
138   though, as it's not possible to specify the order in which the objects are returned.
139
140 * Added block-style for callbacks #332 [bitsweat].
141
142     Before:
143       before_destroy(Proc.new{ |record| Person.destroy_all "firm_id = #{record.id}" })
144    
145     After:
146       before_destroy { |record| Person.destroy_all "firm_id = #{record.id}" }
147
148 * Added :counter_cache option to acts_as_tree that works just like the one you can define on belongs_to #371 [Josh]
149
150 * Added Base.default_timezone accessor that determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling dates
151   and times from the database. This is set to :local by default.
152
153 * Added the possibility for adapters to overwrite add_limit! to implement a different limiting scheme than "LIMIT X" used by MySQL, PostgreSQL, and SQLite.
154
155 * Added the possibility of having objects with acts_as_list created before their scope is available or...
156
157 * Added a db2 adapter that only depends on the Ruby/DB2 bindings (http://raa.ruby-lang.org/project/ruby-db2/) #386 [Maik Schmidt]
158
159 * Added the final touches to the Microsoft SQL Server adapter by Joey Gibson that makes it suitable for actual use #394 [DeLynn Barry]
160
161 * Added that Base#find takes an optional options hash, including :conditions. Base#find_on_conditions deprecated in favor of #find with :conditions #407 [bitsweat]
162
163 * Added HasManyAssociation#count that works like Base#count #413 [intinig]
164
165 * Fixed handling of binary content in blobs and similar fields for Ruby/MySQL and SQLite #409 [xal]
166
167 * Fixed a bug in the Ruby/MySQL that caused binary content to be escaped badly and come back mangled #405 [Tobias Luetke]
168
169 * Fixed that the const_missing autoload assumes the requested constant is set by require_association and calls const_get to retrieve it.
170   If require_association did not set the constant then const_get will call const_missing, resulting in an infinite loop #380 [bitsweat]
171
172 * Fixed broken transactions that were actually only running object-level and not db level transactions [andreas]
173
174 * Fixed that validates_uniqueness_of used 'id' instead of defined primary key #406
175
176 * Fixed that the overwritten respond_to? method didn't take two parameters like the original #391
177
178 * Fixed quoting in validates_format_of that would allow some rules to pass regardless of input #390 [Dmitry V. Sabanin]
179
180
181 *1.3.0* (December 23, 2004)
182
183 * Added a require_association hook on const_missing that makes it possible to use any model class without requiring it first. This makes STI look like:
184
185     before:
186       require_association 'person'
187       class Employee < Person
188       end
189    
190     after:
191       class Employee < Person
192       end
193
194   This also reduces the usefulness of Controller.model in Action Pack to currently only being for documentation purposes.     
195
196 * Added that Base.update_all and Base.delete_all return an integer of the number of affected rows #341
197
198 * Added scope option to validation_uniqueness #349 [Kent Sibilev]
199
200 * Added respondence to *_before_type_cast for all attributes to return their string-state before they were type casted by the column type.
201   This is helpful for getting "100,000" back on a integer-based validation where the value would normally be "100".
202
203 * Added allow_nil options to validates_inclusion_of so that validation is only triggered if the attribute is not nil [what-a-day]
204
205 * Added work-around for PostgreSQL and the problem of getting fixtures to be created from id 1 on each test case.
206   This only works for auto-incrementing primary keys called "id" for now #359 [Scott Baron]
207
208 * Added Base#clear_association_cache to empty all the cached associations #347 [Tobias Luetke]
209
210 * Added more informative exceptions in establish_connection #356 [bitsweat]
211
212 * Added Base#update_attributes that'll accept a hash of attributes and save the record (returning true if it passed validation, false otherwise).
213
214     Before:
215       person.attributes = @params["person"]
216       person.save
217    
218     Now:
219       person.update_attributes(@params["person"])
220
221 * Added Base.destroy and Base.delete to remove records without holding a reference to them first.
222
223 * Added that query benchmarking will only happen if its going to be logged anyway #344
224
225 * Added higher_item and lower_item as public methods for acts_as_list #342 [Tobias Luetke]
226
227 * Fixed that options[:counter_sql] was overwritten with interpolated sql rather than original sql #355 [bitsweat]
228
229 * Fixed that overriding an attribute's accessor would be disregarded by add_on_empty and add_on_boundary_breaking because they simply used
230   the attributes[] hash instead of checking for @base.respond_to?(attr.to_s). [Marten]
231
232 * Fixed that Base.table_name would expect a parameter when used in has_and_belongs_to_many joins [Anna Lissa Cruz]
233
234 * Fixed that nested transactions now work by letting the outer most transaction have the responsibilty of starting and rolling back the transaction.
235   If any of the inner transactions swallow the exception raised, though, the transaction will not be rolled back. So always let the transaction
236   bubble up even when you've dealt with local issues. Closes #231 and #340.
237
238 * Fixed validates_{confirmation,acceptance}_of to only happen when the virtual attributes are not nil #348 [dpiddy@gmail.com]
239
240 * Changed the interface on AbstractAdapter to require that adapters return the number of affected rows on delete and update operations.
241
242 * Fixed the automated timestamping feature when running under Rails' development environment that resets the inheritable attributes on each request.
243
244
245
246 *1.2.0*
247
248 * Added Base.validates_inclusion_of that validates whether the value of the specified attribute is available in a particular enumerable
249   object. [what-a-day]
250
251     class Person < ActiveRecord::Base
252       validates_inclusion_of :gender, :in=>%w( m f ), :message=>"woah! what are you then!??!!"
253       validates_inclusion_of :age, :in=>0..99
254     end
255
256 * Added acts_as_list that can decorates an existing class with methods like move_higher/lower, move_to_top/bottom. [Tobias Luetke] Example:
257
258     class TodoItem < ActiveRecord::Base
259       acts_as_list :scope => :todo_list_id
260       belongs_to :todo_list
261     end
262
263 * Added acts_as_tree that can decorates an existing class with a many to many relationship with itself. Perfect for categories in
264   categories and the likes. [Tobias Luetke]
265
266 * Added that Active Records will automatically record creation and/or update timestamps of database objects if fields of the names
267   created_at/created_on or updated_at/updated_on are present. [Tobias Luetke]
268
269 * Added Base.default_error_messages as a hash of all the error messages used in the validates_*_of so they can be changed in one place [Tobias Luetke]
270
271 * Added automatic transaction block around AssociationCollection.<<, AssociationCollection.delete, and AssociationCollection.destroy_all
272
273 * Fixed that Base#find will return an array if given an array -- regardless of the number of elements #270 [Marten]
274
275 * Fixed that has_and_belongs_to_many would generate bad sql when naming conventions differed from using vanilla "id" everywhere [RedTerror]
276
277 * Added a better exception for when a type column is used in a table without the intention of triggering single-table inheritance. Example:
278
279     ActiveRecord::SubclassNotFound: The single-table inheritance mechanism failed to locate the subclass: 'bad_class!'.
280     This error is raised because the column 'type' is reserved for storing the class in case of inheritance.
281     Please rename this column if you didn't intend it to be used for storing the inheritance class or
282     overwrite Company.inheritance_column to use another column for that information.
283
284 * Added that single-table inheritance will only kick in if the inheritance_column (by default "type") is present. Otherwise, inheritance won't
285   have any magic side effects.
286
287 * Added the possibility of marking fields as being in error without adding a message (using nil) to it that'll get displayed wth full_messages #208 [mjobin]
288
289 * Fixed Base.errors to be indifferent as to whether strings or symbols are used. Examples:
290
291     Before:
292       errors.add(:name, "must be shorter") if name.size > 10
293       errors.on(:name)  # => "must be shorter"
294       errors.on("name") # => nil
295
296     After:
297       errors.add(:name, "must be shorter") if name.size > 10
298       errors.on(:name)  # => "must be shorter"
299       errors.on("name") # => "must be shorter"
300
301 * Added Base.validates_format_of that Validates whether the value of the specified attribute is of the correct form by matching
302   it against the regular expression provided. [Marcel]
303
304     class Person < ActiveRecord::Base
305       validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/, :on => :create
306     end
307
308 * Added Base.validates_length_of that delegates to add_on_boundary_breaking #312 [Tobias Luetke]. Example:
309
310     Validates that the specified attribute matches the length restrictions supplied in either:
311    
312       - configuration[:minimum]
313       - configuration[:maximum]
314       - configuration[:is]
315       - configuration[:within] (aka. configuration[:in])
316    
317     Only one option can be used at a time.
318    
319       class Person < ActiveRecord::Base
320         validates_length_of :first_name, :maximum=>30
321         validates_length_of :last_name, :maximum=>30, :message=>"less than %d if you don't mind"
322         validates_length_of :user_name, :within => 6..20, :too_long => "pick a shorter name", :too_short => "pick a longer name"
323         validates_length_of :fav_bra_size, :minimum=>1, :too_short=>"please enter at least %d character"
324         validates_length_of :smurf_leader, :is=>4, :message=>"papa is spelled with %d characters... don't play me."
325       end
326    
327 * Added Base.validate_presence as an alternative to implementing validate and doing errors.add_on_empty yourself.
328
329 * Added Base.validates_uniqueness_of that alidates whether the value of the specified attributes are unique across the system.
330   Useful for making sure that only one user can be named "davidhh".
331  
332     class Person < ActiveRecord::Base
333       validates_uniqueness_of :user_name
334     end
335  
336   When the record is created, a check is performed to make sure that no record exist in the database with the given value for the specified
337   attribute (that maps to a column). When the record is updated, the same check is made but disregarding the record itself.
338
339
340 * Added Base.validates_confirmation_of that encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example:
341  
342      Model:
343        class Person < ActiveRecord::Base
344          validates_confirmation_of :password
345        end
346  
347      View:
348        <%= password_field "person", "password" %>
349        <%= password_field "person", "password_confirmation" %>
350  
351    The person has to already have a password attribute (a column in the people table), but the password_confirmation is virtual.
352    It exists only as an in-memory variable for validating the password. This check is performed both on create and update.
353
354
355 * Added Base.validates_acceptance_of that encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example:
356  
357    class Person < ActiveRecord::Base
358      validates_acceptance_of :terms_of_service
359    end
360  
361   The terms_of_service attribute is entirely virtual. No database column is needed. This check is performed both on create and update.
362
363   NOTE: The agreement is considered valid if it's set to the string "1". This makes it easy to relate it to an HTML checkbox.
364
365  
366 * Added validation macros to make the stackable just like the lifecycle callbacks. Examples:
367
368     class Person < ActiveRecord::Base
369       validate { |record| record.errors.add("name", "too short") unless name.size > 10 }
370       validate { |record| record.errors.add("name", "too long")  unless name.size < 20 }
371       validate_on_create :validate_password
372      
373       private
374         def validate_password
375           errors.add("password", "too short") unless password.size > 6
376         end
377     end
378
379 * Added the option for sanitizing find_by_sql and the offset parts in regular finds [Sam Stephenson]. Examples:
380
381     Project.find_all ["category = ?", category_name], "created ASC", ["? OFFSET ?", 15, 20]
382     Post.find_by_sql ["SELECT * FROM posts WHERE author = ? AND created > ?", author_id, start_date]
383
384 * Fixed value quoting in all generated SQL statements, so that integers are not surrounded in quotes and that all sanitation are happening
385   through the database's own quoting routine. This should hopefully make it lots easier for new adapters that doesn't accept '1' for integer
386   columns.
387
388 * Fixed has_and_belongs_to_many guessing of foreign key so that keys are generated correctly for models like SomeVerySpecialClient
389   [Florian Weber]
390
391 * Added counter_sql option for has_many associations [bitsweat]. Documentation:
392
393     <tt>:counter_sql</tt> - specify a complete SQL statement to fetch the size of the association. If +:finder_sql+ is
394     specified but +:counter_sql+, +:counter_sql+ will be generated by replacing SELECT ... FROM with SELECT COUNT(*) FROM.
395
396 * Fixed that methods wrapped in callbacks still return their original result #260 [bitsweat]
397
398 * Fixed the Inflector to handle the movie/movies pair correctly #261 [Scott Baron]
399
400 * Added named bind-style variable interpolation #281 [Michael Koziarski]. Example:
401
402     Person.find(["id = :id and first_name = :first_name", { :id => 5, :first_name = "bob' or 1=1" }])
403
404 * Added bind-style variable interpolation for the condition arrays that uses the adapter's quote method [Michael Koziarski]
405
406   Before:
407     find_first([ "user_name = '%s' AND password = '%s'", user_name, password ])]
408     find_first([ "firm_id = %s", firm_id ])] # unsafe!
409
410   After:
411     find_first([ "user_name = ? AND password = ?", user_name, password ])]
412     find_first([ "firm_id = ?", firm_id ])]
413
414 * Added CSV format for fixtures #272 [what-a-day]. (See the new and expanded documentation on fixtures for more information)
415
416 * Fixed fixtures using primary key fields called something else than "id" [dave]
417
418 * Added proper handling of time fields that are turned into Time objects with the dummy date of 2000/1/1 [HariSeldon]
419
420 * Added reverse order of deleting fixtures, so referential keys can be maintained #247 [Tim Bates]
421
422 * Added relative path search for sqlite dbfiles in database.yml (if RAILS_ROOT is defined) #233 [bitsweat]
423
424 * Added option to establish_connection where you'll be able to leave out the parameter to have it use the RAILS_ENV environment variable
425
426 * Fixed problems with primary keys and postgresql sequences (#230) [Tim Bates]
427
428 * Added reloading for associations under cached environments like FastCGI and mod_ruby. This makes it possible to use those environments for development.
429   This is turned on by default, but can be turned off with ActiveRecord::Base.reload_dependencies = false in production environments.
430
431   NOTE: This will only have an effect if you let the associations manage the requiring of model classes. All libraries loaded through
432   require will be "forever" cached. You can, however, use ActiveRecord::Base.load_or_require("library") to get this behavior outside of the
433   auto-loading associations.
434
435 * Added ERB capabilities to the fixture files for dynamic fixture generation. You don't need to do anything, just include ERB blocks like:
436
437     david:
438       id: 1
439       name: David
440
441     jamis:
442       id: 2
443       name: Jamis
444
445     <% for digit in 3..10 %>
446     dev_<%= digit %>:
447       id: <%= digit %>
448       name: fixture_<%= digit %>
449     <% end %>
450
451 * Changed the yaml fixture searcher to look in the root of the fixtures directory, so when you before could have something like:
452
453     fixtures/developers/fixtures.yaml
454     fixtures/accounts/fixtures.yaml
455  
456   ...you now need to do:
457  
458     fixtures/developers.yaml
459     fixtures/accounts.yaml
460
461 * Changed the fixture format from:
462
463     name: david
464     data:
465      id: 1
466      name: David Heinemeier Hansson
467      birthday: 1979-10-15
468      profession: Systems development
469     ---
470     name: steve
471     data:
472      id: 2
473      name: Steve Ross Kellock
474      birthday: 1974-09-27
475      profession: guy with keyboard
476
477   ...to:
478
479     david:
480      id: 1
481      name: David Heinemeier Hansson
482      birthday: 1979-10-15
483      profession: Systems development
484    
485     steve:
486      id: 2
487      name: Steve Ross Kellock
488      birthday: 1974-09-27
489      profession: guy with keyboard
490    
491   The change is NOT backwards compatible. Fixtures written in the old YAML style needs to be rewritten!
492
493 * All associations will now attempt to require the classes that they associate to. Relieving the need for most explicit 'require' statements.
494
495
496 *1.1.0* (34)
497
498 * Added automatic fixture setup and instance variable availability. Fixtures can also be automatically
499   instantiated in instance variables relating to their names using the following style:
500
501     class FixturesTest < Test::Unit::TestCase
502       fixtures :developers # you can add more with comma separation
503
504       def test_developers
505         assert_equal 3, @developers.size # the container for all the fixtures is automatically set
506         assert_kind_of Developer, @david # works like @developers["david"].find
507         assert_equal "David Heinemeier Hansson", @david.name
508       end
509     end
510
511 * Added HasAndBelongsToManyAssociation#push_with_attributes(object, join_attributes) that can create associations in the join table with additional
512   attributes. This is really useful when you have information that's only relevant to the join itself, such as a "added_on" column for an association
513   between post and category. The added attributes will automatically be injected into objects retrieved through the association similar to the piggy-back
514   approach:
515  
516     post.categories.push_with_attributes(category, :added_on => Date.today)
517     post.categories.first.added_on # => Date.today
518    
519   NOTE: The categories table doesn't have a added_on column, it's the categories_post join table that does!
520
521 * Fixed that :exclusively_dependent and :dependent can't be activated at the same time on has_many associations [bitsweat]
522
523 * Fixed that database passwords couldn't be all numeric [bitsweat]
524
525 * Fixed that calling id would create the instance variable for new_records preventing them from being saved correctly [bitsweat]
526
527 * Added sanitization feature to HasManyAssociation#find_all so it works just like Base.find_all [Sam Stephenson/bitsweat]
528
529 * Added that you can pass overlapping ids to find without getting duplicated records back [bitsweat]
530
531 * Added that Base.benchmark returns the result of the block [bitsweat]
532
533 * Fixed problem with unit tests on Windows with SQLite [paterno]
534
535 * Fixed that quotes would break regular non-yaml fixtures [Dmitry Sabanin/daft]
536
537 * Fixed fixtures on windows with line endings cause problems under unix / mac [Tobias Luetke]
538
539 * Added HasAndBelongsToManyAssociation#find(id) that'll search inside the collection and find the object or record with that id
540
541 * Added :conditions option to has_and_belongs_to_many that works just like the one on all the other associations
542
543 * Added AssociationCollection#clear to remove all associations from has_many and has_and_belongs_to_many associations without destroying the records [geech]
544
545 * Added type-checking and remove in 1-instead-of-N sql statements to AssociationCollection#delete [geech]
546
547 * Added a return of self to AssociationCollection#<< so appending can be chained, like project << Milestone.create << Milestone.create [geech]
548
549 * Added Base#hash and Base#eql? which means that all of the equality using features of array and other containers now works:
550
551     [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
552
553 * Added :uniq as an option to has_and_belongs_to_many which will automatically ensure that AssociateCollection#uniq is called
554   before pulling records out of the association. This is especially useful for three-way (and above) has_and_belongs_to_many associations.
555
556 * Added AssociateCollection#uniq which is especially useful for has_and_belongs_to_many associations that can include duplicates,
557   which is common on associations that also use metadata. Usage: post.categories.uniq
558
559 * Fixed respond_to? to use a subclass specific hash instead of an Active Record-wide one
560
561 * Fixed has_and_belongs_to_many to treat associations between classes in modules properly [Florian Weber]
562
563 * Added a NoMethod exception to be raised when query and writer methods are called for attributes that doesn't exist [geech]
564
565 * Added a more robust version of Fixtures that throws meaningful errors when on formatting issues [geech]
566
567 * Added Base#transaction as a compliment to Base.transaction for prettier use in instance methods [geech]
568
569 * Improved the speed of respond_to? by placing the dynamic methods lookup table in a hash [geech]
570
571 * Added that any additional fields added to the join table in a has_and_belongs_to_many association
572   will be placed as attributes when pulling records out through has_and_belongs_to_many associations.
573   This is helpful when have information about the association itself that you want available on retrival.
574
575 * Added better loading exception catching and RubyGems retries to the database adapters [alexeyv]
576
577 * Fixed bug with per-model transactions [daniel]
578
579 * Fixed Base#transaction so that it returns the result of the last expression in the transaction block [alexeyv]
580
581 * Added Fixture#find to find the record corresponding to the fixture id. The record
582   class name is guessed by using Inflector#classify (also new) on the fixture directory name.
583  
584     Before: Document.find(@documents["first"]["id"])
585     After : @documents["first"].find
586
587 * Fixed that the table name part of column names ("TABLE.COLUMN") wasn't removed properly [Andreas Schwarz]
588
589 * Fixed a bug with Base#size when a finder_sql was used that didn't capitalize SELECT and FROM [geech]
590
591 * Fixed quoting problems on SQLite by adding quote_string to the AbstractAdapter that can be overwritten by the concrete
592   adapters for a call to the dbm. [Andreas Schwarz]
593  
594 * Removed RubyGems backup strategy for requiring SQLite-adapter -- if people want to use gems, they're already doing it with AR.
595
596
597 *1.0.0 (35)*
598
599 * Added OO-style associations methods [Florian Weber]. Examples:
600
601     Project#milestones_count       => Project#milestones.size
602     Project#build_to_milestones    => Project#milestones.build
603     Project#create_for_milestones  => Project#milestones.create
604     Project#find_in_milestones     => Project#milestones.find
605     Project#find_all_in_milestones => Project#milestones.find_all
606
607 * Added serialize as a new class method to control when text attributes should be YAMLized or not. This means that automated
608   serialization of hashes, arrays, and so on WILL NO LONGER HAPPEN (#10). You need to do something like this:
609  
610     class User < ActiveRecord::Base
611       serialize :settings
612     end
613  
614   This will assume that settings is a text column and will now YAMLize any object put in that attribute. You can also specify
615   an optional :class_name option that'll raise an exception if a serialized object is retrieved as a descendent of a class not in
616   the hierarchy. Example:
617  
618     class User < ActiveRecord::Base
619       serialize :settings, :class_name => "Hash"
620     end
621  
622     user = User.create("settings" => %w( one two three ))
623     User.find(user.id).settings # => raises SerializationTypeMismatch
624
625 * Added the option to connect to a different database for one model at a time. Just call establish_connection on the class
626   you want to have connected to another database than Base. This will automatically also connect decendents of that class
627   to the different database [Renald Buter].
628
629 * Added transactional protection for Base#save. Validations can now check for values knowing that it happens in a transaction and callbacks
630   can raise exceptions knowing that the save will be rolled back. [Suggested by Alexey Verkhovsky]
631
632 * Added column name quoting so reserved words, such as "references", can be used as column names [Ryan Platte]
633
634 * Added the possibility to chain the return of what happened inside a logged block [geech]:
635
636     This now works:
637       log { ... }.map { ... }
638
639     Instead of doing:
640       result = []
641       log { result = ... }
642       result.map { ... }
643
644 * Added "socket" option for the MySQL adapter, so you can change it to something else than "/tmp/mysql.sock" [Anna Lissa Cruz]
645
646 * Added respond_to? answers for all the attribute methods. So if Person has a name attribute retrieved from the table schema,
647   person.respond_to? "name" will return true.
648
649 * Added Base.benchmark which can be used to aggregate logging and benchmark, so you can measure and represent multiple statements in a single block.
650   Usage (hides all the SQL calls for the individual actions and calculates total runtime for them all):
651
652     Project.benchmark("Creating project") do
653       project = Project.create("name" => "stuff")
654       project.create_manager("name" => "David")
655       project.milestones << Milestone.find_all
656     end
657
658 * Added logging of invalid SQL statements [Suggested by Daniel Von Fange]
659
660 * Added alias Errors#[] for Errors#on, so you can now say person.errors["name"] to retrieve the errors for name [Andreas Schwarz]
661
662 * Added RubyGems require attempt if sqlite-ruby is not available through regular methods.
663
664 * Added compatibility with 2.x series of sqlite-ruby drivers. [Jamis Buck]
665
666 * Added type safety for association assignments, so a ActiveRecord::AssociationTypeMismatch will be raised if you attempt to
667   assign an object that's not of the associated class. This cures the problem with nil giving id = 4 and fixnums giving id = 1 on
668   mistaken association assignments. [Reported by Andreas Schwarz]
669
670 * Added the option to keep many fixtures in one single YAML document [what-a-day]
671
672 * Added the class method "inheritance_column" that can be overwritten to return the name of an alternative column than "type" for storing
673   the type for inheritance hierarchies. [Dave Steinberg]
674
675 * Added [] and []= as an alternative way to access attributes when the regular methods have been overwritten [Dave Steinberg]
676
677 * Added the option to observer more than one class at the time by specifying observed_class as an array
678
679 * Added auto-id propagation support for tables with arbitrary primary keys that have autogenerated sequences associated with them
680   on PostgreSQL. [Dave Steinberg]
681
682 * Changed that integer and floats set to "" through attributes= remain as NULL. This was especially a problem for scaffolding and postgresql. (#49)
683
684 * Changed the MySQL Adapter to rely on MySQL for its defaults for socket, host, and port [Andreas Schwarz]
685
686 * Changed ActionControllerError to decent from StandardError instead of Exception. It can now be caught by a generic rescue.
687
688 * Changed class inheritable attributes to not use eval [Caio Chassot]
689
690 * Changed Errors#add to now use "invalid" as the default message instead of true, which means full_messages work with those [Marcel Molina Jr]
691
692 * Fixed spelling on Base#add_on_boundry_breaking to Base#add_on_boundary_breaking (old naming still works) [Marcel Molina Jr.]
693
694 * Fixed that entries in the has_and_belongs_to_many join table didn't get removed when an associated object was destroyed.
695
696 * Fixed unnecessary calls to SET AUTOCOMMIT=0/1 for MySQL adapter [Andreas Schwarz]
697
698 * Fixed PostgreSQL defaults are now handled gracefully [Dave Steinberg]
699
700 * Fixed increment/decrement_counter are now atomic updates [Andreas Schwarz]
701
702 * Fixed the problems the Inflector had turning Attachment into attuchments and Cases into Casis [radsaq/Florian Gross]
703
704 * Fixed that cloned records would point attribute references on the parent object [Andreas Schwarz]
705
706 * Fixed SQL for type call on inheritance hierarchies [Caio Chassot]
707
708 * Fixed bug with typed inheritance [Florian Weber]
709
710 * Fixed a bug where has_many collection_count wouldn't use the conditions specified for that association
711
712
713 *0.9.5*
714
715 * Expanded the table_name guessing rules immensely [Florian Green]. Documentation:
716
717     Guesses the table name (in forced lower-case) based on the name of the class in the inheritance hierarchy descending
718     directly from ActiveRecord. So if the hierarchy looks like: Reply < Message < ActiveRecord, then Message is used
719     to guess the table name from even when called on Reply. The guessing rules are as follows:
720     * Class name ends in "x", "ch" or "ss": "es" is appended, so a Search class becomes a searches table.
721     * Class name ends in "y" preceded by a consonant or "qu": The "y" is replaced with "ies",
722       so a Category class becomes a categories table.
723     * Class name ends in "fe": The "fe" is replaced with "ves", so a Wife class becomes a wives table.
724     * Class name ends in "lf" or "rf": The "f" is replaced with "ves", so a Half class becomes a halves table.
725     * Class name ends in "person": The "person" is replaced with "people", so a Salesperson class becomes a salespeople table.
726     * Class name ends in "man": The "man" is replaced with "men", so a Spokesman class becomes a spokesmen table.
727     * Class name ends in "sis": The "i" is replaced with an "e", so a Basis class becomes a bases table.
728     * Class name ends in "tum" or "ium": The "um" is replaced with an "a", so a Datum class becomes a data table.
729     * Class name ends in "child": The "child" is replaced with "children", so a NodeChild class becomes a node_children table.
730     * Class name ends in an "s": No additional characters are added or removed.
731     * Class name doesn't end in "s": An "s" is appended, so a Comment class becomes a comments table.
732     * Class name with word compositions: Compositions are underscored, so CreditCard class becomes a credit_cards table.
733     Additionally, the class-level table_name_prefix is prepended to the table_name and the table_name_suffix is appended.
734     So if you have "myapp_" as a prefix, the table name guess for an Account class becomes "myapp_accounts".
735    
736     You can also overwrite this class method to allow for unguessable links, such as a Mouse class with a link to a
737     "mice" table. Example:
738    
739       class Mouse < ActiveRecord::Base
740          def self.table_name() "mice" end
741       end
742  
743   This conversion is now done through an external class called Inflector residing in lib/active_record/support/inflector.rb.
744
745 * Added find_all_in_collection to has_many defined collections. Works like this:
746
747     class Firm < ActiveRecord::Base
748       has_many :clients
749     end
750    
751     firm.id # => 1
752     firm.find_all_in_clients "revenue > 1000" # SELECT * FROM clients WHERE firm_id = 1 AND revenue > 1000
753
754   [Requested by Dave Thomas]
755
756 * Fixed finders for inheritance hierarchies deeper than one level [Florian Weber]
757
758 * Added add_on_boundry_breaking to errors to accompany add_on_empty as a default validation method. It's used like this:
759
760     class Person < ActiveRecord::Base
761       protected
762         def validation
763           errors.add_on_boundry_breaking "password", 3..20
764         end
765     end
766    
767   This will add an error to the tune of "is too short (min is 3 characters)" or "is too long (min is 20 characters)" if
768   the password is outside the boundry. The messages can be changed by passing a third and forth parameter as message strings.
769
770 * Implemented a clone method that works properly with AR. It returns a clone of the record that
771   hasn't been assigned an id yet and is treated as a new record.
772
773 * Allow for domain sockets in PostgreSQL by not assuming localhost when no host is specified [Scott Barron]
774
775 * Fixed that bignums are saved properly instead of attempted to be YAMLized [Andreas Schwartz]
776
777 * Fixed a bug in the GEM where the rdoc options weren't being passed according to spec [Chad Fowler]
778
779 * Fixed a bug with the exclusively_dependent option for has_many
780
781
782 *0.9.4*
783
784 * Correctly guesses the primary key when the class is inside a module [Dave Steinberg].
785
786 * Added [] and []= as alternatives to read_attribute and write_attribute [Dave Steinberg]
787
788 * has_and_belongs_to_many now accepts an :order key to determine in which order the collection is returned [radsaq].
789
790 * The ids passed to find and find_on_conditions are now automatically sanitized.
791
792 * Added escaping of plings in YAML content.
793
794 * Multi-parameter assigns where all the parameters are empty will now be set to nil instead of a new instance of their class.
795
796 * Proper type within an inheritance hierarchy is now ensured already at object initialization (instead of first at create)
797
798
799 *0.9.3*
800
801 * Fixed bug with using a different primary key name together with has_and_belongs_to_many [Investigation by Scott]
802
803 * Added :exclusively_dependent option to the has_many association macro. The doc reads:
804
805     If set to true all the associated object are deleted in one SQL statement without having their
806     before_destroy callback run. This should only be used on associations that depend solely on
807     this class and don't need to do any clean-up in before_destroy. The upside is that it's much
808     faster, especially if there's a counter_cache involved.
809
810 * Added :port key to connection options, so the PostgreSQL and MySQL adapters can connect to a database server
811   running on another port than the default.
812
813 * Converted the new natural singleton methods that prevented AR objects from being saved by PStore
814   (and hence be placed in a Rails session) to a module. [Florian Weber]
815
816 * Fixed the use of floats (was broken since 0.9.0+)
817
818 * Fixed PostgreSQL adapter so default values are displayed properly when used in conjunction with
819   Action Pack scaffolding.
820
821 * Fixed booleans support for PostgreSQL (use real true/false on boolean fields instead of 0/1 on tinyints) [radsaq]
822
823
824 *0.9.2*
825
826 * Added static method for instantly updating a record
827
828 * Treat decimal and numeric as Ruby floats [Andreas Schwartz]
829
830 * Treat chars as Ruby strings (fixes problem for Action Pack form helpers too)
831
832 * Removed debugging output accidently left in (which would screw web applications)
833
834
835 *0.9.1*
836
837 * Added MIT license
838
839 * Added natural object-style assignment for has_and_belongs_to_many associations. Consider the following model:
840
841     class Event < ActiveRecord::Base
842       has_one_and_belongs_to_many :sponsors
843     end
844    
845     class Sponsor < ActiveRecord::Base
846       has_one_and_belongs_to_many :sponsors
847     end
848
849   Earlier, you'd have to use synthetic methods for creating associations between two objects of the above class:
850  
851     roskilde_festival.add_to_sponsors(carlsberg)
852     roskilde_festival.remove_from_sponsors(carlsberg)
853
854     nike.add_to_events(world_cup)
855     nike.remove_from_events(world_cup)
856    
857   Now you can use regular array-styled methods:
858  
859     roskilde_festival.sponsors << carlsberg
860     roskilde_festival.sponsors.delete(carlsberg)
861
862     nike.events << world_cup
863     nike.events.delete(world_cup)
864
865 * Added delete method for has_many associations. Using this will nullify an association between the has_many and the belonging
866   object by setting the foreign key to null. Consider this model:
867  
868     class Post < ActiveRecord::Base
869       has_many :comments
870     end
871
872     class Comment < ActiveRecord::Base
873       belongs_to :post
874     end
875
876   You could do something like:
877
878     funny_comment.has_post? # => true
879     announcement.comments.delete(funny_comment)
880     funny_comment.has_post? # => false
881
882
883 *0.9.0*
884
885 * Active Record is now thread safe! (So you can use it with Cerise and WEBrick applications)
886   [Implementation idea by Michael Neumann, debugging assistance by Jamis Buck]
887
888 * Improved performance by roughly 400% on a basic test case of pulling 100 records and querying one attribute.
889   This brings the tax for using Active Record instead of "riding on the metal" (using MySQL-ruby C-driver directly) down to ~50%.
890   Done by doing lazy type conversions and caching column information on the class-level.
891
892 * Added callback objects and procs as options for implementing the target for callback macros.
893
894 * Added "counter_cache" option to belongs_to that automates the usage of increment_counter and decrement_counter. Consider:
895
896     class Post < ActiveRecord::Base
897       has_many :comments
898     end
899
900     class Comment < ActiveRecord::Base
901       belongs_to :post
902     end
903
904   Iterating over 100 posts like this:
905  
906     <% for post in @posts %>
907       <%= post.title %> has <%= post.comments_count %> comments
908     <% end %>
909    
910   Will generate 100 SQL count queries -- one for each call to post.comments_count. If you instead add a "comments_count" int column
911   to the posts table and rewrite the comments association macro with:
912
913     class Comment < ActiveRecord::Base
914       belongs_to :post, :counter_cache => true
915     end
916  
917   Those 100 SQL count queries will be reduced to zero. Beware that counter caching is only appropriate for objects that begin life
918   with the object it's specified to belong with and is destroyed like that as well. Typically objects where you would also specify
919   :dependent => true. If your objects switch from one belonging to another (like a post that can be move from one category to another),
920   you'll have to manage the counter yourself.
921
922 * Added natural object-style assignment for has_one and belongs_to associations. Consider the following model:
923
924     class Project < ActiveRecord::Base
925       has_one :manager
926     end
927    
928     class Manager < ActiveRecord::Base
929       belongs_to :project
930     end
931  
932   Earlier, assignments would work like following regardless of which way the assignment told the best story:
933  
934     active_record.manager_id = david.id
935  
936   Now you can do it either from the belonging side:
937
938     david.project = active_record
939  
940   ...or from the having side:
941  
942     active_record.manager = david
943  
944   If the assignment happens from the having side, the assigned object is automatically saved. So in the example above, the
945   project_id attribute on david would be set to the id of active_record, then david would be saved.
946
947 * Added natural object-style assignment for has_many associations [Florian Weber]. Consider the following model:
948
949     class Project < ActiveRecord::Base
950       has_many :milestones
951     end
952    
953     class Milestone < ActiveRecord::Base
954       belongs_to :project
955     end
956  
957   Earlier, assignments would work like following regardless of which way the assignment told the best story:
958  
959     deadline.project_id = active_record.id
960  
961   Now you can do it either from the belonging side:
962
963     deadline.project = active_record
964  
965   ...or from the having side:
966  
967     active_record.milestones << deadline
968  
969   The milestone is automatically saved with the new foreign key.
970
971 * API CHANGE: Attributes for text (or blob or similar) columns will now have unknown classes stored using YAML instead of using
972   to_s. (Known classes that won't be yamelized are: String, NilClass, TrueClass, FalseClass, Fixnum, Date, and Time).
973   Likewise, data pulled out of text-based attributes will be attempted converged using Yaml if they have the "--- " header.
974   This was primarily done to be enable the storage of hashes and arrays without wrapping them in aggregations, so now you can do:
975  
976     user = User.find(1)
977     user.preferences = { "background" => "black", "display" => large }
978     user.save
979    
980     User.find(1).preferences # => { "background" => "black", "display" => large }
981  
982   Please note that this method should only be used when you don't care about representing the object in proper columns in
983   the database. A money object consisting of an amount and a currency is still a much better fit for a value object done through
984   aggregations than this new option.
985
986 * POSSIBLE CODE BREAKAGE: As a consequence of the lazy type conversions, it's a bad idea to reference the @attributes hash
987   directly (it always was, but now it's paramount that you don't). If you do, you won't get the type conversion. So to implement
988   new accessors for existing attributes, use read_attribute(attr_name) and write_attribute(attr_name, value) instead. Like this:
989  
990     class Song < ActiveRecord::Base
991       # Uses an integer of seconds to hold the length of the song
992      
993       def length=(minutes)
994         write_attribute("length", minutes * 60)
995       end
996      
997       def length
998         read_attribute("length") / 60
999       end
1000     end
1001
1002   The clever kid will notice that this opens a door to sidestep the automated type conversion by using @attributes directly.
1003   This is not recommended as read/write_attribute may be granted additional responsibilities in the future, but if you think
1004   you know what you're doing and aren't afraid of future consequences, this is an option.
1005
1006 * Applied a few minor bug fixes reported by Daniel Von Fange.
1007
1008
1009 *0.8.4*
1010
1011 _Reflection_
1012
1013 * Added ActiveRecord::Reflection with a bunch of methods and classes for reflecting in aggregations and associations.
1014
1015 * Added Base.columns and Base.content_columns which returns arrays of column description (type, default, etc) objects.
1016
1017 * Added Base#attribute_names which returns an array of names for the attributes available on the object.
1018
1019 * Added Base#column_for_attribute(name) which returns the column description object for the named attribute.
1020
1021
1022 _Misc_
1023
1024 * Added multi-parameter assignment:
1025
1026     # Instantiate objects for all attribute classes that needs more than one constructor parameter. This is done
1027     # by calling new on the column type or aggregation type (through composed_of) object with these parameters.
1028     # So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
1029     # written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
1030     # parenteses to have the parameters typecasted before they're used in the constructor. Use i for Fixnum, f for Float,
1031     # s for String, and a for Array.
1032  
1033   This is incredibly useful for assigning dates from HTML drop-downs of month, year, and day.
1034
1035 * Fixed bug with custom primary key column name and Base.find on multiple parameters.
1036
1037 * Fixed bug with dependent option on has_one associations if there was no associated object.
1038
1039
1040 *0.8.3*
1041
1042 _Transactions_
1043
1044 * Added transactional protection for destroy (important for the new :dependent option) [Suggested by Carl Youngblood]
1045
1046 * Fixed so transactions are ignored on MyISAM tables for MySQL (use InnoDB to get transactions)
1047
1048 * Changed transactions so only exceptions will cause a rollback, not returned false.
1049
1050
1051 _Mapping_
1052
1053 * Added support for non-integer primary keys [Aredridel/earlier work by Michael Neumann]
1054  
1055     User.find "jdoe"
1056     Product.find "PDKEY-INT-12"
1057
1058 * Added option to specify naming method for primary key column. ActiveRecord::Base.primary_key_prefix_type can either
1059   be set to nil, :table_name, or :table_name_with_underscore. :table_name will assume that Product class has a primary key
1060   of "productid" and :table_name_with_underscore will assume "product_id". The default nil will just give "id".
1061    
1062 * Added an overwriteable primary_key method that'll instruct AR to the name of the
1063   id column [Aredridele/earlier work by Guan Yang]
1064    
1065     class Project < ActiveRecord::Base
1066       def self.primary_key() "project_id" end
1067     end
1068
1069 * Fixed that Active Records can safely associate inside and out of modules.
1070
1071     class MyApplication::Account < ActiveRecord::Base
1072       has_many :clients # will look for MyApplication::Client
1073       has_many :interests, :class_name => "Business::Interest" # will look for Business::Interest
1074     end
1075
1076 * Fixed that Active Records can safely live inside modules [Aredridel]
1077
1078     class MyApplication::Account < ActiveRecord::Base
1079     end
1080
1081
1082 _Misc_
1083
1084 * Added freeze call to value object assignments to ensure they remain immutable [Spotted by Gavin Sinclair]
1085  
1086 * Changed interface for specifying observed class in observers. Was OBSERVED_CLASS constant, now is
1087   observed_class() class method. This is more consistant with things like self.table_name(). Works like this:
1088
1089     class AuditObserver < ActiveRecord::Observer
1090       def self.observed_class() Account end
1091       def after_update(account)
1092         AuditTrail.new(account, "UPDATED")
1093       end
1094     end
1095
1096   [Suggested by Gavin Sinclair]
1097
1098 * Create new Active Record objects by setting the attributes through a block. Like this:
1099
1100     person = Person.new do |p|
1101       p.name = 'Freddy'
1102       p.age  = 19
1103     end
1104
1105   [Suggested by Gavin Sinclair]
1106
1107
1108 *0.8.2*
1109
1110 * Added inheritable callback queues that can ensure that certai