2

Is there a more elegant way to write this in Ruby, maybe using a loop?

def save_related_info
  update_column(:sender_company_name, user.preference.company_name)
  update_column(:sender_address, user.preference.address)
  update_column(:sender_telephone, user.preference.telephone)
  update_column(:sender_email, user.preference.email)
  update_column(:sender_url, user.preference.url)
  update_column(:sender_vat_number, user.preference.vat_number)
  update_column(:sender_payment_details, user.preference.payment_details)
end

Thanks for any help.

1
  • 1
    We don't have enough code, but it looks like that model should have an association to "preference" to avoid such duplication of data, doesn't it? Commented Aug 10, 2013 at 12:07

3 Answers 3

3

Any reason you're not using update_attributes to do them all at once?

def save_related_info
  update_attributes(
    :sender_company_name => user.preference.company_name,
    :sender_address => user.preference.address,
    :sender_telephone => user.preference.telephone,
    :sender_email => user.preference.email,
    :sender_url => user.preference.url,
    :sender_vat_number => user.preference.vat_number,
    :sender_payment_details => user.preference.payment_details
  )
end
Sign up to request clarification or add additional context in comments.

4 Comments

Note that update_column skips validations, callbacks and timestamps updating, so it's not the same.
@tokland That sounds like a bad idea to me, but if the OP does infact want to skip that stuff, Rails 4 has update_columns
I agree, updating with pure SQL ignoring all the model stuff is usually a bad idea.
Good point. I am still learning Ruby, so I just read up on the difference between the two.
2
def save_related_info
  %w[company_name address telephone email url vat_number payment_details]
  .each{|s| update_column("sender_#{s}".to_sym, user.preference.send(s))}
end

7 Comments

maybe shorter with :"sender_#{s}"? and definitely I'd use the standard indented do/end block, more clear just at the expense of 1 line.
@tokland Regarding the symbol literal, it's the same. Putting a method and its block together in one line makes it look easier, I think.
Don't think that build column name from property name it's a good idea. In that example it could be correct but in general could cause a lot of problems and possible errors.
@silent_coder why? that seems like the DRY way of doing it, and from the question is clear there is a 1:1 correspondence, I don't see the problem. If some attribute changes then you create a hash with the exceptions, it's very typical stuff.
If columns and properties did not match then I'd write a column => property hash. But if they all match I won't lose a second with it. Write the simplest code that works, update only when necessary.
|
1

first guess is to put keys in and values in lists and then use loop. something like this:

keys = ['key1', 'key2', 'key3', 'key4']
values = [val1, val2, val3, val4]
keys.each_index do |i|
 update_column(keys[i], values[i])
end

Minus in that approach is that the order of elements in values array should fit for order of keys. You could avoid it of using hash instead of arrays. Code will looks like this:

data = { "key1" => val1, "key2" => val2, "key3" => val3 };
data.each do |key, value|
 update_column(keys, values)
end

6 Comments

note that you'd use zip in the first snippet if you decided to write it this way.
I know that it will be better from ruby style point of view, but I'm coding multiple languages and I prefer to have solid coding style which is the same for most of the languages. But I'm agree, that in Ruby case your better will be used %w notation.
Ok, but personally I prefer to write the most idiomatic code in every language (btw, a lot of languages have zip: haskell, python, scala, erlang, JS+underscore...).
@Ph0en1x If you keep the same style of coding for different languages, then that defeats the purpose of having different languages. Why do you think there are different languages?
Because clients need different languages. And in many cases I can't choose, just use what they ask.
|

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.