One-time script to update 1000s of values in a single column in a table: nil error?

Hi, I have a model called Stock with a value called “strength.” I
wrote a simple method in the Stock.rb model file to update the value
of “strength” for each record in the stocks table. I created a
controller called fix_controller.rb. I don’t have access to the live
system, so the idea is that an admin will go to http://url/fix and a
script will run to check and potentially update the “strength” value
for every record in the stocks table.

fix_controller.rb
^^^^^^^^^^^^^^^
class FixController < ApplicationController

def index
stocks = Stock.find(:all)

stocks.each do |s|
    if s.strength.nil? || s.strength == ''
      puts 'nothing to update'
    else
      s.update_units
    end
end

end
end

Stock.rb
^^^^^^^^^
def update_units
if self.strength == ‘’ || self.strength.nil?
puts ‘nil - cannot update’
elsif self.strength != ‘’ && self.strength != nil
self.strength = self.strength.gsub!(’ ml’, ‘ml’) if
self.strength.gsub!(’ ml’, ‘ml’) != nil
self.strength = self.strength.gsub!(’ mL’, ‘ml’) if
self.strength.gsub!(’ mL’, ‘ml’) != nil
self.strength = self.strength.gsub!(’ g’, ‘g’) if self.strength.gsub!
(’ g’, ‘g’) != nil
self.strength = self.strength.gsub!(’ oz’, ‘oz’) if
self.strength.gsub!(’ oz’, ‘oz’) != nil
self.strength = self.strength.gsub!(’ mg’, ‘mg’) if
self.strength.gsub!(’ mg’, ‘mg’) != nil
end

When I try to run this, I always get the error:

NoMethodError: private method `gsub’ called for nil:NilClass

I’m sure this is a simple error and/or I’m not going about this the
correct way. I really only need to run this code once… Any idea why
I’m getting that error? I’m checking for nil…

it looks like you are trying to strip a leading space from each
“strength” value if its not nil.

something like

stocks = Stock.find(:all, :conditions => ‘(strength IS NOT NULL) AND
(strength != “”)’)

would give you all the stocks values with non-blank values. So you can
skip a lot of your testing above.

You could then do something like

stocks.each do |stock|
stock.strength = stock.strength.to_s.gsub(/^\s+/,’’)
stock.save
end

the above is using a regular expression to match the leading spaces.
the to_s shouldn’t be necessary, because you should only be dealing
with non-nil strength values at this point, but it’s defensive coding.

rails has a string extension .blank? which returns true for empty or
nil or spaces values, e.g.

nil.blank?
[].blank?
" ".blank?
‘’.blank?

all return true

On 18 March 2010 02:26, Clay H. [email protected] wrote:

Stock.rb
^^^^^^^^^
self.strength = self.strength.gsub!(’ ml’, ‘ml’) if

The “gsub bang” method returns nil if no changes are made: it’s a
method for changing string variables in place, not really for
assigning the return value (unless you’re using the return value to
check whether any replacements were made.

Change to:

On 18 March 2010 02:26, Clay H. [email protected] wrote:

correct way. I really only need to run this code once… Any idea why
I’m getting that error? I’m checking for nil…

As you only need to run this once it might be better as a database
migration

If you leave it as an action it should really be a POST. Otherwise
google may come along and ‘fix’ it for you while scanning your site.

Colin

What exactly does the “…in place” part of that mean?

On 18 March 2010 12:18, Clay H. [email protected] wrote:

What exactly does the “…in place” part of that mean?

On Mar 18, 4:42 am, Michael P. [email protected] wrote:

The “gsub bang” method returns nil if no changes are made: it’s a
method for changing string variables in place, not really for
assigning the return value (unless you’re using the return value to
check whether any replacements were made.

If you assign a value to a variable:

my_variable = “100 mg”
you can alter the variable using the bang method without using an =
operator to assign
so :
my_variable = my_variable.gsub(’ mg’, ‘mg’)
is the same as:
my_variable.gsub!(’ mg’, ‘mg’)
but beware of:
my_variable = my_variable.gsub!(’ mg’, ‘mg’)
as if no substitution is made, the new value of my_variable will be
“nil” (as you discovered :wink:

http://ruby-doc.org/core/classes/String.html#M000817

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs