Prev: Installing Ruby 1.9.2 on Win7
Next: IO.popen
From: Brian Candler on 2 Aug 2010 09:05 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 2 Aug 2010 09:07 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 2 Aug 2010 09:21 >> >> 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 2 Aug 2010 09:24 > 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 2 Aug 2010 09:28
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/. |