diff options
Diffstat (limited to 'activerecord/lib/active_record/persistence.rb')
-rw-r--r-- | activerecord/lib/active_record/persistence.rb | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index fbbf9082cc..b48a137a73 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -71,6 +71,100 @@ module ActiveRecord klass.allocate.init_with("attributes" => attributes, "new_record" => false, &block) end + # Updates an object (or multiple objects) and saves it to the database, if validations pass. + # The resulting object is returned whether the object was saved successfully to the database or not. + # + # ==== Parameters + # + # * +id+ - This should be the id or an array of ids to be updated. + # * +attributes+ - This should be a hash of attributes or an array of hashes. + # + # ==== Examples + # + # # Updates one record + # Person.update(15, user_name: "Samuel", group: "expert") + # + # # Updates multiple records + # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } } + # Person.update(people.keys, people.values) + # + # # Updates multiple records from the result of a relation + # people = Person.where(group: "expert") + # people.update(group: "masters") + # + # Note: Updating a large number of records will run an UPDATE + # query for each record, which may cause a performance issue. + # When running callbacks is not needed for each record update, + # it is preferred to use {update_all}[rdoc-ref:Relation#update_all] + # for updating all records in a single query. + def update(id = :all, attributes) + if id.is_a?(Array) + id.map.with_index { |one_id, idx| update(one_id, attributes[idx]) }.compact + elsif id == :all + all.each { |record| record.update(attributes) } + else + if ActiveRecord::Base === id + raise ArgumentError, + "You are passing an instance of ActiveRecord::Base to `update`. " \ + "Please pass the id of the object by calling `.id`." + end + object = find(id) + object.update(attributes) + object + end + rescue RecordNotFound + end + + # Destroy an object (or multiple objects) that has the given id. The object is instantiated first, + # therefore all callbacks and filters are fired off before the object is deleted. This method is + # less efficient than #delete but allows cleanup methods and other actions to be run. + # + # This essentially finds the object (or multiple objects) with the given id, creates a new object + # from the attributes, and then calls destroy on it. + # + # ==== Parameters + # + # * +id+ - This should be the id or an array of ids to be destroyed. + # + # ==== Examples + # + # # Destroy a single object + # Todo.destroy(1) + # + # # Destroy multiple objects + # todos = [1,2,3] + # Todo.destroy(todos) + def destroy(id) + if id.is_a?(Array) + id.map { |one_id| destroy(one_id) }.compact + else + find(id).destroy + end + rescue RecordNotFound + end + + # Deletes the row with a primary key matching the +id+ argument, using a + # SQL +DELETE+ statement, and returns the number of rows deleted. Active + # Record objects are not instantiated, so the object's callbacks are not + # executed, including any <tt>:dependent</tt> association options. + # + # You can delete multiple rows at once by passing an Array of <tt>id</tt>s. + # + # Note: Although it is often much faster than the alternative, #destroy, + # skipping callbacks might bypass business logic in your application + # that ensures referential integrity or performs other essential jobs. + # + # ==== Examples + # + # # Delete a single row + # Todo.delete(1) + # + # # Delete multiple rows + # Todo.delete([2,3,4]) + def delete(id_or_array) + where(primary_key => id_or_array).delete_all + end + private # Called by +instantiate+ to decide which class to use for a new # record instance. |