0

I'm trying to blank out a bunch of columns in an easy-to-read formatted code. I know I could just do this:

@user = User.find(3)
@user.column1 = nil
@user.column2 = nil
@user.column3 = nil
etc...

But that doesn't seem like a very Ruby way to do things, nor is it particularly clean to read.

I'm trying to figure out why I can't just do an 'each do' array like this:

columns = [ "key", "provider", "uid", "access_code",
                "customer_id", "cc_id", "cc_brand", "cc_last4",
                "cc_expiration", "last_payment_id", "last_payment_date",
                "last_payment_amount" ]

columns.each do |record|
  @user.record = nil
end

@user.save

I receive the following error:

undefined method `record=' for #<User:0x00000003a91d18>

I know that similar questions have been asked before, but they are usually related to updated a bunch of different tables. I'm only interested in the user table.

Also, there are a lot of answers linking to http://apidock.com/rails/ActiveRecord/Base/update_all/class. But that's an old deprecated method that apparently bypasses callbacks. That seems rather dangerous.

Can anyone think why a simple 'each do' array won't work?

3 Answers 3

1

You can use send funtion for dynamic functions names:

 @user.send("#{record}=", nil)
Sign up to request clarification or add additional context in comments.

2 Comments

Wow! Speedy and effective answer. That worked perfectly. Thanks!!
Sure, "send" function is presented for solving problem like this, what you was trying to do is call function named record for @user not call the catual function name you want, that's why it raise no function called record for this object, and you can also call @user.send(record) if you want to get the value of the attribute
1

send can also be used to call methods associated with your model (private methods too).

However, since in your case, you are only editing the fields of the ActiveRecord object (and not calling any method), here is an alternative approach:

columns = [ "key", "provider", "uid", "access_code",
            "customer_id", "cc_id", "cc_brand", "cc_last4",
            "cc_expiration", "last_payment_id", "last_payment_date",
            "last_payment_amount" ]

columns.each do |record|
  @user[record] = nil
end

@user.save

1 Comment

This is a great alternative solution. Much cleaner to read. I like it.
1

Another option without resorting to the swiss army knife of send

columns = [ "key", "provider", "uid", "access_code",
            "customer_id", "cc_id", "cc_brand", "cc_last4",
            "cc_expiration", "last_payment_id", "last_payment_date",
            "last_payment_amount" ]

params = columns.map(&:to_sym).zip([nil]).to_h

@user.update_attributes(params)

2 Comments

you can take advantage of zip in place of inject here. columns.zip([nil]).to_h
Nice one @spike. Edited the answer to reflect that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.