Reimond Hill
Reimond Hill

Reputation: 4760

Cocoapods RUBY undefined local variable or method

I am still quite a beginner on Ruby. I am trying to write some extra code to handle our 50 targets Cocoapods dependencies.

With the following code:

testString = "TEST!!!"

def processPods(platform_name)
    project = Xcodeproj::Project.open "./WhiteLabel.xcodeproj"
    project.targets.each { |target| 
        target_name = target.name
        if target.platform_name == platform_name
            puts "Processing #{target_name} for Platform #{platform_name}"
            puts testString #-->Error ...
        end 
    }
end

#Cocoapods methods
abstract_target 'iOS' do
    puts testString #-->Executes
    processPods(:ios)
end

For the sake of the question, "testString" replaces a bigger variable.

When I run the code I get:

TEST!!!
Processing WhiteLabel for Platform ios

[!] Invalid `Podfile` file: undefined local variable or method `testString' for #<Pod::Podfile:0x00007f8fe11cc2d0>.

 #  from ~/Documents/Developer/Xcode/WhiteLabelApple/Podfile:124
 #  -------------------------------------------
 #              puts "Processing #{target_name} for Platform #{platform_name}"
 >              puts testString
 #          end 
 #  -------------------------------------------

Any idea why?

Upvotes: 0

Views: 3497

Answers (2)

kgilpin
kgilpin

Reputation: 2226

If you don't want to change the variable name, you can take advantage of the fact that Ruby blocks are closures; the enclosing variables are accessible within the block.

test_string = "TEST!!!"

process_pods = lambda do |platform_name|
    project = Xcodeproj::Project.open "./WhiteLabel.xcodeproj"
    project.targets.each { |target| 
        target_name = target.name
        if target.platform_name == platform_name
            puts "Processing #{target_name} for Platform #{platform_name}"
            puts test_string #-->Should work ...
        end 
    }
end

abstract_target 'iOS' do
    puts test_string #-->Executes
    process_pods.call(:ios)
end

Sometimes, it's not possible to change the variable to a constant because it is in fact, variable. So putting code in a block provides a way to organize the code without sacrificing access to the surrounding variables.

Upvotes: 1

J&#246;rg W Mittag
J&#246;rg W Mittag

Reputation: 369438

Variables that start with a lowercase letter are local variables. Local variables are local to the scope they are defined in. (Hence why they are called "local" variables.)

In your case, you are defining a local variable named testString in the script scope, and are trying to access it in the scope of the method definition body processPods, where it simply isn't defined.

It works in the block at the bottom, because block scopes nest.

You can either:

  • pass an additional argument to processPods,
  • define the method using a block instead of a method definition expression, or
  • make the variable a constant variable in the Object scope by changing its name to uppercase.

Upvotes: 1

Related Questions