module SudoAttributes module Base # Protect attributes using ActiveRecord's built in attr_protected class macro. # When invoked, it also adds other sudo_attributes class and instance methods to model such as +sudo_create+ # # ==== Example # # Define attributes which are protected from mass assignment # class User < ActiveRecord::Base # sudo_attr_protected :admin # end def sudo_attr_protected(*attrs) Private::set_attributes(self, attrs, :protected) end # Protect attributes using ActiveRecord's built in attr_accessible class macro. # When invoked, it also adds other sudo_attributes class and instance methods to model such as +sudo_create+ # # ==== Example # # Define attributes which are not protected from mass assignment # class User < ActiveRecord::Base # sudo_attr_accessible :admin # end def sudo_attr_accessible(*attrs) Private::set_attributes(self, attrs, :accessible) end end module Private # :nodoc: all # Used internally to assign protected attributes and include additional sudo_attributes functionality def self.set_attributes(klass, attrs, type) # Call attr_(accessible|protected) if attributes are passed in klass.send("attr_#{type}", *attrs) unless attrs.empty? klass.extend SudoAttributes::ClassMethods klass.send :include, SudoAttributes::InstanceMethods end end # Added to ActiveRecord model only if sudo_attr_(accessible|protected) is called module ClassMethods # Creates an object with protected attributes 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. # # Unlike ActiveRecord::Base.create, the attributes parameter can only be a Hash. This Hash describes the # attributes on the objects that are to be created. # # ==== Example # # Create a single new object where admin is a protected attribute # User.sudo_create(:first_name => 'Pete', :admin => true) def sudo_create(attributes=nil) instance = sudo_new(attributes) instance.save instance end # Creates an object just like sudo_create but calls save! instead of save so an exception is raised if the record is invalid # # ==== Example # # Create a single new object where admin is a protected attribute # User.sudo_create!(:first_name => 'Pete', :admin => true) def sudo_create!(attributes=nil) instance = sudo_new(attributes) instance.save! instance end # Instantiates an object just like ActiveRecord::Base.new, but allowing mass assignment of protected attributes # # ==== Example # # Instantiate an object where admin is a protected attribute # User.sudo_new(:first_name => 'Pete', :admin => true) def sudo_new(attributes=nil) instance = new(nil) instance.send(:attributes=, attributes, false) instance end alias sudo_build sudo_new end # Added to ActiveRecord model only if sudo_attr_(accessible|protected) is called module InstanceMethods # Updates attributes of a model, including protected ones, from the passed-in hash and saves the # record. If the object is invalid, the saving will fail and false will be returned. # # ==== Example # # Updated protected attributes on an instance of User # @user = User.find(params[:id]) # @user.sudo_update_attributes(params[:user]) def sudo_update_attributes(new_attributes) self.send(:attributes=, new_attributes, false) save end # Updates its receiver just like +sudo_update_attributes+ but calls save! instead # of +save+, so an exception is raised if the record is invalid. # # ==== Example # # Updated protected attributes on an instance of User # @user = User.find(params[:id]) # @user.sudo_update_attributes!(params[:user]) def sudo_update_attributes!(new_attributes) self.send(:attributes=, new_attributes, false) save! end end end ActiveRecord::Base.extend SudoAttributes::Base