How to update partial attributes of a object from a form?

Nanyang Zhan wrote:

The problem is when I update one group of attributes using:
@user.update_attributes(params[:user])
now, because the params[:user] hash only contains partial attributes
that @user has, so this can't work.

update_attributes does not require all attributes to be in the hash you
pass to it. It will just update whatever attributes you provide and
leave the others alone.

Jeff
softiesonrails.com

What I don't understand is why Rails writes the whole row when you call
update_attributes. Why can't it just update the attributes that you pass
in? Any enlightenment on this?

Jeff wrote:

Nanyang I would suggest locking down the possible validation modes
inside your model.

Thus, add a validation instance method like 'strict_validation', and
then key on this inside the validation checks.

validates_presence_of :city, :if => Proc.new {|model| !
model.strict_validation?}

and in your controller,

my_model = Model.new
my_model.strict_validation = true

....

keeping the controller thin, and standardizing the models operation.

(the above is pretty loose code, but hopefully demonstrates the idea)

Cheers,
Jodi
General Partner
The nNovation Group inc.
www.nnovation.ca/blog

(Nanyang, I've read back through the thread, so I hope the following
will work).

Basically you'll want to set 3 varieties of validation. and within
your User model you'll an instance method to indicate the validation
you require.

within the controller (you may need 1 controller per type of
validation, or a way to figure out what validation method you'll use):

user = User.new(params[:user])
user.set_validation(User::GENERAL_INFO) #see model below [or
User::PERSONAL_INFO), User.set_validation(User::CONTACT_INFO]
if user.valid?
   user.save
else
   #deal with the validation error
end

and within your model, define the constants (validation methods,
actual validations, et al.)

class Users < ActiveRecord::Base

validates_presence_of :city, :if => Proc.new {|model| ! model.
contact_info_validation?}

   GENERAL_INFO = 1
   PERSONAL_INFO = 2
   CONTACT_INFO = 3

def set_validation(means)
   @validation_means = means
end

def contact_info_validation?
   @validation_means == User::CONTACT_INFO
end

The above syntax isn't tested, so take the approach run with it.

Note: others with more Ruby Fu may recommend better ways to manage
constants (maybe as symbols), but this approach in general will scale
your requirements well.

Cheers,
Jodi
General Partner
The nNovation Group inc.
www.nnovation.ca/blog