I've got a ruby script
#!/usr/bin/ruby
require 'rubygems'
require 'mechanize'
require 'nokogiri'
require 'highline/import'
require 'stringio'
#Change based on Semester
$term = '09'
$year = '2012'
$frequency = 4 #Number of Seconds between check requests
$agent = Mechanize.new
$agent.redirect_ok = true
$agent.user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.11 Safari/535.19"
$agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
#Uber simway to colorize outputin
class String
def color(c)
colors = {
:black => 30,
:red => 31,
:green => 32,
:yellow => 33,
:blue => 34,
:magenta => 35,
:cyan => 36,
:white => 37
}
return "\e[#{colors[c] || c}m#{self}\e[0m"
end
end
#Logins, Gets the Courses, Returns Courses Obj with Name/URL/Tools for each
def login(username, password)
#Login to the system!
page = $agent.get("https://auth.vt.edu/login?service=https://webapps.banner.vt.edu/banner-cas-prod/authorized/banner/SelfService")
login = page.forms.first
login.set_fields({
:username => username,
:password => password
})
if (login.submit().body.match(/Invalid username or password/)) then
return false
else
return true
end
end
#Gets Course Information
def getCourse(crn)
begin
courseDetails = Nokogiri::HTML( $agent.get(
"https://banweb.banner.vt.edu/ssb/prod/HZSKVTSC.P_ProcComments?CRN=#{crn}&TERM=#{$term}&YEAR=#{$year}"
).body)
rescue
return false #Failed to get course
end
#Flatten table to make it easier to work with
course = {}
dataSet = false
course[:title] = courseDetails.css('td.title').last.text.gsub(/-\ +/, '')
course[:crn] = crn
courseDetails.css('table table tr').each_with_index do |row|
#If we have a dataSet
case dataSet
when :rowA
[ :i, :days, :end, :begin, :end, :exam].each_with_index do |el, i|
if row.css('td')[i] then
course[el] = row.css('td')[i].text
end
end
when :rowB
[ :instructor, :type, :status, :seats, :capacity ].each_with_index do |el, i|
course[el] = row.css('td')[i].text
end
end
dataSet = false
#Is there a dataset?
row.css('td').each do |cell|
case cell.text
when "Days"
dataSet = :rowA
when "Instructor"
dataSet = :rowB
end
end
end
return course
end
#Registers you for the given CRN, returns true if successful, false if not
def registerCrn(crn)
#Follow Path
$agent.get("https://banweb.banner.vt.edu/ssb/prod/twbkwbis.P_GenMenu?name=bmenu.P_MainMnu")
reg = $agent.get("https://banweb.banner.vt.edu/ssb/prod/hzskstat.P_DispRegStatPage")
dropAdd = reg.link_with(:href => "/ssb/prod/bwskfreg.P_AddDropCrse?term_in=#{$year}#{$term}").click
#Fill in CRN Box and Submit
crnEntry = dropAdd.form_with(:action => '/ssb/prod/bwckcoms.P_Regs')
crnEntry.fields_with(:id => 'crn_id1').first.value = crn
crnEntry['CRN_IN'] = crn
add = crnEntry.submit(crnEntry.button_with(:value => 'Submit Changes')).body
if add =~ /#{crn}/ && !(add =~ /Registration Errors/) then
return true
else
return false
end
end
#Main loop that checks the availaibility of each courses and fires to registerCrn on availaibility
def checkCourses(courses)
requestCount = 0
startTime = Time.new
loop do
system("clear")
requestCount += 1
nowTime = Time.new
puts "Checking Availaibility of CRNs".color(:yellow)
puts "--------------------------------\n"
puts "Started:\t#{startTime.asctime}".color(:magenta)
puts "Now: \t#{nowTime.asctime}".color(:cyan)
puts "Request:\t#{requestCount} (Once every #{$frequency} seconds)".color(:green)
puts "--------------------------------\n\n"
courses.each_with_index do |c, i|
puts "#{c[:crn]} - #{c[:title]}".color(:blue)
course = getCourse(c[:crn])
next unless course #If throws error
puts "Availaibility: #{course[:seats]} / #{course[:capacity]}".color(:red)
if (course[:seats] =~ /Full/) then
else
if (registerCrn(c[:crn])) then
puts "CRN #{c[:crn]} Registration Sucessfull"
courses.slice!(i)
else
puts "Couldn't Register"
end
end
print "\n"
end
sleep $frequency
end
end
#Add courses to be checked
def addCourses
crns = []
loop do
system("clear")
puts "Your CRNs:".color(:red)
crns.each do |crn|
puts " -> #{crn[:title]} (CRN: #{crn[:crn]})".color(:magenta)
end
#Prompt for CRN
alt = (crns.length > 0) ? " (or just type 'start') " : " "
input = ask("\nEnter a CRN to add it#{alt}".color(:green) + ":: ") { |q| q.echo = true }
#Validate CRN to be 5 Digits
if (input =~ /^\d{5}$/) then
#Display CRN Info
c = getCourse(input.to_s)
puts "\nCourse: #{c[:title]} - #{c[:crn]}".color(:red)
puts "--> Time: #{c[:begin]}-#{c[:end]} on #{c[:days]}".color(:cyan)
puts "--> Teacher: #{c[:instructor]}".color(:cyan)
puts "--> Type: #{c[:type]} || Status: #{c[:status]}".color(:cyan)
puts "--> Availability: #{c[:seats]} / #{c[:capacity]}\n".color(:cyan)
#Add Class Prompt
add = ask("Add This Class? (yes/no)".color(:yellow) + ":: ") { |q| q.echo = true }
crns.push(c) if (add =~ /yes/)
elsif (input == "start") then
checkCourses(crns)
end
end
end
def main
system("clear")
puts "Welcome to CourseAdd by mil".color(:blue)
username = ask("PID ".color(:green) + ":: ") { |q| q.echo = true }
password = ask("Password ".color(:green) + ":: " ) { |q| q.echo = "*" }
system("clear")
if login(username, password) then
addCourses
else
puts "Invalid PID/Password"
exit
end
end
main
but when I run ruby Untitled.rb it give me this error.
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- mechanize (LoadError)
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /Users/user/Desktop/Untitled.rb:3
What does this mean and how can I fix it? I'm not sure if I need to be doing this through an IDE or if terminal works. I'm brand new to ruby so I honestly have not a clue what the issue could be.
You need to install mechanize. In your terminal, type:
gem install mechanize
Retry your script when it finishes installing. If you have other gems that are missing, you can use the same command to install them.
gem install <gem name>
Related
Open-uri and nokogiri are slow to scrape the site I want hence the Net::OpenTimeout execution expired error. I attempted to code a custom error with rescue however I do not know what condition I can look for to raise that custom error.
I attempted to few if else statements however I really just guessed how to check if I was gonna get that error. I hard coded a condition that failed and thus rescued the error. I am very new to ruby and custom errors. In fact this is my first.
class Scrape
Base = 'http://www.wine.com'
##menu = []
##pages = []
def self.index
index_url = Base + "/list/wine/7155?sortBy=savings&pricemax=90"
#below is where I need to check for the condition to
raise the error
if doc = Nokogiri::HTML(open(index_url))
container = doc.css('.prodList')
wines = container.css('.prodItem')
wines.each do |wine|
##menu << {
:link => wine.css('.prodItemInfo_link').attribute('href').value,
:name => wine.css('.prodItemInfo_name').text,
:rating => (wine.css('.averageRating_average').text.to_i) > 0 ?
(wine.css('.averageRating_average').text) : 'no rating',
:price => wine.css('.productPrice_price-saleWhole').text.strip
}
end
##menu.each do |item|
Bottle.new.create(item)
end
else
begin
raise Custom_error
rescue Custom_error => error
puts error.message
end
end
end
def self.scrape_page(wine_obj)
wine_link = wine_obj.link
individual_page = Base + wine_link
docu = Nokogiri::HTML(open(individual_page))
y = docu.css('.viewMoreModule_text')
more = docu.css('.viewMoreModule_text')
##pages << {
:obj => wine_obj,
:name => docu.css('.pipName').text,
:alcohol_percent => y
x = docu.css('.mobileProdAttrs').css('.prodAlcoholPercent')
y = x.css('.prodAlcoholPercent_percent').text,
:price => docu.css('span.productPrice_price-saleWhole').text,
:origin => docu.css('span.prodItemInfo_originText a').text,
:winemaker_notes => docu.css('.viewMoreModule_text').first.text,
:more => y[2].text,
:rating => docu.css('span.averageRating_average').first.text
}
Page.create_find_by_name( ##pages.last )
end
def self.pages
##pages
end
end
class Cli
def run
puts 'loading from cyberspace'
Scrape.index
Bottle.make_list
controller
end
def controller
input = ''
response = ''
puts ' '
view
while input != 11
response = gets.chomp.to_i
input = "#{response}11".to_i
if input == 111
menu
elsif input == 11
exit
elsif input > 0 && input < 26
find_by_input(input)
elsif input != 0 && input != 111
error_1
end
end
end
def view
puts "welcome to the wine bar"
puts "================="
puts " W I N E "
puts " B A R "
puts "================="
puts " "
puts "type 1 for list of wine"
puts " "
puts "type 0 to exit "
end
def menu
wines = Bottle.list
second_input = ''
while second_input != 0
puts "<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>"
puts "type the corresponding number to view more wine info"
puts
"__________________________________________________________________"
wines.each do |wine|
puts "#{wine.index}) #{wine.name} #{wine.price}"
end
second_input = gets.chomp.to_i
if second_input > 0 && second_input < 26
find_by_input(second_input)
elsif second_input == 0
exit
second_input = 0
elsif second_input > 25 && second_input != 101
error_1
end
end
puts <<-DOC
the the wine number again
for winemaker notes
DOC
end
def find_by_input(input)
while input != 0
selection = Bottle.find_by_input(input)
puts "NAME: #{selection.name}"
puts "PRICE: $#{selection.price}"
puts "RATING: #{selection.rating}"
puts "________________________________________"
puts " type #{input} again "
puts " for more info "
puts " provided by the winemaker "
# reseting input and extending user control functionality
third_input = ''
third_input = gets.chomp.to_i
if third_input == selection.index
response = Scrape.scrape_page(selection)
view_2(response, third_input)
elsif input == 0
exit
end
end
end
def view_2(response, old_input)
next_input = ''
while next_input != 0
puts "Alcohol Percent: #{response.alcohol_percent}"
puts "Winemaker Notes: #{response.winemaker_notes}"
puts " "
puts "Type #{old_input} again for more!!"
next_input = gets.chomp.to_i
if next_input == old_input
input = 0
next_input = 0
# refacort as it puts out 88 again and should not. Also 0 is not
exiting with correct behavior
# refactor so looking for "#{input}"1 to prevent the recall of
input
more(response)
end
end
end
def more(response)
puts response.more
puts menu
end
def error_1
puts " WHOA coder "
puts "type a better number!"
end
def exit
puts <<-DOC
well that was fun
Thank you for checking out
my first cli program
DOC
end
end ```
```class Page
attr_accessor :alcohol_percent, :price, :name, :origin, :winemaker_notes,
:rating, :more, :obj
##web_pages = []
def self.create_find_by_name(hash)
if answer = ##web_pages.find{ |obj| obj.name == hash[:name]}
answer
else
self.new.create(hash)
end
end
def create(hash)
hash.each do |key, value|
self.send(("#{key}="), value)
end
save
view_more
end
def view_more
##web_pages.last
end
def save
##web_pages << self
end
end
attr_accessor :link, :name, :price, :rating, :index
##bottles = []
def create(hash)
hash.each do |key, words|
self.send(("#{key}="), words )
end
save
end
def save
##bottles << self
end
def self.make_list
##numbered_list = ##bottles.sort{ |x,y| x.price <=>
y.price}.map.with_index(1) do
|w,i| w.index = i
w
end
end
def self.list
##numbered_list
end
def self.find_by_input(input)
a = ##numbered_list.find{ |wine| wine.index == input}
# puts "#{a.name} $#{a.price} rating: #{a.rating}"
# puts "type #{input} again for winemaker notes"
# more = ''
# while more != 0
# more = gets.chomp.to_i
# (input == more) ? (Scrape.scrape_page(a.link)) : (self.list)
# end
end
end
class Scrape
Base = 'http://www.wine.com'
##menu = []
##pages = []
def self.index
index_url = Base + "/list/wine/7155?sortBy=savings&pricemax=90"
if doc = Nokogiri::HTML(open(index_url))
container = doc.css('.prodList')
wines = container.css('.prodItem')
wines.each do |wine|
##menu << {
:link => wine.css('.prodItemInfo_link').attribute('href').value,
:name => wine.css('.prodItemInfo_name').text,
:rating => (wine.css('.averageRating_average').text.to_i) > 0 ?
(wine.css('.averageRating_average').text) : 'no rating',
:price => wine.css('.productPrice_price-saleWhole').text.strip
}
end
##menu.each do |item|
Bottle.new.create(item)
end
else
begin
raise Custom_error
rescue Custom_error => error
puts error.message
end
end
end
def self.scrape_page(wine_obj)
wine_link = wine_obj.link
individual_page = Base + wine_link
docu = Nokogiri::HTML(open(individual_page))
y = docu.css('.viewMoreModule_text')
more = docu.css('.viewMoreModule_text')
##pages << {
:obj => wine_obj,
:name => docu.css('.pipName').text,
alcholo = docu.css('.mobileProdAttrs').css('.prodAlcoholPercent'),
:alcohol_percent => alcholo.css('.prodAlcoholPercent_percent').text,
:price => docu.css('span.productPrice_price-saleWhole').text,
:origin => docu.css('span.prodItemInfo_originText a').text,
:winemaker_notes => docu.css('.viewMoreModule_text').first.text,
:more => y[2].text,
:rating => docu.css('span.averageRating_average').first.text
}
Page.create_find_by_name( ##pages.last )
end
def self.pages
##pages
end
end
When the internet connection is down/too slow the custom error is raised.
When an exception is thrown, the program stops its normal flow. You need to surround the part of the code that can throw an exception with a begin..rescue clause, and attempt to handle it, re-raise it, or raise another exception instead.
In your example, that would be:
begin
Nokogiri::HTML(open(url))
rescue Net::OpenTimeoutError => e
# log the error message if needed, raise your CustomError instead
raise CustomError, e.message
end
You can omit the begin, and put a rescue clause at the end of the method, ruby will interpret this as if the entire method body was wrapped in a begin..rescue block, something like this:
def open_page(url)
return Nokogiri::HTML(open(url))
rescue Net::OpenTimeoutError => e
raise CustomError, e.message
end
This code gives me these errors in my ruby console:
1) warning: else without rescue is useless
2) syntax error, unexpected end-of-input, expecting keyword_end
Why am I getting both of these errors at the same time?
require 'nokogiri'
require 'httparty'
require 'byebug'
require 'awesome_print'
require 'watir'
def input #takes user input and grabs the url for that particular search
puts "1) Enter the job title that you want to search for \n"
j_input = gets.chomp
job = j_input.split(/ /).join("+")
puts "================================= \n"
puts "1/2)Do you want to input city-and-state(1) or zipcode(2)? \n"
choice = gets.chomp
if choice == "1"
puts "2) Enter the city that you want to search for \n"
city_input = gets.chomp
city = city_input.split(/ /).join("+")
puts "================================= \n"
puts "3) Enter the state that you want to search for \n"
state_input = gets.chomp
state = "+" + state_input
puts target_url = "https://www.indeed.com/resumes/?q=#{job}&l=#{city}%2C#{state}&cb=jt"
elsif choice == "2"
puts "Enter the zipcode that you want to search for \n"
zipcode = gets.chomp
puts target_url = "https://www.indeed.com/resumes?q=#{job}&l=#{zipcode}&cb=jt"
else
puts "error"
end
unparsed_page = HTTParty.get(target_url)
parsed_page = Nokogiri::HTML(unparsed_page)
resume_listing = parsed_page.css('div.sre-entry')
per_page = resume_listing.count
resumes = Array.new
counter = 0
result_count = parsed_page.css('div#result_count').text.split(' ')[0].to_f
page_count = (result_count.to_f / per_page.to_f ).ceil
current_count = 0
byebug
if counter <= 0
unparsed_page = HTTParty.get(target_url)
parsed_page = Nokogiri::HTML(unparsed_page)
resume_listing = parsed_page.css('div.sre-entry')
per_page = resume_listing.count
pagination_resume_listing.each do |resume_listing|
#resume_info = {
# title:
# link:
# skills:
# education:
#}
#resumes << resume_info
puts "Added #{resume_info[:title]}"
else
while current_count <= page_count * per_page
pagination_url = "https://www.indeed.com/resumes?q=#{job}&l=#{zipcode}&co=US&cb=jt&start=#{current_count}"
unparsed_pagination_page = HTTParty.get(pagination_url)
pagination_parsed_page = Nokogiri::HTML(unparsed_pagination_page)
pagination_resume_listing = pagination_parsed_page.css('div.sre-entry')
pagination_resume_listing.each do |resume_listing|
#resume_info = {
# title:
# link:
# skills:
# education:
#}
#resumes << resume_info
puts "Added #{resume_info[:title]}"
current_count += 50
end
end
end
end
end
It won't allow me to fix the else without rescue issue without telling me that it expects an extra end at the end of my code. Of course when I put the end there it does nothing and says that it wants another end
I would say that your code is horribly formatted, but it would first have to be formatted at all to be even that much. Once you format it, the answer is quite obvious, you have a mis-placed end.
puts "Added #{resume_info[:title]}"
# Should be and end here for the "do" block above
else
Here is what it should be:
require 'nokogiri'
require 'httparty'
require 'byebug'
require 'awesome_print'
require 'watir'
def input #takes user input and grabs the url for that particular search
puts "1) Enter the job title that you want to search for \n"
j_input = gets.chomp
job = j_input.split(/ /).join("+")
puts "================================= \n"
puts "1/2)Do you want to input city-and-state(1) or zipcode(2)? \n"
choice = gets.chomp
if choice == "1"
puts "2) Enter the city that you want to search for \n"
city_input = gets.chomp
city = city_input.split(/ /).join("+")
puts "================================= \n"
puts "3) Enter the state that you want to search for \n"
state_input = gets.chomp
state = "+" + state_input
puts target_url = "https://www.indeed.com/resumes/?q=#{job}&l=#{city}%2C#{state}&cb=jt"
elsif choice == "2"
puts "Enter the zipcode that you want to search for \n"
zipcode = gets.chomp
puts target_url = "https://www.indeed.com/resumes?q=#{job}&l=#{zipcode}&cb=jt"
else
puts "error"
end
unparsed_page = HTTParty.get(target_url)
parsed_page = Nokogiri::HTML(unparsed_page)
resume_listing = parsed_page.css('div.sre-entry')
per_page = resume_listing.count
resumes = Array.new
counter = 0
result_count = parsed_page.css('div#result_count').text.split(' ')[0].to_f
page_count = (result_count.to_f / per_page.to_f ).ceil
current_count = 0
byebug
if counter <= 0
unparsed_page = HTTParty.get(target_url)
parsed_page = Nokogiri::HTML(unparsed_page)
resume_listing = parsed_page.css('div.sre-entry')
per_page = resume_listing.count
pagination_resume_listing.each do |resume_listing|
#resume_info = {
# title:
# link:
# skills:
# education:
#}
#resumes << resume_info
puts "Added #{resume_info[:title]}"
end
else
while current_count <= page_count * per_page
pagination_url = "https://www.indeed.com/resumes?q=#{job}&l=#{zipcode}&co=US&cb=jt&start=#{current_count}"
unparsed_pagination_page = HTTParty.get(pagination_url)
pagination_parsed_page = Nokogiri::HTML(unparsed_pagination_page)
pagination_resume_listing = pagination_parsed_page.css('div.sre-entry')
pagination_resume_listing.each do |resume_listing|
#resume_info = {
# title:
# link:
# skills:
# education:
#}
#resumes << resume_info
puts "Added #{resume_info[:title]}"
current_count += 50
end
end
end
end
Lesson here is to ALWAYS format your code, for everyone's sake, most of all your own. There is no excuse to not be formatted, and not doing so leads to trivial problems like this that are difficult to find.
NOTE
I did not test this or run it, simply formatted, which made the mis-matched end obvious.
I'm having difficulty in adding underscores in my program. Also what is troubling me is that I can't seem to figure out how to remove the underscores when the user inputs the correct letter.
class Game
attr_reader :guess_count, :is_over, :word_length
def initialize (secret_word)
#secret_word = secret_word
#guess_count = 0
#is_over = false
#word_length = secret_word.length
end
def check_word(guess)
#guess_count += 1
if #secret_word == guess
puts "Congratulations!"
#is_over = true
else
#is_over = false
puts "Sorry, try again!"
end
end
def subtract_guess_count
counter = #word_length - #guess_count
end
end
puts "User 1, What is your secret word?"
secret_word = gets.chomp
anything = Game.new(secret_word)
while !anything.is_over
puts "User 2, Guess the secret word"
guess = gets.chomp
anything.check_word(guess)
if anything.subtract_guess_count == 0
puts "You lose! the correct word was #{secret_word}"
exit!
end
if anything.is_over == false
puts "You have #{anything.subtract_guess_count} left!"
end
end
Major Edit
To create a string of underscores you can do this:
word = ""
1.upto(#secret_word.length) do
word << "_"
end
To replace a character with an underscore (and vice versa) in a ruby string you can use the syntax:
word[i] = "_"
To print a word with spaces between each letter you can use the following:
array = word.split(//)
array.join(" ")
For your code a check_letter function could be useful:
def check_letter (guess)
if (#secret_word[guess])
for i in 0..((#secret_word.length) -1 )
if #secret_word[i] == guess
#progress[i] = guess
end
end
end
show_progress
check_word(#progress)
end
Working code
#! /usr/bin/env ruby
#
class Game
attr_reader :guess_count, :is_over, :word_length, :progress
def initialize (secret_word)
#secret_word = secret_word
#guess_count = 0
#is_over = false
#word_length = secret_word.length
#progress = ""
1.upto(secret_word.length) do
#progress << "_"
end
end
def check_word(guess)
if #secret_word == guess
puts "Congratulations!"
#is_over = true
else
#is_over = false
puts "Sorry, try again!"
end
end
def check_letter (guess)
if (#secret_word[guess])
for i in 0..((#secret_word.length) -1 )
if #secret_word[i] == guess
#progress[i] = guess
end
end
end
show_progress
check_word(#progress)
end
def show_progress
array = #progress.split(//)
word = ""
array.each do |letter|
word << letter + " "
end
puts word
end
def one_less_guess
#guess_count += 1
end
def subtract_guess_count
counter = #word_length - #guess_count
end
end
puts "User 1, What is your secret word?"
secret_word = gets.chomp
anything = Game.new(secret_word)
while !anything.is_over
puts "User 2, Guess the secret word"
guess = gets.chomp
anything.one_less_guess
if guess.length == 1
anything.check_letter(guess)
else
anything.check_word(guess)
end
if anything.subtract_guess_count == 0
puts "You lose! the correct word was #{secret_word}"
exit!
end
if anything.is_over == false
puts "You have #{anything.subtract_guess_count} left!"
end
end
I've been working on this code for ages and I can't get it working. It takes user information form a text file, creates user groups and puts the users in the groups. It makes the security group just fine, but it does not put the users in the groups. There is no error message but after going through the error checking is goes through the code that should add the user and puts the error at the bottom. Can anyone help please?
The usernames in the text file are setup like so:
fred,bush,1990-20-3,123456781,2008-20-3,D5,
xin,zhao,1990-20-2,123456782,2008-20-3,D5,
bobby,bob,1990-20-1,123456783,2008-20-3,D5,
john,lose,1990-20-4,123456784,2008-20-3,D5,
elly,moose,1990-20-5,123456785,2008-20-3,D5,
jackie,chan,1990-20-6,123456786,2008-20-3,D5,
katarina,lotus,1990-20-7,123456787,2008-20-3,D5,
kelly,nunu,1990-20-8,123456788,2008-20-3,D5,
lois,harris,1990-20-9,123456789,2008-20-3,D5,
gutwold,manly,1990-20-10,123456780,2008-20-3,D5,
griswold,womenly,1990-20-11,123456710,2008-20-3,D5,
bessy,horse,1990-20-12,123456711,2008-20-3,D5,
And the code is:
require 'date'
domain = "dc=TROPTRAIN,dc=net,dc=au"
ou = "ou=studentsOU"
filepath = 'C:\Documents and Settings\Administrator\My Documents\Luke Abbey Ruby Final\userfile\error_log.txt'
users = 'C:\Documents and Settings\Administrator\My Documents\Luke Abbey Ruby Final\userfile\newusers.txt'
#intro function for the program
def intro
system "cls"
puts ""
puts " Tropical Train - Adding users"
puts "====================================================================="
puts ""
end
#get user file
check = 0
while check == 0
intro
puts "Please enter the path to the user file,"
puts "or enter the the letter 's' to use the stored file location:"
puts ""
puts "#{users}"
userfile = gets.chomp.to_s
if ((userfile == 's') || (userfile == 'S'))
check = 1
userfile = users
#puts userfile
#system "pause"
elsif(test(?e,userfile))
check = 1
elsif userfile =~ (/[\x00\/\\:\*\?\"<>\|]/)
puts "The userfile contains invalid characters. Try again."
system "pause"
check = 0
elsif userfile == ""
puts "You entered nothing. Try again."
system "pause"
check = 0
elsif(!test(?e,userfile))
check = 0
puts "The file #{userfile} does not exist. Try again."
system "pause"
else
puts "Your entry is invalid. Try again."
system "pause"
check = 0
end
end
#create the security groups via DOS and check wheteher they already exist
grpC2 = 0
grpC3 = 0
grpC4 = 0
grpD5 = 0
expired = 0
students = 0
%x[dsquery group "dc=troptrain,dc=net,dc=au"].each do |line|
data = line
if line.include?("grpC2")
grpC2 = 1
end
if line.include?("grpC3")
grpC3 = 1
end
if line.include?("grpC4")
grpC4 = 1
end
if line.include?("grpD5")
grpD5 = 1
end
if line.include?("Expired")
expired = 1
end
if line.include?("Students")
students = 1
end
end
if grpC2 != 1
%x[dsadd group "cn=grpC2,ou=studentsOU,dc=troptrain,dc=net,dc=au"]
end
if grpC3 != 1
%x[dsadd group "cn=grpC3,ou=studentsOU,dc=troptrain,dc=net,dc=au"]
end
if grpC4 != 1
%x[dsadd group "cn=grpC4,ou=studentsOU,dc=troptrain,dc=net,dc=au"]
end
if grpD5 != 1
%x[dsadd group "cn=grpD5,ou=studentsOU,dc=troptrain,dc=net,dc=au"]
end
if expired != 1
%x[dsadd group "cn=Expired,ou=studentsOU,dc=troptrain,dc=net,dc=au"]
end
if students != 1
%x[dsadd group "cn=Students,ou=studentsOU,dc=troptrain,dc=net,dc=au"]
end
#open the file
f1 = File.open(userfile,"r")
#read the file line by line
count = 0
f1.each do |line|
data = line.split(',')
firstname = data[0].capitalize
surname = data[1].capitalize
dob = data[2].to_s
snumber = data[3].to_s
enddate1 = data [4].gsub!("-","/")
enddate = enddate1
area = data[5]
fullname = (firstname + (" ") + surname)
group = "cn=#{'grp'+data[5]}"
password1 = data[2].gsub("-", "")
password = password1
count = count + 1
#display values for establishing error checks
#puts ""
#puts "fullname: #{fullname}"
#puts "dob: #{dob}"
#puts "snumber: #{snumber}"
#puts "enddate: #{enddate}"
#puts "area: #{area}"
#puts "password: #{password}"
#puts "group: #{group}"
#puts "count: #{count}"
#puts ""
if ((data[2] =~ /[^0-9-]/) || (data[3] =~ /[^0-9-]/) || (data[4] =~ /[^0-9\/]/) || (data[5] =~ /[^A-Za-z0-9 ]/) || (data[0] =~ /[^A-Za-z ]/) || (data[1] =~ /[^A-Za-z ]/) || (data[0] == "") || (data[1] == "") || (data[2] == "") || (data[3] == "") || (data[4] == "") || (data[5] == "") || (data[6] == ""))
puts ""
puts "====================================================================="
puts "User account No #{count}: #{fullname} was not created."
puts ""
if (File.exist?(filepath))
file = File.open((filepath), "a+")
t = Time.now
file.puts "====================================================================="
file.puts "User account No #{count}: #{fullname} was not created."
file.puts t
file.puts ""
else
puts "Error log cannot be found!"
puts "Searched directory: #{filepath}"
end
#checking database entries for errors
if ((data[0] == "") || (data[0] =~ /[^A-Za-z ]/))
puts "No/Incorrect firstname on file."
file.puts "No/Incorrect firstname on file."
end
if ((data[1] == "") || (data[1] =~ /[^A-Za-z ]/))
puts "No/Incorrect surname on file."
file.puts "No/Incorrect surname on file."
end
if ((data[2] == "") || (data[2] =~ /[^0-9-]/))
puts "No/Incorrect birthdate on file."
file.puts "No/Incorrect birthdate on file."
end
if ((data[3] == "") || (data[3] =~ /[^0-9-]/))
puts "No/Incorrect student number on file."
file.puts "No/Incorrect student number on file."
end
if ((data[4] == "") || (data[4] =~ /[^0-9\/]/))
puts "No/Incorrect study end date on file."
file.puts "No/Incorrect study end date on file."
end
if ((data[5] == "") || (data[5] =~ /[^A-Za-z0-9 ]/))
puts "No/Incorrect study area on file."
file.puts "No/Incorrect study area on file."
end
file.close
else
begin
puts "working"
system 'pause'
ad = WIN32OLE.connect("LDAP://#{ou},#{domain}")
user = ad.create("user","cn=#{fullname}")
user.givenName = firstname
user.Sn = surname
user.SAMAccountname = "#{snumber}"
user.userPrincipalName = "#{snumber}#Troptrain.net.au"
user.displayName = fullname
user.profilePath = "c:\\profiles\\students\\logon"
user.setInfo
user_fqdn = "cn=#{fullname},#{ou},#{domain}"
user = WIN32OLE.connect("LDAP://#{user_fqdn}")
user.userPassword = Password01
user.accountDisabled = 0
user.accountExpirationDate = enddate
user.setInfo
studentgroup_fqdn = "#{group},#{ou},#{domain}"
grp = WIN32OLE.connect("LDAP://#{studentgroup_fqdn}")
grp.add("LDAP://#{user_fqdn}")
allgroup_fqdn = "cn=students,#{ou},#{domain}"
allgrp = WIN32OLE.connect("LDAP://#{allgroup_fqdn}")
allgrp.add("LDAP://#{user_fqdn}")
puts ""
puts "====================================================================="
puts "User account No #{count}: #{fullname} was created."
sleep 0.5
rescue
end
end
end
puts "====================================================================="
puts ""
puts "See Error log for details."
puts ""
puts "The program has finished creating users."
f1.close
Separate your concerns.
You need to parse a text file and retrieve users and groups from it in a structured way.
You need to import your groups and then import your users.
You then assign the users to the groups you created.
Each User and Group must be located in their own OUs to identify them.
Those OUs must be known.
Now work backward and factor out everything you need to continue with.
Find your host name, port and the credentials to bind to the LDAP server.
Find your Base DN. (DC=troptrain, DC=net, DC=au)
Find your User and Group prefixes. (the OU segments after the Base DN).
Import your data.
Verify. (This is also important!)
As LDAP can appear to be somewhat backward from the typical relational database, I recommend using the ActiveLDAP ruby gem with gem install active_ldap. It makes working with LDAP far easier.
#!/usr/bin/env ruby
require 'active_ldap'
class User < ActiveLdap::Base
ldap_mapping :dn_attribute => 'CN', :prefix => '<user-ou-prefix>',
has_many :groups, :class => 'Group', :wrap => 'memberOf', :primary_key => 'DN'
end
class Group < ActiveLdap::Base
ldap_mapping :dn_attribute => 'CN', :prefix => '<group-ou-prefix>',
has_many :members, :class => 'User', :wrap => 'member', :primary_key => 'DN'
end
ActiveLdap::Base.setup_connection(
:host => '<hostname>',
:base => '<base-dn>',
:bind_dn => '<bind-dn>',
:password => '<bind-password>',
:allow_anonymous => false,
:try_sasl => false,
:port => 389
)
From there, you should have the ability to create, read, update, and delete users using an ActiveRecord-like interface. the call to #setup_connection establishes what options are used to connect, and the has_many calls establish foreign-key-like relations between your classes.
# Find and display all users:
User.find(:all, '*') do |user|
puts user.cn
end
# Create a group with a CN of 'Anonymous'
group = Group.new('Anonymous')
group.description = "An anonymous group."
group.save
# Change the user with the CN 'Nobody' and change their displayName attribute.
user = User.find('Nobody')
user.displayName = "Nobody's Name"
user.save
# Delete a group with a CN of 'Foobar'.
group = Group.find('Foobar')
group.delete
ActiveLdap makes it extremely easy to manipulate LDAP from Ruby, I highly recommend it.
Hi Im getting an core error which is really standard I suppose in Ruby but dont know what to make of it. I have a program that I have written. Its purpose is to register guests at a camping. You have a menu with 5 different options. 1. Checkin. When i do this I get a undefined method generateParkingLot' for #<Camping:0x10030a768> (NoMethodError)
When I choose Checkout I get a undefined local variable or methoddeparture' for Menu:Class (NameError).
So please i someone has a clue to my problem it would be great. I will here paste all my code. The code is separated in different files and I have used require for the different files. Here though I will paste all the code in one trace. Thankful for all help.
-Sebastien
require 'guest'
require 'parking_lot'
class Camping
attr_accessor :current_guests, :parking_lots, :all_guests, :staticGuests
def initialize(current_guests, parking_lots, all_guests, staticGuests)
#current_guests = Array.new()
# initiera husvagnsplatserna
#parking_lots = Array.new(32)
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
#staticGuests = Array[
Guest.new("Logan Howlett", "Tokyo", "07484822",1, #parking_lots[0]),
Guest.new("Scott Summers", "Chicago", "8908332", 2, #parking_lots[1]),
Guest.new("Hank Moody", "Boston", "908490590", 3, #parking_lots[2]),
Guest.new("Jean Grey", "Detroit", "48058221", 4, #parking_lots[3]),
Guest.new("Charles Xavier","Washington DC", "019204822",5, #parking_lots[4])
]
end
#all_guests = []
#staticGuests.each do |guest|
#current_guests[guest.plot.nr] = guest
#all_guests.push(guest)
end
end
def to_s
# creates an empty string
list = " "
# loop from 1 to 32
(1..32).each do |n|
if (!#current_guests[n-1].nil?)
list += #current_guests[n-1].to_s
else
# else adds the text "Vacant"
list += n.to_s + ": Vacant!\n"
end
return list
end
def generateParkingLot
randomNr = 1+rand(32)
# exists a guest at the (0-based) position?
if (!#current_guests[randomNr-1].nil?)
# if so generate a new figure
generateEmpty(array)
else
# returns the generated number
return randomNr
end
end
end
end
class Guest
attr_accessor :firstname, :lastname, :address, :phone, :departure
attr_reader :arrived, :plot
def initialize (firstName, lastName, address, phone, plot)
#firstName = firstName
#lastName = lastName
#address = address
#phone = phone
#arrived = arrived
#plot = plot
end
def to_s
"Personal information:
(#{#firstName}, #{#lastName}, #{#address}, #{#phone}, #{#arrived}, #{#departure}, #{#plot})"
end
end
require 'ruby_camping'
require 'camping_guests'
class Main
if __FILE__ == $0
$camping = Camping.new(#current_guests, #all_guests, #parking_lots,#staticGuests)
puts "\n"
puts "Welcome to Ruby Camping!"
while (true)
Menu.menu
end
end
end
require 'date'
require 'camping_guests'
require 'guest'
class Menu
def initialize(guests = [])
#camping = Camping.new(guests)
end
def self.menu
puts "---------------------------"
puts " Menu"
puts " 1. Checkin"
puts " 2. Checkout"
puts " 3. List current guests"
puts " 4. List all guests"
puts " 5. Exit\n"
puts ""
puts " What do you want to do?"
puts "---------------------------"
print ": "
action = get_input
do_action(action)
end
# fetches menu choice and returns chosen alternativ
def self.get_input
input = gets.chomp.to_i
while (input > 5 || input < 1) do
puts "Ooups, please try again."
input = gets.chomp.to_i
end
return input
end
def self.do_action(action)
case action
when 1:
check_in
when 2:
check_out
when 3:
puts $camping.current_guests
when 4:
puts $camping.all_guests
when 5:
puts "You are now leaving the camping, welcome back!"
exit
end
end
def self.check_in
puts "Welcome to the checkin"
puts "Please state your first name: "
firstName = gets.chomp
puts "Please state your last name:"
lastName = gets.chomp
puts "Write your address: "
address = gets.chomp
puts "and your phone number: "
phone = gets.chomp
puts "finally, your arrival date!"
arrived = gets.chomp
newPLot = $camping.generateParkingLot
newGuest = Guest.new(firstName, lastName, address, phone,arrived,$camping.parking_lots[newPLot-1])
$camping.current_guests[newPLot-1] = newGuest
#all_guests.push(newGuest)
puts "The registration was a success!! You have received the " + newPLot.to_s + "."
end
def self.check_out
puts "Welcome to checkout!"
puts $camping.all_guests
puts "State plot of the person to checkout!"
plot = gets.chomp.to_i
puts "Ange utcheckningsdatum: "
departureDate = gets.chomp.to_i
guest = $camping.current_guests[plot-1]
#departure = departure
guest.departure = departureDate
guestStayedDays = departureDate - guest.arrived
guest.plot.increase(guestStayedDays)
puts guest
$camping.current_guests[plot-1] = nil
end
end
class Parking_Lot
attr_accessor :nr
attr_reader :electricity_meter
def initialize (nr)
#nr = nr
#electricity_meter = 4000-rand(2000)
end
def increase_meter(days)
generatedUse = (10+rand(70))*days
puts "Increases the meter with " + generatedUse.to_s + " kWh."
#electricity_meter += generatedUse
end
def to_s
"Plot #{#nr+1} Electricity meter: #{#electricity_meter} kWh"
end
end
It looks (although I haven't tried this out) like some of your your 'end's are wrong.
The one which is causing your first error (generateParkingLot undefined) is that generateParkingLot is actually defined inside to_s, so you need an extra 'end' at the end of your to_s method.
As for the second error (departure not recognised), the folowing line in self.check_out is at fault:
#departure = departure
because there is no 'departure' variable. (Perhaps you meant DepartureDate?). I suspect there may be a few other issues with this code, but I'm afraid I don't really have time to check now.
One I noticed was that when you have
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
I think you might want to end that, either with an 'end' or curly brackets, e.g.
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
end
Although that would make your other blocks not match.. In general, just try and make sure your blocks are all defined properly (e.g. everything has a matching end).