From: Brian Candler on
Kyle Barbour wrote:
> Hello everyone,
>
> I'm new to Ruby, so I'm most likely making an elementary mistake.
> However, searching Google didn't help me find my answer, and after
> mucking around with irb I still haven't figured it out.
>
> I wrote a method that was intended to take all of the files in a given
> directory and put them into an array. Here's the code I wrote:
>
> def getFiles(dir)
> pwdFiles = Array.new
>
> Dir.foreach(dir) do |entry|
> pwdFiles.push(entry) if File.file?(entry) == true
> end
> end
>
> This works fine when called on the working directory --- that is,
> getFiles(Dir.pwd). However, when I call it on a subdirectory --- for
> example, getFiles("doc") --- it only returns one file. I tested to
> make sure that the files being ignored in the subdirectory actually
> gave "true" when tested with File.file?(entry), which they do.
>
> Anyone know what I'm doing wrong?

I'm guessing you need to add this line to the end of your method:

return pwdFiles

or just

pwdFiles

since the return value of a method is the value of the last expression
evaluated.

As an alternative, Dir["etc/*"] builds an Array directly. So you could
have:

def get_files(dir)
Dir["#{dir}/*"].select { |x| File.file?(x) }
end

(Aside: getFiles works fine, but get_files is a more conventional Ruby
method name. Use CamelCase for constants/classes)
--
Posted via http://www.ruby-forum.com/.

From: Brian Candler on
Oh, and another hint: try things out in irb to find out what's
happening.

/$ irb --simple-prompt
>> Dir.chdir("/")
=> 0
>> Dir.foreach("etc") { |x| puts x }
From: James Harrison on
>>
>> def getFiles(dir)
>> pwdFiles = Array.new
>>
>> Dir.foreach(dir) do |entry|
>> pwdFiles.push(entry) if File.file?(entry) == true
>> end
>> end
>>

The symbolic constant for truth is True, not true.

In either case, because File.file? returns either True or False, you can drop the comparison:


>> def getFiles(dir)
>> pwdFiles = Array.new
>>
>> Dir.foreach(dir) do |entry|
>> pwdFiles.push(entry) if File.file?(entry)
>> end
>> end


If this is truly a method in an object, though, bear in mind scoping issues. pwdFiles is only available inside this method definition. When you declare it in your intialize statement, prepend with a scope-changing symbol. The most common in this case is @

def initialize
#will contain all file entries in the directory
@pwdFiles = []
end

def get_files(dir)
@pwdFiles = Array.new

Dir.foreach(dir) do |entry|
@pwdFiles.push(entry) if File.file?(entry) == true
end
end



And pay attention to the advice about camelCase versus snake_case for method names: because Ruby's duck typed, it's helped me out sometimes to be able to glance at my code and tell what is a variable and what isn't very quickly.

Best

James
From: Bob Smith on
> pwdFiles.push(entry) if File.file?(entry) == true

While not an answer to your question, I thought I'd comment on the line
above -- you don't need to add the "== true".

pwdFiles.push(entry) if File.file?(entry)


A little more:

Now, this is just me, but I also try to avoid writing negative logic...
if I wanted only the items where File.file?(entry) was false, I would
write:

pwdFiles.push(entry) unless File.file?(entry)

instead of

pwdFiles.push(entry) if not File.file?(entry)
or
pwdFiles.push(entry) if File.file?(entry) == false



Please note: this is all just personal preference -- your code will work
just fine. I only mention it as you indicated you were new, and I
thought I'd share.


--
Posted via http://www.ruby-forum.com/.

From: Brian Candler on
James Harrison wrote:
> The symbolic constant for truth is True, not true.

That is incorrect, as 5 seconds with irb will show you.

$ irb --simple-prompt
>> true
=> true
>> True
NameError: uninitialized constant True
from (irb):2

(You may have been thinking of TrueClass and FalseClass, perhaps?)

> In either case, because File.file? returns either True or False, you can
> drop the comparison:

It returns true or false, but yes the comparison can be removed.

> If this is truly a method in an object, though, bear in mind scoping
> issues. pwdFiles is only available inside this method definition. When
> you declare it in your intialize statement, prepend with a
> scope-changing symbol. The most common in this case is @
>
> def initialize
> #will contain all file entries in the directory
> @pwdFiles = []
> end

@ is not a "scope changing symbol". @pwdFiles is an instance variable of
the object, whereas pwdFiles is a local variable. They are completely
different concepts.

Since the OP wanted to return the value from the getFiles method, and
not set any instance variables in the object, then a local variable is
appropriate here.
--
Posted via http://www.ruby-forum.com/.

 |  Next  |  Last
Pages: 1 2
Prev: Installing Ruby 1.9.2 on Win7
Next: IO.popen