Ruby Invalid argument # rb_sysopen [duplicate] - ruby

This question already has answers here:
No such file or directory # rb_sysopen for external URL / Rails 6.11 / Ruby 3
(2 answers)
Closed 1 year ago.
I'm new to ruby. I have problems with the following code on my windows environment:
require 'open-uri'
require 'nokogiri'
url = "https://www.rottentomatoes.com/m/spectre_2015"
page = Nokogiri::HTML(open(url))
print page
ruby_code
and get this error:
PS C:\Users\xxxxx\Desktop\crawler> ruby crawl.rb
crawl.rb:5:in initialize': Invalid argument # rb_sysopen - https://www.rottentomatoes.com/m/spectre_2015 (Errno::EINVAL) from crawl.rb:5:in open'
from crawl.rb:5:in `'
PS C:\Users\xxxxx\Desktop\crawler>
downloaded / installed ruby + visual studio code
created folder crawler + file crawl.rb
gem install nokogiri + gem install open-uri
run code
I am thankful for every help....

Method :open you call belongs to Kernel class:
> method :open
=> #<Method: Object(Kernel)#open(*)>
I believe you want to call URI.open because you require open-uri gems.
page Nokogiri::HTML(URI.open(url))

As you can see in the documentation of Kernel#open, if your path argument does not start with a | character, it is treated as a file [bold emphasis mine]:
open(path [, mode [, perm]] [, opt]) → io or nil
open(path [, mode [, perm]] [, opt]) {|io| block } → obj
Creates an IO object connected to the given stream, file, or subprocess.
If path does not start with a pipe character (|), treat it as the name of a file to open using the specified mode (defaulting to “r”).
So, you are telling Ruby to open a subdirectory of the current directory named https:, and inside that subdirectory open a subdirectory named www.rottentomatoes.com, and inside that subdirectory open a subdirectory named m, and inside that subdirectory open a file named spectre_2015. And what Ruby is telling you, is that it cannot find that file.
If what you are trying to do is to download the document to which that URI resolves, then you can use the open-uri library that is part of the Ruby standard library. The open-uri library provides a method called URI::open, which lets you treat a URI like an IO stream:
require 'open-uri'
require 'nokogiri'
url = 'https://www.rottentomatoes.com/m/spectre_2015'
page = Nokogiri.HTML(URI.open(url))
print page

Related

RubyZip Unzipping .docx, modifying, and zipping back up throws Errno::EACCESS error

So, I'm using Nokogiri and Rubyzip to unzip a .docx file, modify the word/docoument.xml file in it (in this case just change every element wrapped in to say "Dreams!"), and then zip it back up.
require 'nokogiri'
require 'zip'
zip = Zip::File.open("apple.docx")
doc = zip.find_entry("word/document.xml")
xml = Nokogiri::XML.parse(doc.get_input_stream)
inputs = xml.root.xpath("//w:t")
inputs.each{|element| element.content = "DREAMS!"}
zip.get_output_stream("word/document.xml", "w") {|f| f.write(xml.to_s)}
zip.close
Running the code through IRB line by line works perfectly and makes the changes to the .docx file as I needed, but if I run the script from the command line
ruby xmltodoc.rb
I receive the following error:
C:/Ruby193/lib/ruby/gems/1.9.1/gems/rubyzip-1.1.7/lib/zip/file.rb:416:in `rename': Permission denied - (C:/Users/Bane/De
sktop/apple.docx20150326-6016-k9ff1n, apple.docx) (Errno::EACCES)
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rubyzip-1.1.7/lib/zip/file.rb:416:in `on_success_replace'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rubyzip-1.1.7/lib/zip/file.rb:308:in `commit'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rubyzip-1.1.7/lib/zip/file.rb:332:in `close'
from ./xmltodoc.rb:15:in `<main>'
All users on my computer have all permissions for that .docx file. The file also doesn't have any special settings--just a new file with a paragraph. This error only shows up on Windows, but the script works perfectly on Mac and Ubuntu. Running Powershell as Admin throws the same error. Any ideas?
On my Windows 7 system the following works.
require 'nokogiri'
require 'zip'
Zip::File.open("#{File.dirname(__FILE__)}/apple.docx") do |zipfile|
doc = zipfile.read("word/document.xml")
xml = Nokogiri::XML.parse(doc)
inputs = xml.root.xpath("//w:t")
inputs.each{|element| element.content = "DREAMS!"}
zipfile.get_output_stream("word/document.xml") {|f| f.write(xml.to_s)}
end
Instead you also could use the gem docx, here is an example, the names of the bookmarks are in dutch because, well that's the language my MS Office is in.
require 'docx'
# Create a Docx::Document object for our existing docx file
doc = Docx::Document.open('C:\Users\Gebruiker\test.docx'.gsub(/\\/,'/'))
# Insert a single line of text after one of our bookmarks
# p doc.bookmarks['bladwijzer1'].methods
doc.bookmarks['bladwijzer1'].insert_text_after("Hello world.")
# Insert multiple lines of text at our bookmark
doc.bookmarks['bladwijzer3'].insert_multiple_lines(['Hello', 'World', 'foo'])
# Save document to specified path
doc.save('example-edited.docx')

How do I require a Ruby file?

I have a file called "go.rb" that contains:
require 'turboname'
dictionary = Turboname::Random.new
100999032982389.times do
name = Turboname::Domain.new(:from => dictionary)
name.save if name.length < 15 and name.available?
tld = name.tldize
name.save(tld) if tld and name.length < 15 and name.available?(tld)
end
turboname.rb is located in the same directory as go.rb. It's the same level. I just want to include this file in this script. I don't want to deal with gems or bundles.
./turboname.rb:1:in `require': no such file to load -- turboname/version (LoadError)
from ./turboname.rb:1
from go.rb:1:in `require'
from go.rb:1
Use a require_relative Statement
Recent Ruby versions no longer add . to the load path stored in $:. However, one solution is to use Kernel#require_relative to require a file relative to the current value of __FILE__. For example:
require_relative './turboname'
Note that this doesn't work in interactive REPL sessions with irb or pry, but works fine within actual source files.
The error isn't telling you it can't find ./turboname.rb. It's telling you that it found that file, but the first line of ./turboname.rb tries to require 'turboname/version', which Ruby can't find. Does ./turboname/version.rb exist? If so, is it readable by the current user?
If everything else checks out, then you have a load-path problem. At the top of go.rb, explicitly add the current working directory (or whichever directory contains turboname.rb and turboname/version.rb (possibly ./lib/) to your load path:
$LOAD_PATH << File.dirname(__FILE__) # for ./
# or
$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib') # for ./lib/
With Ruby 2.0:
require "#{__dir__}/turboname"

Ruby 'require' error: cannot load such file

I've one file, main.rb with the following content:
require "tokenizer.rb"
The tokenizer.rb file is in the same directory and its content is:
class Tokenizer
def self.tokenize(string)
return string.split(" ")
end
end
If i try to run main.rb I get the following error:
C:\Documents and Settings\my\src\folder>ruby main.rb
C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- tokenizer.rb (LoadError)
from C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require '
from main.rb:1:in `<main>'
I just noticed that if I use load instead of require everything works fine. What may the problem be here?
I just tried and it works with require "./tokenizer".
Just do this:
require_relative 'tokenizer'
If you put this in a Ruby file that is in the same directory as tokenizer.rb, it will work fine no matter what your current working directory (CWD) is.
Explanation of why this is the best way
The other answers claim you should use require './tokenizer', but that is the wrong answer, because it will only work if you run your Ruby process in the same directory that tokenizer.rb is in. Pretty much the only reason to consider using require like that would be if you need to support Ruby 1.8, which doesn't have require_relative.
The require './tokenizer' answer might work for you today, but it unnecessarily limits the ways in which you can run your Ruby code. Tomorrow, if you want to move your files to a different directory, or just want to start your Ruby process from a different directory, you'll have to rethink all of those require statements.
Using require to access files that are on the load path is a fine thing and Ruby gems do it all the time. But you shouldn't start the argument to require with a . unless you are doing something very special and know what you are doing.
When you write code that makes assumptions about its environment, you should think carefully about what assumptions to make. In this case, there are up to three different ways to require the tokenizer file, and each makes a different assumption:
require_relative 'path/to/tokenizer': Assumes that the relative path between the two Ruby source files will stay the same.
require 'path/to/tokenizer': Assumes that path/to/tokenizer is inside one of the directories on the load path ($LOAD_PATH). This generally requires extra setup, since you have to add something to the load path.
require './path/to/tokenizer': Assumes that the relative path from the Ruby process's current working directory to tokenizer.rb is going to stay the same.
I think that for most people and most situations, the assumptions made in options #1 and #2 are more likely to hold true over time.
Ruby 1.9 has removed the current directory from the load path, and so you will need to do a relative require on this file, as David Grayson says:
require_relative 'tokenizer'
There's no need to suffix it with .rb, as Ruby's smart enough to know that's what you mean anyway.
require loads a file from the $LOAD_PATH. If you want to require a file relative to the currently executing file instead of from the $LOAD_PATH, use require_relative.
I would recommend,
load './tokenizer.rb'
Given, that you know the file is in the same working directory.
If you're trying to require it relative to the file, you can use
require_relative 'tokenizer'
I hope this helps.
Another nice little method is to include the current directory in your load path with
$:.unshift('.')
You could push it onto the $: ($LOAD_PATH) array but unshift will force it to load your current working directory before the rest of the load path.
Once you've added your current directory in your load path you don't need to keep specifying
require './tokenizer'
and can just go back to using
require 'tokenizer'
This will work nicely if it is in a gem lib directory and this is the tokenizer.rb
require_relative 'tokenizer/main'
For those who are absolutely sure their relative path is correct, my problem was that my files did not have the .rb extension! (Even though I used RubyMine to create the files and selected that they were Ruby files on creation.)
Double check the file extensions on your file!
What about including the current directory in the search path?
ruby -I. main.rb
I used jruby-1.7.4 to compile my ruby code.
require 'roman-numerals.rb'
is the code which threw the below error.
LoadError: no such file to load -- roman-numerals
require at org/jruby/RubyKernel.java:1054
require at /Users/amanoharan/.rvm/rubies/jruby-1.7.4/lib/ruby/shared/rubygems/custom_require.rb:36
(root) at /Users/amanoharan/Documents/Aptana Studio 3 Workspace/RubyApplication/RubyApplication1/Ruby2.rb:2
I removed rb from require and gave
require 'roman-numerals'
It worked fine.
The problem is that require does not load from the current directory. This is what I thought, too but then I found this thread. For example I tried the following code:
irb> f = File.new('blabla.rb')
=> #<File:blabla.rb>
irb> f.read
=> "class Tokenizer\n def self.tokenize(string)\n return string.split(
\" \")\n end\nend\n"
irb> require f
LoadError: cannot load such file -- blabla.rb
from D:/dev/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `req
uire'
from D:/dev/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `req
uire'
from (irb):24
from D:/dev/Ruby193/bin/irb:12:in `<main>'
As it can be seen it read the file ok, but I could not require it (the path was not recognized). and here goes code that works:
irb f = File.new('D://blabla.rb')
=> #<File:D://blabla.rb>
irb f.read
=> "class Tokenizer\n def self.tokenize(string)\n return string.split(
\" \")\n end\nend\n"
irb> require f
=> true
As you can see if you specify the full path the file loads correctly.
First :
$ sudo gem install colored2
And,you should input your password
Then :
$ sudo gem update --system
Appear
Updating rubygems-update
ERROR: While executing gem ... (OpenSSL::SSL::SSLError)
hostname "gems.ruby-china.org" does not match the server certificate
Then:
$ rvm -v
$ rvm get head
Last
What language do you want to use?? [ Swift / ObjC ]
ObjC
Would you like to include a demo application with your library? [ Yes / No ]
Yes
Which testing frameworks will you use? [ Specta / Kiwi / None ]
None
Would you like to do view based testing? [ Yes / No ]
No
What is your class prefix?
XMG
Running pod install on your new library.
you need to give the path.
Atleast you should give the path from the current directory. It will work for sure.
./filename

Why I can't load scripts with specific filenames with `load`?

Yesterday I discovered, that I can't reload my script rss.rb using load. It only do something unknown for me for several seconds, returns true and doesn't execute script. But It can be loaded (once) with no problems using require_relative. I had to rename script file, to use it as I wanted.
So why require_relative works, but load doesn't? And how to know, which filenames can't be loaded with load?
I'm using ruby 1.9.2p0 (2010-08-18) [i386-mingw32]
UPD: C:> type 1.rb
p load 'rss.rb'
p load '2.rb'
C:> type rss.rb
p 'rss.rb loaded'
C:> type 2.rb
p '2.rb loaded'
C:> ruby 1.rb
true
"2.rb loaded"
true
You're loading the rss.rb from the standard library. load goes through the $LOAD_PATH first and only if the file is not found there, looks for the file in the current directory.
You can make it look only in the current directory by doing load "./rss.rb".
The reason it works with require_relative is that require_relative never looks at the $LOAD_PATH.
When using load you should keep in mind that load, unlike require_relative will look for the file in the current directory, not in the directory where the script is. So whether or not it finds the file depends on which directory you're in when invoking the script. (Of course the same was true for loading local files using require in previous ruby versions).

Rails irb default directory

I'm trying to include a source code file when I run irb but irb is unable to find it.
For example, say I am in the following directory in terminal:
/dan/rubyapp/
Assume I have a file named "firstapp.rb" in /dan/rubyapp/
I startup irb and from the irb prompt I type
> require "firstapp.rb"
but the file can't be found. If I type "Dir.pwd" it shows as
/dan/rubyapp/
The only way I can get "require" to work is if I include the full path like so
> require "/dan/rubyapp/firstapp.rb"
Is that the only way I can get this to work? All the tutorials I see online simply do "require file_name" so I assumed it would work.
here is the output from $: at irb
ruby-1.9.2-p0 > $:
=> ["/Users/Daniel/.rvm/gems/ruby-1.9.2-p0/gems/wirble-0.1.3/bin",
"/Users/Daniel/.rvm/gems/ruby-1.9.2-p0/gems/wirble-0.1.3/lib",
"/Users/Daniel/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/site_ruby/1.9.1",
"/Users/Daniel/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/site_ruby/1.9.1/x86_64-darwin10.4.0",
"/Users/Daniel/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/site_ruby",
"/Users/Daniel/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/vendor_ruby/1.9.1",
"/Users/Daniel/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/vendor_ruby/1.9.1/x86_64-darwin10.4.0",
"/Users/Daniel/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/vendor_ruby",
"/Users/Daniel/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1",
"/Users/Daniel/.rvm/rubies/ruby-
1.9.2-p0/lib/ruby/1.9.1/x86_64-darwin10.4.0"]
The problem is that the current working directory is no longer in your path (as of Ruby 1.9.2). There are a few different ways around the problem.
1) In a ruby file itself, you can use the method require_relative instead of require. This will load a file relative to the loaction of the file containing the require_relative method:
http://extensions.rubyforge.org/rdoc/classes/Kernel.html
require_relative 'firstapp.rb'
This, however, will not work in irb.
2) Your other option is to include the current path in your argument to the require method. This will work in irb or in a ruby file. For instance:
require './firstapp.rb'
The reason this was implemented in ruby was to avoid inadvertently requiring the wrong file if there are different files with the same name in different directories in the path (similar to how *nix does not include the current directory "." in its path)
A couple of things to try:
1) Drop the .rb from the end of your require so you have:
require 'firstapp'
You don't normally add the .rb to a require (only to a load) - have a look here for more details:
http://www.fromjavatoruby.com/2008/10/require-vs-load.html
2) Failing that, make sure the current directory is on your load path - in irb execute:
p $:
and it will print out your ruby load path - check for an entry for "." (mine is the last entry)

Resources