Mix debugger commands and ruby code evaluation - ruby-on-rails

I'm currently upgrading an old project from and old version of ruby(1.8.7)/rails(3.0) to 1.9.3/3.1 (as a stepping stone to newer versions).
I'm using gems debugger for 1.9.3 and ruby-debug for 1.8.7
When I run , I can run commands like info variables to get the list and values of all currently-scoped variables:
...
#current_phone = nil
#fields = {}
#global = {:source_type=>"pdf"}
#images = []
#index = {}
#lines = []
...
Also I can run arbitrary ruby code - a useful one I've been using is
File.open("/tmp/new_version", "w"){|f|f.write(#fields)}
which is useful for me to quickly compare between the old version and the new version using a file diff program.
Can I link these together so I can write to a file all the output of info variables? It would be sufficient if I could do
tempvar = info variables
or something along those lines, of course, but that gives
*** NameError Exception: undefined local variable or method `variables' for <ClassWhatever>

instance_variables.map { |v| [v, instance_variable_get(v)] }
Not exactly hash map, but you'll be good with it.

Related

Ruby Rails Screen Scrape different results in Rails Console

I'm confused about a difference I'm seeing in Nokogiri commands run from Rails Console and what I get from the same commands run in a Rails Helper.
In Rails Console, I am able to capture the data I want with these commands:
endpoint = "https://basketball-reference.com/leagues/BAA_1947_totals.html"
browser = Watir::Browser.new(:chrome)
browser.goto(endpoint)
#doc_season = Nokogiri::HTML.parse(URI.open("https://basketball-reference.com/leagues/BAA_1947_totals.html"))
player_season_table = #doc_season.css("tbody")
rows = player_season_table.css("tr")
rows.search('.thead').each(&:remove) #THIS WORKED
rows[0].at_css("td").try(:text) # Gets single player name
rows[0].at_css("a").attributes["href"].try(:value) # Gets that player page URL
However, my rails helper that is meant to take those commands and fold them into methods:
module ScraperHelper
def target_scrape(url)
browser = Watir::Browser.new(:chrome)
browser.goto(url)
doc = Nokogiri::HTML.parse(browser.html)
end
def league_year_prefix(year, league = 'NBA')
# aba_seasons = 1968..1976
baa_seasons = 1947..1949
baa_seasons.include?(year) ? league_year = "BAA_#{year}" : league_year = "#{league}_#{year}"
end
def players_total_of_season(year, league = 'NBA')
# always the latter year of the season, first year is 1947 no quotes
# ABA is 1968 to 1976
league_year = league_year_prefix(year, league)
#doc_season = target_scrape("http://basketball-reference.com/leagues/#{league_year}_totals.html")
end
def gather_players_from_season
player_season_table = #doc_season.css("tbody")
rows = player_season_table.css("tr")
rows.search('.thead').each(&:remove)
puts rows[0].at_css("td").try(:text)
puts rows[0].at_css("a").attributes["href"].try(:value)
end
end
On that module, I try to emulate the rails console commands and break them into modules. And to test it out (since I don't have any other functionality or views built yet), I run Rails console, include this helper and run the methods.
But I get wildly different results.
in the gather_players_from_season method, I can see that
player_season_table = #doc_season.css("tbody")
Is no longer grabbing the same data it grabbed when run as a command line by line. It also doesn't like the attributes method here:
puts rows[0].at_css("a").attributes["href"].try(:value)
So my first thought is a difference in gems maybe? Watir is launching the headless browser. Nokogiri isn't causing errors as near as I can tell.
Your first thought of comparing the Gem versions is a great idea, but I am noticing a difference between the two code solutions:
In the Rails Console
the code parses the HTML with URI.open: Nokogiri::HTML.parse(URI.open("some html"))
In the ScraperHelper code
the code does not call URI.open, Nokogiri::HTML.parse("some html")
Perhaps that difference will return different values and make the rest of the ScraperHelper return unexpected results.

Call Ruby from a VBScript

Hey I have been working with ruby and vbscript lately. There is a scenario where I need to call a ruby script from another vbscript and I am stuck there. I tried this code,
Set newobj = CreateObject("WScript.shell")
obj = newobj.Run("ruby E:\rubyfile.rb > D:\newdoc.txt",1,true)
but the ruby script is not giving the result. Am I doing it right or is there some other way to do it?
If the ruby script is executed separately then the results are generated, so the problem is not with the ruby script.
You need a shell (%comspec% /c) to get a shell's feature like > redirection. So change
obj = newobj.Run("ruby E:\rubyfile.rb > D:\newdoc.txt",1,true)
to
nRet = newobj.Run("%comspec% /c ruby E:\rubyfile.rb > D:\newdoc.txt",1,true)
(Study the docs for .Run to see the reason for nRet instead of obj and spend a thought on the lousy-ness of the name "newobj")

Configuration of ContentfulModel gem is lost after initialization

Completely new Rails 4.2.3 application. The only changes to the Gemfile have been removal of Spring, addition of dotenv, and the latest contentful_rails and contentful_model gems as published on rubygems.org.
For unknown reasons, the configuration details defined in the initializer are gone by the time the app comes up. It's the same object (same value for ContentfulModel.configuration.object_id) but the values that were previously correct are now nil.
I added an initializer as shown in the README.
$ cat config/initializers/contentful_model.rb
ContentfulModel.configure do |config|
byebug
config.access_token = ENV['CONTENTFUL_ACCESS_TOKEN']
config.preview_access_token = ENV['CONTENTFUL_PREVIEW_ACCESS_TOKEN']
config.space = ENV['CONTENTFUL_SPACE']
# config.options = {
#extra options to send to the Contentful::Client
# }
end
And I defined one model, Category.
$ cat app/models/category.rb
class Category < ContentfulModel::Base
self.content_type_id = "[category content type string]"
end
So here's what happens when I fire up the Rails console:
$ rails c
[1, 9] in /home/trevor/code/chef/www-contentful-rails/config/initializers/contentful_model.rb
1: ContentfulModel.configure do |config|
2: config.access_token = ENV['CONTENTFUL_ACCESS_TOKEN']
3: config.preview_access_token = ENV['CONTENTFUL_PREVIEW_ACCESS_TOKEN']
4: config.space = ENV['CONTENTFUL_SPACE']
5: # config.options = {
6: #extra options to send to the Contentful::Client
7: # }
8: byebug
=> 9: end
(byebug) ContentfulModel.configuration
#<ContentfulModel::Configuration:0x00000005bc7be0 #access_token="[my actual token string]", #entry_mapping={}, #preview_access_token="[my actual preview token string]", #space="[my actual space]">
(byebug) continue
/home/trevor/.rvm/gems/ruby-2.2.2#www-contentful-rails/gems/actionpack-4.2.3/lib/action_dispatch/http/mime_type.rb:163: warning: already initialized constant Mime::JSON
/home/trevor/.rvm/gems/ruby-2.2.2#www-contentful-rails/gems/actionpack-4.2.3/lib/action_dispatch/http/mime_type.rb:163: warning: previous definition of JSON was here
Loading development environment (Rails 4.2.3)
2.2.2 :001 > ContentfulModel.configuration
=> #<ContentfulModel::Configuration:0x00000005bc7be0 #access_token=nil, #entry_mapping={"[category content type string]"=>Category}, #preview_access_token=nil, #space=nil>
2.2.2 :002 >
I've spent a bunch of time sifting the gem source and stepping through the debugger without results. I've posted an issue for the project on GitHub because I haven't been able to identify the source of the problem and I have to assume its within the gem. Any assistance with how to troubleshoot this further would be very welcome!
The solution was to use the undocumented approach required due to changes a few months ago.
The contentful_rails gem requires contentful_model (and vice versa), and the only configuration documentation for contentful_model is in that project's README, describing the approach in my question. Configuration made in this way was then completely wiped when contentful_rails was initialized, which expected the configuration to be done in its own initializer.
So I have deleted config/initializers/contentful_model.rb and now my config/intializers/contents_rails.rb file looks like:
ContentfulRails.configure do |config|
config.authenticate_webhooks = true # false here would allow the webhooks to process without basic auth
config.webhooks_username = ENV['CONTENTFUL_WEBHOOK_USERNAME']
config.webhooks_password = ENV['CONTENTFUL_WEBHOOK_PASSWORD']
config.access_token = ENV['CONTENTFUL_ACCESS_TOKEN']
config.preview_access_token = ENV['CONTENTFUL_PREVIEW_ACCESS_TOKEN']
config.space = ENV['CONTENTFUL_SPACE']
config.contentful_options = {
#extra options to send to the Contentful::Client
}
end
Of note is that config.options is no longer a thing; it's config.contentful_options.

Reading docs in irb

One thing I miss about ipython is it has a ? operator which diggs up the docs for a particular function.
I know ruby has a similar command line tool but it is extremely inconvenient to call it while I am in irb.
Does ruby/irb have anything similar?
Pry is a Ruby version of IPython, it supports the ? command to look up documentation on methods, but uses a slightly different syntax:
pry(main)> ? File.dirname
From: file.c in Ruby Core (C Method):
Number of lines: 6
visibility: public
signature: dirname()
Returns all components of the filename given in file_name
except the last one. The filename must be formed using forward
slashes (/'') regardless of the separator used on the
local file system.
File.dirname("/home/gumby/work/ruby.rb") #=> "/home/gumby/work"
You can also look up sourcecode with the $ command:
pry(main)> $ File.link
From: file.c in Ruby Core (C Method):
Number of lines: 14
static VALUE
rb_file_s_link(VALUE klass, VALUE from, VALUE to)
{
rb_secure(2);
FilePathValue(from);
FilePathValue(to);
from = rb_str_encode_ospath(from);
to = rb_str_encode_ospath(to);
if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
sys_fail2(from, to);
}
return INT2FIX(0);
}
See http://pry.github.com for more information :)
You can start with
irb(main):001:0> `ri Object`
Although the output of this is less than readable. You'd need to filter out some metacharacters.
In fact, someone already made a gem for it
gem install ori
Then in irb
irb(main):001:0> require 'ori'
=> true
irb(main):002:0> Object.ri
Looking up topics [Object] o
= Object < BasicObject
------------------------------------------------------------------------------
= Includes:
Java (from gem activesupport-3.0.9)
(from gem activesupport-3.0.9) [...]
No, it doesn't. Python has docstrings:
def my_method(arg1,arg2):
""" What's inside this string will be made available as the __doc__ attribute """
# some code
So, when the ? is called from ipython, it probably calls the __doc__ attribute on the object. Ruby doesn't have this.

Use cache money only for a single model?

I want to use cache-money but I don't want to start automatically caching everything (I'm working with a large production app, terabytes of data etc). How do I use it for only the models that I specify? Right now I've got:
# initializers/cache_money.rb
require 'cache_money'
config = (cfg = YAML.load(IO.read(File.join(RAILS_ROOT, "config", "memcached.yml"))))[RAILS_ENV] || cfg["defaults"]
$memcache = MemCache.new(config)
$memcache.servers = config['servers']
$local = Cash::Local.new($memcache)
$lock = Cash::Lock.new($memcache)
$cache = Cash::Transactional.new($local, $lock)
and then in the model I want to cache with cache-money:
# my_model.rb
class MyModel < ActiveRecord::Base
is_cached :repository => $cache
# ...
end
But this doesn't work; the call to is_cached gives the following error: NoMethodError: undefined method `create' for Config:Module
Any ideas? Failing that, is there anywhere I can go for help with cache-money? I couldn't find a mailing list or anything.
I think this is a bug in the cache_money code.
There are forks available on github that fix this bug, eg:
http://github.com/quake/cache-money
The fix can be seen with this commit:
http://github.com/quake/cache-money/commit/54c3d12789f31f2904d1fe85c102d7dbe5829590
I've just experienced the same problem trying to deploy an application. Running on my development machine it was fine, but it failed with this error on the production machine.
Apart from the architecture (OSX vs CentOS) the only difference i could see was that the ruby versions were different (1.8.6 p114 vs 1.8.6 p0). After upgrading the server to the latest 1.8 version (1.8.7 p160) this error went away.

Resources