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

I have a user table, and it has forty columns, including name, gender,
address, email, phone…
So my @user object will have forty attributes.
I divide these attributes into 4 groups… namely ‘general info’,
‘personal info’, ‘contact info’… and I make separate forms to edit
these 4 different group attributes.

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.

now, i use
@user.update_attribute(:address, params[:user][:address])
@user.update_attribute(:city, params[:user][:city])
@user.update_attribute(:state, params[:user][:state])
@user.update_attribute(:zip_code, params[:user][:zip_code])
@user.update_attribute(:country, params[:user][:country])
@user.update_attribute(:phone, params[:user][:phone])
@user.update_attribute(:phone_alt, params[:user][:phone_alt])
which seem like a mess.

any other solution?

Nanyang Z. 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

On Dec 8, 2006, at 9:23 AM, Nanyang Z. wrote:

that @user has, so this can’t work.

any other solution?

params[:user].each do |attr,value|
@user.write_attribute(attr, value)
end
@user.save

Rob B. http://agileconsultingllc.com
[email protected]

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?

Thanks, Rob B… I may need your code.

Jeff C., You are right.
My code didn’t work just because there were validations requiring
attributes that current form didn’t contain.

I need these validations, but I still want to create attributes from
different forms.
If I delete these validations in User Model, I will need to add my own
validating judging codes into Controller’s actions, which may bring much
more lines.
How can I keep these smart Rails Validations?

Jeff C. wrote:

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.

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

Jodi S. wrote:

keeping the controller thin, and standardizing the models operation.

Jodi, your idea is cool. I’ll note it down.
But now I don’t know how to write the code.

I use Rob’s code to Update_attribute instead of Update_attributeS. This
skip the validation.

but problem occured when the loop met a date_select attribute(S). This
date attribute(S), which are made up of 3 select boxes, couldn’t be
updated into @user.birthday.

now, i use
params[:user].each do |attr,value|
case attr
when ‘birthday(1i)’
birthday = value
when ‘birthday(2i)’
birthday += “-” + value
when ‘birthday(3i)’
birthday += “-” + value
@user.update_attribute(:birthday, birthday)
else
@user.update_attribute(attr, value)
end
end
@user.save
to deal the problem. It looks BAD, though it works. How can I correct
it?

Jodi, Thank you for your kindness and patience.
After reading some posts about validation, I understand your first post
better.
Now you have just posted another one. With help of these, the work will
be much easier.
Thanks again.

Jodi S. wrote:

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

Rob B. wrote:

params[:user].each do |attr,value|
@user.write_attribute(attr, value)
end

Borrowing from Rob’s idea, couldn’t you write your own validate that
just validates things that are in the “params”? I’m not set up to look
at it right now, but doesn’t the params include all of the form items,
but if there is no text in the form item the value of the param is empty
or nil?

so write your own validate that does something like this:
params.each do |attr,value|
errors.add(attr, “shouldn’t be empty”) if value.blank?
end

This would seem like a good way to do it, if and only if I’m right about
the params hash including items from the form that are blank.

jp

(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