Cannot load data file in Sinatra - ruby

I created the following parser:
require "./artist"
require "./song"
require "./genre"
require "debugger"
class Parser
attr_accessor :artists, :genres, :song
attr_reader :mp3
REGEX = /(?<artist>.*)\s\-\s(?<song>.*)\s\[(?<genre>.*)\]/
def initialize(directory="data")
debugger
#mp3 = Dir.entries(directory).select {|f| !File.directory? f}
debugger
end
def parse
#mp3.map do |file|
match = REGEX.match(file)
artist = Artist.find_by_name(match[:artist]) || Artist.new.tap {|artist| artist.name = match[:artist]}
song = Song.new
song.name = match[:song]
song.genre = Genre.find_by_name(match[:genre]) || Genre.new.tap {|genre| genre.name = match[:genre]}
#debugger
artist.add_song(song)
end
end
end
a = Parser.new.parse
I tried running it by calling parser.rb in the directory, lib, where it is located. I get the following error messages:
Parser.rb:47:in `open': No such file or directory - data (Errno::ENOENT)
from parser.rb:47:in `entries'
from parser.rb:47:in `initialize'
from parser.rb:68:in `new'
from parser.rb:68:in `<main>'
This is my file structure:
Can anyone please tell me why it cannot recognize my data directory? I have been staring for a while now and cannot figure it out. It was working like 10 mins ago and I cannot remember what I change to get it all messed up.
Appreciate your feedback! Thanks

You should be able to run your example like ruby -I/lib lib/parser.rb from the directory above lib. The -I will set the "include path", such that the ruby interpreter will find the other required ruby files like (lib/)song.rb.

Related

`initialize': No such file or directory # rb_sysopen when using Nokogiri to open site

I created a CLI program that uses Scraper class to scrape site. I am Using Nokogiri and Open-URI. The error on top is popping up. I looked online and did not find help.
I made sure the site doesn't have typos.
from the CLI class I create a new Scraper class using the site as arg
class KefotoScraper::CLI
attr_accessor :kefoto_scraper
def initialize
site = "https://www.kefotos.mx"
#kefoto_scraper = Scraper.new(site)
end
end
In Scraper I have the following code:
class Scraper
attr_accessor :doc, :product_names, :site, :name, :link
def initialize(site)
#site = site
#doc = doc
#product_names = product_names
#name = name
#link = link
#price_range = [].uniq
scrape_product
end
def get_html
#doc = Nokogiri::HTML(open(#site))
#product_names = doc.css(".navbar-nav li")
product_names
end
def scrape_product
get_html.each {|product|
#name = product.css("span").text
plink = product.css("a").attr("href").text
#link = "#{site}#{link}"
link_doc = Nokogiri::HTML(open(#link))
pr = link_doc.scan(/[\$£](\d{1,3}(,\d{3})*(\.\d*)?)/)
prices = pr_link.text
prices.each {|price|
if #price_range.include?(price[0]) == false
#price_range << price[0]
end
}
new_product = Products.new(#name, #price_range)
puts new_product
}
end
end
I get the following error:
scraper.rb:18:in `initialize': No such file or directory # rb_sysopen - https://www.kefotos.mx (Errno::ENOENT)
open by default operates on local files, not URLs. That error means "I can't find a file on your hard drive named https://www.kefotos.mx".
You can let it work on URIs by requiring the open-uri library:
require 'open-uri'
This will make your code work, but it is a much better practice to use a proper HTTP client to read HTTP resources, as an attacker could potentially use an overloaded open() to access files on your machine's hard drive.
For example, if you were to use just net/http:
# At the top of your scraper.rb:
require 'net/http'
# Then, in your class:
link_doc = Nokogiri::HTML(Net::HTTP.get(URI(#link)))

How to automatically call classes in Ruby script from a specific directory

I have a directory /lib where I store *.rb files. Each one of them contains a class with a single class method remove_user().
How can I make the main script automatically go over those files and call the same method on all of them? I want to just drop-in files in that directory in the future without modifying the main script in any way.
I do know how to require all the files from a directory based on "Best way to require all files from a directory in ruby?", but I'm not very sure how to invoke the classes "in a loop" from here.
Update
I've tried a the code suggested in "How do I create automatically a instance of every class in a directory?"
files = Dir.glob("lib/*.rb")
def load_modules(class_files)
puts class_files
before = ObjectSpace.each_object(Class).to_a
class_files.each {|file| require_relative file }
after = ObjectSpace.each_object(Class).to_a
(after - before).each {|klass| klass.new.delete_user('myemail#mail.com', 'Audit', 'Test')}
load_modules(files)
end
It produces an error:
/Users/apinchuk/RubymineProjects/autoaudit/init.rb:16:in `new': can't create instance of singleton class (TypeError)
from /Users/RubymineProjects/autoaudit/init.rb:16:in `block in load_modules'
from /Users/RubymineProjects/autoaudit/init.rb:16:in `each'
from /Users/RubymineProjects/autoaudit/init.rb:16:in `load_modules'
from /Users/RubymineProjects/autoaudit/init.rb:20:in `<top (required)>'
from -e:1:in `load'
from -e:1:in `<main>'
And there is nothing I could find about this error.
The create_uat_robot.rb has a structure like this:
class CreateUatRobot
def self.delete_user(email, first_name, last_name)
...
end
end
The name of the file is create_uat_robot.rb
Trying #moveson suggestion as follows:
files = Dir.glob("lib/*.rb")
files.each {|file| require_relative file }
klasses = Dir["lib/*.rb"].map {|file| File.basename(file, '.rb').camelize.constantize}
klasses.each { |klass| klass.delete_user(arguments) }
worked for me.
First you need to create an array of class names:
>> klasses = Dir["lib/*.rb"].map {|file| File.basename(file, '.rb').camelize.constantize }
Then you can call your method on each of them in turn:
>> klasses.each { |klass| klass.remove_user }
If you are not using Rails, you can require ActiveSupport's String extension methods (require 'active_support/core_ext/string'), which will give you the camelize and constantize methods.

How do I reference a method in a different class from a method in another class?

I have a module and class in a file lib/crawler/page-crawler.rb that looks like this:
require 'oga'
require 'net/http'
require 'pry'
module YPCrawler
class PageCrawler
attr_accessor :url
def initialize(url)
#url = url
end
def get_page_listings
body = Net::HTTP.get(URI.parse(#url))
document = Oga.parse_html(body)
document.css('div.result')
end
newpage = PageCrawler.new "http://www.someurl"
#listings = newpage.get_page_listings
#listings.each do |listing|
bizname = YPCrawler::ListingCrawler.new listing['id']
end
end
end
Then I have another module & class in another file lib/crawler/listing-crawler.rb that looks like this:
require 'oga'
require 'pry'
module YPCrawler
class ListingCrawler
def initialize(id)
#id = id
end
def extract_busines_name
binding.pry
end
end
end
However, when I try to run this script ruby lib/yp-crawler.rb which executes the page-crawler.rb file above and works without the YPCrawler call, I get this error:
/lib/crawler/page-crawler.rb:23:in `block in <class:PageCrawler>': uninitialized constant YPCrawler::ListingCrawler (NameError)
The issue is on this line:
bizname = YPCrawler::ListingCrawler.new listing['id']
So how do I call that other from within my iterator in my page-crawler.rb?
Edit 1
When I just do `ListingCrawler.new listing['id'], I get the following error:
uninitialized constant YPCrawler::PageCrawler::ListingCrawler (NameError)
Edit 2
Here is the directory structure of my project:
Edit 3
My yp-crawler.rb looks like this:
require_relative "yp-crawler/version"
require_relative "crawler/page-crawler"
require_relative "crawler/listing-crawler"
module YPCrawler
end
In your yp-crawler.rb file, based on the structure that you posted, you should have something like:
require 'yp-crawler/version'
require 'crawler/listing-crawler'
require 'crawler/page-crawler'
Try this, in your yp-crawler.rb add the line:
Dir["#{File.dirname(__FILE__)}/crawler/**/*.rb"].each { |file| load(file) }
That should automatically include all files in your /crawler directory at runtime. Might want to do the same for the other directories.
Let me know if that helps :)

"ruby -I lib test/test_person.rb" not loading "lib"

just learning ruby.
I have two folders inside my directory:
"lib" and "test"
Inside lib\person.rb:
class Person
attr_accessor :name
def introduction
"Hello, my name is #{name}!"
end
end
Inside test\test_person.rb:
require 'minitest/autorun'
require 'person'
class TestPerson < Minitest::Test
def test_introduction
person = Person.new
person.name = 'Bob'
assert(person.introduction == 'Hello, my name is Bob!')
end
end
When I try to run: ruby -I lib test/test_person.rb I get the following error:
(...) cannot load such file -- person (LoadError) (...)
The -I argument seems that is not working. I get the same error without it.
Any clue?
Tnks
Ok, just figure out what is going on...
I am Brazilian, and we have special characters for accents.
My folder name had one of this "ê".
Ruby is able to load the lib. But not able to recall it.
D:\OneDrive\Documentos\Documentos Felipe\Assuntos Acadêmicos>irb -I lib
irb(main):001:0> $:
=> ["D:/OneDrive/Documentos/Documentos Felipe/Assuntos Acad\x88micos/lib",(...)
\x88 = ê
Changed the folder name. Now it is ok.
If anyone knows how to solve this without worry about the name, would be helpful.
Tnks!

Remote_table in spree 0.70.7 controller: #<TypeError: Zip is not a module>

I'm include gem 'remote_table' in my Gemfile (Rails 3.1.12)
In spree admin i'd create new controller:
class Admin::XlsPriceLoadsController < Admin::BaseController
def upload
source_xls = RemoteTable.new(filename)
source_xls.each do |row|
....
end
end
end
but when this action fired, i'm see the next:
TypeError (Zip is not a module):
app/controllers/admin/xls_price_loads_controller.rb:26:in `upload'
...
when i'm explore the source_xls object, a frozen? property of them is true.
So, can any soul write me, why the parsed object is frozed?
And, if i run this code
source_xls = RemoteTable.new(filename)
source_xls.each do |row|
....
end
from lib/tasks as rake task - all work fine!
Thanks for all advice!
Whereabouts does the filename method/attribute come from? Is that something from spree? What value does it have at the point #upload is called?
Regarding
app/controllers/admin/xls_price_loads_controller.rb:26:inupload'`
What's on line 26?

Resources