Ruby, Mac, Geektool question, file access rights? - ruby

I have a Ruby script that I built in TextMate and can successfully run in TextMate.
I can also successfully run this script straight from the terminal.
The script has this chunk of code in it:
# Get the XML file
puts 'Opening the file'
open("messages.xml", "r") do |f|
puts 'File is opened'
theXML = Hpricot::XML(f)
puts 'Trying to get the message_entity'
message_entity = GetMessage(theXML)
# Build the system command
puts 'Getting the author and the message'
theAuthor = message_entity.search(:author).text
theMessage = message_entity.search(:messagetext).text
# Get the correct image for this author
theAuthorImage = ''
case theAuthor
when 'James' : theAuthorImage = 'images/me32.png'
when 'Zuzu' : theAuthorImage = 'images/Zuzu32.png'
end
puts "/usr/local/bin/growlnotify '" + theAuthor + " says' -m '" + theMessage + "' -n 'Laurens Notes' --image '" + theAuthorImage + "'"
#system("/usr/local/bin/growlnotify '" + theAuthor + " says' -m '" + theMessage + "' -n 'Laurens Notes' --image '" + theAuthorImage + "'")
end
puts 'The End'
When the script is run by GeekTool, it never gets past puts 'File is opened'. It doesn't even hit puts 'The End'. It gives no error at all.
The script is under a folder under the /System folder on my Mac, but I have changed the file permissions to allow "everyone" to have "read & write" access.
EDIT
I just copied the files to a folder directly under my user home folder, and it still has the issue in GeekTool but not in TextMate or straight through the Terminal.
END EDIT
2nd Edit
I think GeekTool may have an issue with paths to files maybe.
For example, I changed the program to just read the XML file straight from the Internet for now and it does that just fine, but there are some images that the program is using for the icons in growlnotify. When run through TextMate, these icons display perfectly. When run using GeekTool...nope. No custom icon at all.
It's as if GeekTool just can't handle the file paths correctly.
When I do puts __FILE__.to_s it gives me the correct filepath to my .rb file though.
** end 2nd edit**
What should I do?

Geektool runs all the commands from / so relative path names will not work when trying to run growlnotify.
puts Dir.pwd #outputs "/"
You will need to pass the absolute paths of the images to growlnotify.
The current path can be retrieved with
File.dirname(__FILE__)
So you would use
theAuthorImage = File.dirname(__FILE__)
case theAuthor
when 'James' : theAuthorImage += '/images/me32.png'
when 'Zuzu' : theAuthorImage += '/images/Zuzu32.png'
end
cmd = "/usr/local/bin/growlnotify '#{theAuthor} says' -m '#{theMessage}' -n 'Laurens Notes' --image '#{theAuthorImage}'"
puts cmd
system cmd

Try wrapping it all in a block like below, which will log to /tmp/geektool.txt. Then you can see if there are any exceptions happening that you aren't aware of (like file permission).
begin
#file.open... etc
rescue Exception => e
file.open('/tmp/geektool.txt', 'w'){|f| f.puts "#{e}\n\n#{e.backtrace}"}
end
Also, don't forget there's the ruby-growl gem.

Have you checked if GeekTool spews any output to console.log or system.log?
Also, if it never gets past 'File is opened', it might be an issue with gems and requiring Hpricot?

Related

Ruby paths with backslash on Mac

Venturing into Ruby lands (learning Ruby). I like it, fun programming language.
Anyhow, I'm trying to build a simple program to delete suffixes from a folder, where user provides the path to the folder in the Mac terminal.
The scenario goes like this:
User runs my program
The program ask user to enter the folder path
User drags and drop the folder into the Mac terminal
Program receives path such as "/Users/zhang/Desktop/test\ folder"
Program goes and renames all files in that folder with suffix such as "image_mdpi.png" to "image.png"
I'm encountering a problem though.
Right now, I'm trying to list the contents of the directory using:
Dir.entries(#directoryPath)
However, it seems Dir.entries doesn't like backslashes '\' in the path. If I use Dir.entries() for a path with backslash, I get an exception saying folder or file doesn't exist.
So my next thought would be to use :
Pathname.new(rawPath)
To let Ruby create a proper path. Unfortunately, even Pathname.new() doesn't like backslash either. My terminal is spitting out
#directoryPath is not dir
This is my source code so far:
# ------------------------------------------------------------------------------
# Renamer.rb
# ------------------------------------------------------------------------------
#
# Program to strip out Android suffixes like _xhdpi, _hpdi, _mdpi and _ldpi
# but only for Mac at the moment.
#
# --------------------------------------------------
# Usage:
# --------------------------------------------------
# 1. User enters a the path to the drawable folder to clean
# 2. program outputs list of files and folder it detects to clean
# 3. program ask user to confirm cleaning
require "Pathname"
#directoryPath = ''
#isCorrectPath = false
# --------------------------------------------------
# Method definitions
# --------------------------------------------------
def ask_for_directory_path
puts "What is the path to the drawable folder you need cleaning?:"
rawPath = gets.chomp.strip
path = Pathname.new("#{rawPath}")
puts "Stored dir path = '#{path}'"
if path.directory?
puts "#directoryPath is dir"
else
puts "#directoryPath is not dir"
end
#directoryPath = path.to_path
end
def confirm_input_correct
print "\n\nIs this correct? [y/N]: "
#isCorrectPath = gets.chomp.strip
end
def reconfirm_input_correct
print "please enter 'y' or 'N': "
#isCorrectPath = gets.strip
end
def output_folder_path
puts "The folder '#{#directoryPath}' contains the following files and folders:"
# Dir.entries doesn't like \
# #directoryPath = #directoryPath.gsub("\\", "")
puts "cleaned path is '#{#directoryPath}'"
begin
puts Dir.entries(#directoryPath)
rescue
puts "\n\nLooks like the path is incorrect:"
puts #directoryPath
end
end
def clean_directory
puts "Cleaning directory now..."
end
puts "Hello, welcome to Renamer commander.\n\n"
ask_for_directory_path
output_folder_path
confirm_input_correct
while #isCorrectPath != 'y' && #isCorrectPath != 'N' do
reconfirm_input_correct
end
if #isCorrectPath == 'y'
clean_directory
else
ask_for_directory_path
end
I went through this learning resource for Ruby two three days ago:
http://rubylearning.com/satishtalim/tutorial.html
I'm also using these resource to figure out what I'm doing wrong:
http://ruby-doc.org/core-2.3.0/Dir.html
https://robm.me.uk/ruby/2014/01/18/pathname.html
Any ideas?
Edit
Well, the current work around(?) is to clean my raw string and delete any backslashes, using new method:
def cleanBackslash(originalString)
return originalString.gsub("\\", "")
end
Then
def ask_for_directory_path
puts "\nWhat is the path to the drawable folder you need cleaning?:"
rawPath = gets.chomp.strip
rawPath = cleanBackslash(rawPath)
...
end
Not the prettiest I guess.
A sample run of the program:
Zhang-computer:$ ruby Renamer.rb
Hello, welcome to Renamer commander.
What is the path to the drawable folder you need cleaning?:
/Users/zhang/Desktop/test\ folder
Stored dir path = '/Users/zhang/Desktop/test folder'
#directoryPath is dir
The folder '/Users/zhang/Desktop/test folder' contains the following files and folders:
cleaned path is '/Users/zhang/Desktop/test folder'
.
..
.DS_Store
file1.txt
file2.txt
file3.txt
Is this correct? [y/N]:
:]
I don't think the problem is with the backslash, but with the whitespace. You don't need to escape it:
Dir.pwd
# => "/home/lbrito/work/snippets/test folder"
Dir.entries(Dir.pwd)
# => ["..", "."]
Try calling Dir.entries without escaping the whitespace.
There is no backslash in the path. The backslash is an escape character displayed by the shell to prevent the space from being interpreted as a separator.
Just like Ruby displays strings containing double quotes by escaping those double quotes.
Okay, first of all, using gets.chomp.strip is probably not a good idea :P
The better and closer solution to what your normally see in a real bash program is to use the Readline library:
i.e.
require "Readline"
...
def ask_for_directory_path
rawPath = String.new
rawPath = Readline.readline("\nWhat is the path to the drawable folder you need cleaning?\n> ", true)
rawPath = rawPath.chomp.strip
rawPath = cleanBackslash(rawPath)
#directoryPath = Pathname.new(rawPath)
end
Using Readline lets you tab complete the folder path. I also needed to clean my backslash from the readline using my own defined:
def cleanBackslash(originalString)
return originalString.gsub("\\", "")
end
After that, the Dir.entries(#directorPath) is able to list all the files and folders in the path, whether the user typed it in manually or drag and drop the folder into the Mac terminal:
Zhang-iMac:Renamer zhang$ ruby Renamer.rb
Hello, welcome to Renamer commander.
What is the path to the drawable folder you need cleaning?
> /Users/zhang/Ruby\ Learning/Renamer/test_folder
The folder '/Users/zhang/Ruby Learning/Renamer/test_folder' contains the following files and folders:
.
..
.DS_Store
drawable
drawable-hdpi
drawable-mdpi
drawable-xhdpi
drawable-xxhdpi
drawable-xxxhdpi
Is this correct? [y/N]: y
Cleaning directory now...
The program is not finish but I think that fixes my problem of the backslash getting in the way.
I don't know how real bash programs are made, but consider this my poor man's bash program lol.
Final program
Check it out:
I feel like a boss now! :D

Appending a parameter's value in parameters.yml when deploying symfony application

First of all I've never used ruby and capifony so this question might be very easy for some of you but not for me. I tried to find examples related to my question but couldn't find any or I'm too new to ruby to miss!
When deploying my Symfony app, the value of a particular key in my parameters file should be dynamically appended so, rather than using exact generic value coming from distribution file below:
parameters_prod.yml.dist
parameters:
my_prefix: my_value_prefix_
Straight after deployment, parameters.yml should read like below:
parameters.yml
parameters:
my_prefix: my_value_prefix_8235647895
8235647895 part above is going to be timestamp.
How can I do this?
My current deploy.rb
namespace :mytest do
desc "Upload the parameters.yml"
task :upload_parameters do
origin_file = parameters_dir + "/" + parameters_file if parameters_dir && parameters_file
origin_file_append = parameters_dir + "/" + parameters_file_append if parameters_dir && parameters_file_append
if origin_file && File.exists?(origin_file)
relative_path = "app/config/parameters.yml"
files = [origin_file]
files << origin_file_append if origin_file_append && File.exists?(origin_file_append)
tmp_origin_file = origin_file + '.tmp'
File.open(tmp_origin_file, 'w') do |fo|
files.each do |file|
File.foreach(file) do |li|
fo.puts li
end
end
end
if shared_files && shared_files.include?(relative_path)
destination_file = shared_path + "/" + relative_path
else
destination_file = latest_release + "/" + relative_path
end
try_sudo "mkdir -p #{File.dirname(destination_file)}"
top.upload(tmp_origin_file, destination_file)
File.delete(tmp_origin_file)
end
end
end

RuntimeError when running script?

So I have found this RUBY script, which looks for all PNG images in sub folders and folders and converts PNG images using TinyPNG API but for some reason I get runtime error
C:/Users/Vygantas/Desktop/tinypng.rb:14:in `':
Usage: ./tinypng.rb C:/Users/Vygantas/Desktop/product C:/Users/Vygantas/Desktop/product(RuntimeError)
#!/usr/bin/ruby -w
#
# tinypng.rb — Placed into the public domain by Daniel Reese.
#
require 'rubygems'
require 'json'
# Set API key.
apikey = "xxxxxxxxxxxxxxxx"
# Verify arguments.
ARGV.length == 2 or fail("Usage: ./tinypng.rb C:\Users\Vygantas\Desktop\product C:\Users\Vygantas\Desktop\product*emphasized text*")
src = ARGV[0]
dst = ARGV[1]
File.exist?(src) or fail("Input folder does not exist: " + src)
File.exist?(dst) or fail("Output folder does not exist: " + dst)
# Optimize each image in the source folder.
Dir.chdir(src)
Dir.glob('*.png') do |png_file|
puts "\nOptimizing #{png_file}"
# Optimize and deflate both images.
cmd = "curl -u api:#{apikey} --data-binary ##{png_file} 'https://api.tinypng.com/shrink'"
puts cmd
r = JSON.parse `#{cmd}`
if r['error']
puts "TinyPNG Error: #{r['message']} (#{r['error']})"
exit(1)
end
url = r['output']['url']
cmd = "curl '#{url}' -o #{dst}/#{png_file}"
puts cmd
`#{cmd}`
end
Dir.chdir("..")
puts 'Done'
As you might see in the code, line 14 (as printed on script execution):
ARGV.length == 2 or fail("Usage: ./tinypng.rb
C:\...\product C:\...\product*emphasized text*")
That said, a script requires two parameters to run. Let me guess: you did not pass two parameters. Those are btw source and destination folders.

Trying to change names of files using Dir and File.rename on Mac OS?

I'm following a tutorial and am trying to change the names of three files in a folder that's located under 'drive/users/myname/test'. I'm getting the error:
'chdir': No such file or directory - test'.
The starting path is already 'drive/users/myname', which is why I thought that I only had to enter 'test' for Dir.chdir.
How do I correctly input the paths on Mac OS?
Dir.chdir('test')
pic_names = Dir['test.{JPG,jpg}']
puts "What do you want to call this batch"
batch_name = gets.chomp
puts
print "Downloading #{pic_names.length} files: "
pic_number = 1
pic_names.each do |p|
print '.'
new_name = "batch_name#{pic_number}.jpg"
File.rename(name, new_name)
pic_number += 1
end
I think you have to provide the absolute path. So, your first line should be:
Dir.chdir("/drive/users/myname/test")
According to the documentation:
Dir.chdir("/var/spool/mail")
puts Dir.pwd
should output/var/spool/mail.
You can look at the documentation for more examples.
In:
File.rename(name, new_name)
name is never defined prior to its attempted use.
Perhaps p is supposed to be name, or name should be p?
With that assumption I'd write the loop something like:
pic_names.each_with_index do |name, pic_number|
print '.'
new_name = "#{ batch_name }#{ 1 + pic_number }.jpg"
File.rename(name, File.join(File.dirname(name), new_name))
end
File.join(File.dirname(name), new_name) is important. You have to refer to the same path in both the original and new filenames, otherwise the file will be moved to a new location, which would be wherever the current-working-directory points to. That's currently masked by your use of chdir at the start, but, without that, you'd wonder where your files went.

Display output of ruby script requiring Mechanize on MacOS Desktop using GeekTools?

I have written a working ruby script using mechanize for fetching my
Stackoverflow reputation and badges
Twitter tweets and followers
and printing the output to screen.
I run this command on the terminal first :
/Users/cyclotrojan/.rvm/rubies/ruby-1.9.2-p290/bin/ruby /Users/cyclotrojan/Desktop/Snippets/get_so_reputation_and_tw_followers.rb
The output is correctly displayed like this on the terminal:
StackOverflow :
Reputation is : 406
Total Badges : 10
Twitter :
Tweets : 1,494
Followers : 137
Now I wish to display the output of my script on my desktop using GeekTools and set refresh time to 30 minutes, so it keeps running the script over and over thus updating my stats. However when I paste the same command on a geektool shell, no output comes.
Here is the script :
File get_so_reputation_and_tw_followers.rb
require 'mechanize'
def get_stackoverflow_data
url_so = 'https://stackoverflow.com/users/898346/cyclotrojan'
begin
so_page = Mechanize.new.get(url_so)
so_reputation = so_page.link_with(:href => "/users/898346/cyclotrojan?tab=reputation").to_s
so_badges = so_page.search(".badgecount").first
print "StackOverflow :" + "\n"
print " Reputation is : " + so_reputation + "\n"
print " Total Badges : " + so_badges + "\n"
rescue
print "StackOverflow :" + "\n"
print "\tReputation is : " + "NA" + "\n"
print "\tTotal Badges : " + "NA" + "\n"
end
end
def get_twitter_data
url_tw = 'https://twitter.com/cyclotrojan'
begin
tw_page = Mechanize.new.get(url_tw)
tw_tweets = tw_page.link_with( :href => "/" + url_tw.split("/").last).to_s.split(" ").first
tw_followers = tw_page.link_with( :href => "/#!/" + url_tw.split("/").last + "/followers").to_s.split(" ").first
print "Twitter :" + "\n"
print "\tTweets : " + tw_tweets + "\n"
print "\tFollowers : " + tw_followers + "\n"
rescue
print "Twitter :" + "\n"
print "\tTweets : " + "NA" + "\n"
print "\tFollowers : " + "NA" + "\n"
end
end # end function
get_stackoverflow_data()
get_twitter_data()
However, the output simply doesnt show up on my desktop. I know that the problem is not with detecting ruby, since I tested it out using another file test.rb
File test.rb
puts "hello"
This command will work on GeekTool shell and display hello correctly :
/Users/cyclotrojan/.rvm/rubies/ruby-1.9.2-p290/bin/ruby /Users/cyclotrojan/Desktop/Snippets/test.rb;
Output on geektool shell:
hello
I have done some debugging and found that if I remove the line
require 'mechanize'
then the script runs correctly and due to exception the following output is displayed :
StackOverflow :
Reputation is : NA
Total Badges : NA
Twitter :
Tweets : NA
Followers : NA
So the issue is with including mechanize in the script. Please help me in resolving this. Thnx !
These questions didnt help :
How to run Ruby scripts in Geektool? ,
Ruby, Mac, Geektool question, file access rights?
You would be able to tell if you didn't try to rescue the error. It looks like our old friend ssl verify error so try this:
#agent = Mechanize.new
#agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
tw_page = #agent.get url_tw
I should add that you might want to make sure you understand the consequences of OpenSSL::SSL::VERIFY_NONE
Also here is a tip:
tweets = tw_page.at('a[#data-element-term="tweet_stats"] strong').text rescue 'N/A'
followers = tw_page.at('a[#data-element-term="follower_stats"] strong').text rescue 'N/A'
puts "Twitter :" + "\n"
puts "\tTweets : #{tweets}"
puts "\tFollowers : #{followers}"

Resources