Manuals of Ruby packages listing their methods? - ruby

For example, I tried to find a manual for OAuth package here but I get Ooops page missing here. I tried rim utility as instructed in Manual pages for Ruby functions from command line but version not documented
= OAuth
(from gem oauth-0.5.3)
------------------------------------------------------------------------------
------------------------------------------------------------------------------
= Constants:
OUT_OF_BAND:
request tokens are passed between the consumer and the provider out of band
(i.e. callbacks cannot be used), per section 6.1.1
PARAMETERS:
required parameters, per sections 6.1.1, 6.3.1, and 7
RESERVED_CHARACTERS:
reserved character regexp, per section 5.1
VERSION:
[not documented]
Because of missing manuals, I have tried to find tools to list methods of packages like in IDE like Dropdown list for ruby methods of a package in RubyMine IDE? and Vim plugin to autocomplete method names of Ruby packages. I haven't yet found a solution there and, here, I want to keep the focus on the manuals and proper ways to find them in Ruby.
Is there some central place for Ruby package manuals like R's cran? And if not, how do authors of public Ruby packages usually document their plugins? Is the easiest way to see which methods each package has to read the source?

This is not the easiest way but you can unpack any gem file corresponding to a package where you may be able to find demonstrations about the usage of each package.
Example about OAuth
You can download the gem file and unpack it to read the source in the following way
wget https://rubygems.org/downloads/oauth-0.5.3.gem
gem unpack oauth-0.5.3.gem
where you find the README with a demonstration about the usage.
README.rdoc
== Demonstration of usage
We need to specify the oauth_callback url explicitly, otherwise it defaults to "oob" (Out of Band)
#callback_url = "http://127.0.0.1:3000/oauth/callback"
Create a new consumer instance by passing it a configuration hash:
#consumer = OAuth::Consumer.new("key","secret", :site => "https://agree2")
Start the process by requesting a token
#request_token = #consumer.get_request_token(:oauth_callback => #callback_url)
session[:token] = request_token.token
session[:token_secret] = request_token.secret
redirect_to #request_token.authorize_url(:oauth_callback => #callback_url)
When user returns create an access_token
hash = { oauth_token: session[:token], oauth_token_secret: session[:token_secret]}
request_token = OAuth::RequestToken.from_hash(#consumer, hash)
#access_token = #request_token.get_access_token
#photos = #access_token.get('/photos.xml')
Now that you have an access token, you can use Typhoeus to interact with the OAuth provider if you choose.
require 'oauth/request_proxy/typhoeus_request'
oauth_params = {:consumer => oauth_consumer, :token => access_token}
hydra = Typhoeus::Hydra.new
req = Typhoeus::Request.new(uri, options) # :method needs to be specified in options
oauth_helper = OAuth::Client::Helper.new(req, oauth_params.merge(:request_uri => uri))
req.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
hydra.queue(req)
hydra.run
#response = req.response
All functions in Ruby OAuth find . -iname "*.rb"
./lib/oauth/cli/authorize_command.rb
./lib/oauth/cli/base_command.rb
./lib/oauth/cli/help_command.rb
./lib/oauth/cli/query_command.rb
./lib/oauth/cli/sign_command.rb
./lib/oauth/cli/version_command.rb
./lib/oauth/cli.rb
./lib/oauth/client/action_controller_request.rb
./lib/oauth/client/em_http.rb
./lib/oauth/client/helper.rb
./lib/oauth/client/net_http.rb
./lib/oauth/client.rb
./lib/oauth/consumer.rb
./lib/oauth/core_ext.rb
./lib/oauth/errors/error.rb
./lib/oauth/errors/problem.rb
./lib/oauth/errors/unauthorized.rb
./lib/oauth/errors.rb
./lib/oauth/helper.rb
./lib/oauth/oauth.rb
./lib/oauth/oauth_test_helper.rb
./lib/oauth/request_proxy/action_controller_request.rb
./lib/oauth/request_proxy/base.rb
./lib/oauth/request_proxy/curb_request.rb
./lib/oauth/request_proxy/em_http_request.rb
./lib/oauth/request_proxy/jabber_request.rb
./lib/oauth/request_proxy/mock_request.rb
./lib/oauth/request_proxy/net_http.rb
./lib/oauth/request_proxy/rack_request.rb
./lib/oauth/request_proxy/rest_client_request.rb
./lib/oauth/request_proxy/typhoeus_request.rb
./lib/oauth/request_proxy.rb
./lib/oauth/server.rb
./lib/oauth/signature/base.rb
./lib/oauth/signature/hmac/sha1.rb
./lib/oauth/signature/plaintext.rb
./lib/oauth/signature/rsa/sha1.rb
./lib/oauth/signature.rb
./lib/oauth/token.rb
./lib/oauth/tokens/access_token.rb
./lib/oauth/tokens/consumer_token.rb
./lib/oauth/tokens/request_token.rb
./lib/oauth/tokens/server_token.rb
./lib/oauth/tokens/token.rb
./lib/oauth/version.rb
./lib/oauth.rb

Related

Custom package provider to work around namespace conflicts

I have a set of RHEL / CentOS systems where I am using the NetBSD pkgsrc system
to install various packages into a certain tree (e.g. /opt/local). I want to
manage this with Puppet. I started out simply using the pkgin provider, but
I quickly ran into namespace conflicts. For example, both the yum and pkgin
providers were adding Package[openssl], and they conflicted.
To fix this, I have been trying to use a static prefix on my pkgsrc packages,
then strip it off when it is actually passed to the pkgin command for handling.
First, I wrote a define to add the prefix and set the provider.
define mypkgin::package($ensure='latest') {
package { "mypkgin_${title}":
ensure => $ensure,
provider => 'mypkgin',
}
}
This will show up in the namespace as Mypkgin::Package[openssl], which does
not itself conflict with anything. And its goal is to add a resource named
Package[mypkgin_openssl], to not conflict with Package[openssl] from yum.
Then, I copied the pkgin provider code and modified it to provide a thing
named mypkgin. I have a small method in here to strip the prefix from the
name, and that is used in a few places so that the pkgin command receives
the pkgsrc package name instead of the prefixed version.
require "puppet/provider/package"
Puppet::Type.type(:package).provide :mypkgin, :parent => Puppet::Provider::Package do
desc "Package management using pkgin/pkgsrc, my local edition."
# Specify full path since it's not in Puppet's exec path
commands :pkgin => "/opt/local/bin/pkgin"
has_feature :installable, :uninstallable, :upgradeable, :versionable
# Strip prefix off of package name
def my_pkgname(package)
package.gsub(/^mypkgin_/, '')
end
def self.parse_pkgin_line(package)
# e.g.
# vim-7.2.446 = Vim editor (vi clone) without GUI
match, name, version, status = *package.match(/(\S+)-(\S+)(?: (=|>|<))?\s+.+$/)
if match
{
:name => name,
:status => status,
:ensure => version
}
end
end
def self.prefetch(packages)
super
# Without -f, no fresh pkg_summary files are downloaded
pkgin("-yf", :update)
end
def self.instances
pkgin(:list).split("\n").map do |package|
new(parse_pkgin_line(package))
end
end
def query
packages = parse_pkgsearch_line
if packages.empty?
if #resource[:ensure] == :absent
notice "declared as absent but unavailable #{#resource.file}:#{resource.line}"
return false
else
#resource.fail "No candidate to be installed"
end
end
packages.first.update( :ensure => :absent )
end
def parse_pkgsearch_line
packages = pkgin(:search, my_pkgname(resource[:name])).split("\n")
return [] if packages.length == 1
packages.slice!(-4, 4)
pkglist = packages.map{ |line| self.class.parse_pkgin_line(line) }
pkglist.select{ |package| my_pkgname(resource[:name]) == package[:name] }
end
def install
if String === #resource[:ensure]
pkgin("-y", :install, "#{my_pkgname(resource[:name])}-#{resource[:ensure]}")
else
pkgin("-y", :install, my_pkgname(resource[:name]))
end
end
def uninstall
pkgin("-y", :remove, my_pkgname(resource[:name]))
end
def latest
package = parse_pkgsearch_line.detect{ |package| package[:status] == '<' }
return properties[:ensure] if not package
return package[:ensure]
end
def update
pkgin("-y", :install, my_pkgname(resource[:name]))
end
end
Every time I run puppet agent --test, it tells me that it has added all of these
packages. So clearly I have some namespace bit wrong. It thinks on each run that
the package either needs to be installed, or upgraded, and it tries to do that.
I assume that in one or more places, I should add or remove calls to
my_pkgname(), but I can't seem to figure out where I've gone wrong.
Your provider determines which packages are already available on the system by means of prefetching. It looks like you have not replaced or overridden the bits that will result in that process ultimately relying on the instances() method.
Looking at that method, it appears that it will generate instances exactly as the pkgin provider would do, right down to the generated package names. That's a problem for you, because your scheme involves translating package names. It's not enough just to translate the names Puppet uses to the native ones -- you must also translate the native ones to the ones you want Puppet to see when you create instances on the provider side.
It looks like self.parse_pkgin_line() could be modified pretty easily to prepend the needed prefix to your package names. That seems like it would be the right thing for it to do, but I'm uncertain whether it would have any undesirable side effects. It is possible that additional changes will be required as well, such as in parse_pkgsearch_line(), but that's not immediately clear to me.

Downloading a track from Soundcloud using Ruby SDK

I am trying to download a track from Soundcloud using the ruby sdk (soundcloud 0.2.0 gem) with an app. I have registered the app on soundcloud and the client_secret is correct. I know this because I can see my profile info and tracks using the app.
Now when I try to download a track using the following code
#track = current_user.soundcloud_client.get(params[:track_uri])
data = current_user.soundcloud_client.get(#track.download_url)
File.open("something.mp3","wb"){|f|f.write(data)}
and when I open the file it has nothing in it. I've tried many approaches including the following one,
data = current_user.soundcloud_client.get(#track.download_url)
file = File.read(data)
And this one gives me an error
can't convert nil into String
on line 13 which is in
app/controllers/store_controller.rb:13:in `read'
that is the File.read function.
I have double checked that the track I am trying to download is public and downloadable.
I tried to test the download_url that is being used explicitly by copying it from console and sending a request using Postman and it worked. I am not sure why it is not working with the app when other things are working so well.
What I want to do is to successfully be able to either download or at least get the data which I could store somewhere.
Version details : -
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
Rails 3.2.18
soundcloud 0.2.0
There are few assumptions that you have to understand before doing this thing.
Not every track on SoundClound can be downloaded! Only tracks that are flagged as downloadable can be downloaded - your code has to consider that option!
Your track URL has to be "resolved" before you get to download_url and after you get download_url you have to use your client_id to get the final download URL.
Tracks can be big, and downlowding them requires time! You should never do tasks like this straight from your Rails app in your controller or model. If the tasks runs longer you always use some background worker or some other kind of background processing "thing" - Sidekiq for example.
Command-line client example
This is example of working client, that you can use to download tracks from SoundClound. Its using official Official SoundCloud API Wrapper for Ruby, assumes that you are using Ruby 1.9.x and its not dependent on Rails in any way.
# We use Bundler to manage our dependencies
require 'bundler/setup'
# We store SC_CLIENT_ID and SC_CLIENT_SECRET in .env
# and dotenv gem loads that for us
require 'dotenv'; Dotenv.load
require 'soundcloud'
require 'open-uri'
# Ruby 1.9.x has a problem with following redirects so we use this
# "monkey-patch" gem to fix that. Not needed in Ruby >= 2.x
require 'open_uri_redirections'
# First there is the authentication part.
client = SoundCloud.new(
client_id: ENV.fetch("SC_CLIENT_ID"),
client_secret: ENV.fetch("SC_CLIENT_SECRET")
)
# Track URL, publicly visible...
track_url = "http://soundcloud.com/forss/flickermood"
# We call SoundCloud API to resolve track url
track = client.get('/resolve', url: track_url)
# If track is not downloadable, abort the process
unless track["downloadable"]
puts "You can't download this track!"
exit 1
end
# We take track id, and we use that to name our local file
track_id = track.id
track_filename = "%s.aif" % track_id.to_s
download_url = "%s?client_id=%s" % [track.download_url, ENV.fetch("SC_CLIENT_ID")]
File.open(track_filename, "wb") do |saved_file|
open(download_url, allow_redirections: :all) do |read_file|
saved_file.write(read_file.read)
end
end
puts "Your track was saved to: #{track_filename}"
Also note that files are in AIFF (Audio Interchange File Format). To convert them to mp3 you do something like this with ffmpeg.
ffmpeg -i 293.aif final-293.mp3

Get chromes console log via Ruby WebDriver

This question has been previously answered in Java (Get chrome's console log)
However, I am using the Ruby bindings and was wondering if that provided similar functionality?
I have looked at the Ruby source code but cannot see any mention or reference to LoggingPreferences.
By the way, I am using RemoteWebDriver and passing in a desired capability object. Presumably I want to set the logging preferences in that object, but I am struggling to see where.
Apologies for late response.
I originally achieved it by adding the following to Webdriver;
module Selenium
module WebDriver
class Options
#
# Returns the available logs for this webDriver instance
#
def available_log_types
#bridge.getAvailableLogTypes
end
#
# Returns the requested log
#
# #param type [String] The required log type
#
# #return [Array] An array of log entries
#
def get_log(type)
#bridge.getLog(type)
end
end
end
end
When "required" this resulted in the following being supported;
driver.manage.get_log(:browser)
However, Version 2.38 of the selenium ruby gem exposes the logging API (although experimental).
http://selenium.googlecode.com/git/rb/CHANGES
https://code.google.com/p/selenium/wiki/Logging
Therefore, from 2.38 onwards the following should work WITHOUT the above extension;
driver.manage.logs.get :browser
You can use this code as well
require 'selenium-webdriver'
console_logs = #browser.driver.manage.logs.get(:browser)
puts = console_logs
ReportBuilder.build_report
Use command -f json -o my_report_file.json to generate reports.

How to use ohai gem

In the OpsCode Wiki there is there following documentation:
require 'ohai'
# ...
# Profit! ;-)
How can I print the JSON data provided by the 'ohai' command but using IRB? I tried to see the code in application.rb but I get empty data.
require 'ohai/application'
ohai = Ohai::System.new
ohai.json_pretty_print
=> "{\n\n}"
I am not trying to do this within Chef (or Shef), I just want to use the ohai gem itself, in my own app.
Poking about in the Ohai::Application class (what you get when you run ohai), #run_application instantiates Ohai::System and, unless it was configured by a file, it calls all_plugins to populate it with data.
Presumably, Ohai::System#all_plugins delegates the data collection to the lib/ohai/plugins directory.
$ irb -rohai
> system = Ohai::System.new
=> #<Ohai::System:0x00000100988950 #data={}, #seen_plugins={}, #providers={}, #plugin_path="", #hints={}>
> system.all_plugins
=> true
> puts system.to_json
{"languages":{"ruby":{"platform":"x86_64-darwin10.8.0","version":"1.9.2", ...
> system.to_json.size
=> 42395
I too searched for a simple and good library to do that...
I came across
Usagewatch
and after 5 minutes had my monitoring.rb done..
Install : gem install usagewatch
Install on mac : gem install usagewatch_ext
Refer to this article for more info

Ruby require a code snippet from github

Is there anyway to get Ruby's require statement to download a file from somewhere like github rather than just the local file system?
Update: Sorry I should have made the question clearer. I want to download a file that contains Ruby module and import it into my script rather than just downloading an image or some other arbitrary file within my script.
In other words something like this
require 'http:\\github.com\myrepo\snippet.rb'
puts 'hi'
By default, this is not possible. Also, it's not a good idea for security reasons.
You have a couple of alternatives. If the file you want to include is a Gem and Git repository, then you can use Bundler to download and package the dependency in your project. Then you'll be able to require the file directly in your source code.
This is the best and safest way to include an external dependency.
If you trust the source and you really know what you are doing, you can download the file using Net::HTTP (or any other HTTP library) and eval the body directly in your Ruby code.
You can package everything in a custom require_remote function.
You could download and eval it
require "open-uri"
alias :require_old :require
def require(path)
return false if $".include?(path)
unless path=~ /\Ahttp:\/\/
return require_old(path)
end
eval(open(path).read)
$"<< path
true
end
Be aware, this code has no error checking for network outages nonexisting files, ... . I also believe it is in general not a good idea to require libraries this way, there are security and reliability problems in this approach. But maybe you have a valid usecase for this.
you can include a remote gem from within Gemfiles then it will download when you run bundle install
After reading this question and answers I wanted something a little more bullet proof and verbose that used a paradigm of creating a local file from a repo and then requiring it, only if it didn't already exist locally already. The request for the repo version is explicit via the method repo_require. Used on files you control, this approach improves security IMO.
# try local load
def local_require(filename, relative_path)
relative_flname = File.join(relative_path, filename)
require_relative(relative_flname)
end
# try loading locally first, try repo version on load error
# caution: only use with files you control access to!
def repo_require(raw_repo_prefix, filename, relative_path = '')
local_require(filename, relative_path)
rescue LoadError => e
puts e.message
require 'open-uri'
tempdir = Dir.mktmpdir("repo_require-")
temp_flname = File.join(tempdir, File.basename(filename))
return false if $LOADED_FEATURES.include?(temp_flname)
remote_flname = File.join(raw_repo_prefix, filename)
puts "file not found locally, checking repo: #{remote_flname}"
begin
File.open(temp_flname, 'w') do |f|
f.write(URI.parse(remote_flname).read)
end
rescue OpenURI::HTTPError => e
raise "Error: Can't load #{filename} from repo: #{e.message} - #{remote_flname}"
end
require(temp_flname)
FileUtils.remove_entry(tempdir)
end
Then you could call repo_require like this:
repo_require('https://raw.githubusercontent.com/username/reponame/branch',
'filename', 'relative_path')
The relative_path would the the relative path you would use for the file if the repo was locally installed. For example, you may have something like require_relative '../lib/utils.rb'. In this example filename='lib/utils.rb' and relative_path='..'. This information allows the repo url to be constructed correctly as it does not use the relative path portion.

Resources