How to add a page to RDoc? - ruby

Noob here trying to figure out the simple task of adding a page to my RDoc documentation. If I do rake doc:app and view a page, then there is a sidebar that says "Pages" with README_FOR_APP listed. All I want to do is create a page named "Cheatsheet" that will appear under "Pages." How do I create a documentation page and tell RDoc to include the new page?

IMO it's a bit convoluted. Here's the references I used:
http://rake.rubyforge.org/classes/Rake/RDocTask.html
How to Rename or Move Rails's README_FOR_APP
Nutshell version:
Take the "app" task from your rails library directory, for example I tested using:
~/.rvm/gems/ruby-1.9.2-p0#foo/gems/railties-3.0.9/lib/rails/tasks/documentation.rake
The part you need looks (approximately) like this:
namespace :doc do
def gem_path(gem_name)
path = $LOAD_PATH.grep(/#{gem_name}[\w.-]*\/lib$/).first
yield File.dirname(path) if path
end
RDocTaskWithoutDescriptions.new("app2") { |rdoc|
rdoc.rdoc_dir = 'doc/app'
rdoc.template = ENV['template'] if ENV['template']
rdoc.title = ENV['title'] || "Rails Application Documentation"
rdoc.options << '--line-numbers' << '--inline-source'
rdoc.options << '--charset' << 'utf-8'
rdoc.rdoc_files.include('doc/*_FOR_APP') # Modified this line
rdoc.rdoc_files.include('app/**/*.rb')
rdoc.rdoc_files.include('lib/**/*.rb')
}
end
Put this in your app's lib/tasks directory in a .rake file, e.g., doc2.rake.
Update the task name if you want to keep the original, e.g., "app2".
Update the "doc/README_FOR_APP" string to a wider pattern, or add new file(s) to process.
Create doc/Cheatsheet_FOR_APP and the new rake doc:app2 task will pick it up.

Related

How to remove a group from Xcode project programmatically?

I need to manage an Xcode project from a batch process, partially remove certain groups.
As I understand, the only tool is xcodeproj. Or writing own pbxproj file parser.
So I have installed xcodeproj.
First of all, there is no reasonable documentation, that one that is new to it could understand it easily. I assume I need to write some rb file. And execute it as ruby xcodeproj_batch.rb
Here is what I have done. But this does not work. This script finds the needed group but it does not delete it.
xcodeproj_batch.rb:
require 'rubygems'
require 'xcodeproj'
project_path = '../TestProject/TestProject.xcodeproj'
project = Xcodeproj::Project.open(project_path)
groupToDelete = Xcodeproj::Project::PBXGroup
project.groups.each do |group|
if group.name == 'Test'
groupToDelete = group
puts 'cleared: '+group.name
groupToDelete.clear
end
end
project.groups.delete(groupToDelete)
project.save(project_path)
I assume this script has errors. I don't have xcodeproj and ruby background. I'm trying here to remove the group in two different ways. What am I missing?
I have found the problem, I needed to use remove_from_project and not clear:
require 'rubygems'
require 'xcodeproj'
project_path = '../TestProject/TestProject.xcodeproj'
project = Xcodeproj::Project.open(project_path)
groupToDelete = nil
project.groups.each do |group|
if group.name == 'Test'
groupToDelete = group
puts 'cleared: '+group.name
# add break;
end
end
groupToDelete.remove_from_project
project.save(project_path)

How do you open a zip file using watir-webdriver?

My test suite has a cucumber front end with a ruby backend, running the latest version of watir-webdriver and its dependencies atop the latest version of OSX. My cucumber environment is setup to execute in Firefox.
The export feature of our app creates a zip file but to test the import feature, I need the contents of the zip file.
My actual test needs to unpack that zip file and select the individual files in it for use in testing the import feature of our web application.
Can anyone point me to a reference that can help me figure out how to write that?
Based off my experience, you download this file the same way that a normal user might. So first off, you just click the download button or whatever and then can access the file wherever it is and check out its contents.
Assuming the downloads just go to your Downloads folder by default, there is some simple code you can use to select the most recently downloaded item:
fn = Dir.glob("~/Downloads/*.zip").max { |a,b| File.ctime(a) <=> File.ctime(b)}
Then just use the unzip shell command to unzip the file. No reason to add another gem into the mix when you can just use generic shell commands.
`unzip #{fn}`
Then, you'd use Dir.glob again to get the filenames of everything inside the unzipped files folder. Assuming the file was named "thing.zip", you do this:
files = Dir.glob("~/Downloads/thing/*")
If you want to files to be downloaded directly to your project folder, you can try this. This also prevents the popup from asking you if you really want to save the file which is handy. I think this still works but haven't used it in some time. The above stuff works for sure though.
profile = Selenium::WebDriver::Firefox::Profile.new
download_dir = Dir.pwd + "/test_downloads"
profile['browser.download.dir'] = download_dir
profile['browser.helperApps.neverAsk.saveToDisk'] = "application/zip"
b = Watir::Browser.new. :firefox, :profile => profile
I ended up adding the rubyzip gem at https://github.com/rubyzip/rubyzip
the solution is on that link but i modified mine a little bit. I added the following to my common.rb file. see below:
require 'Zip'
def unpack_zip
test_home='/Users/yournamegoeshere/SRC/watir_testing/project files'
sleep(5) #<--manually making time to hit the save download dialog
zip_file_paths = []
Find.find(test_home) do |path|
zip_file_paths << path if path =~ /.*\.zip$/
end
file_name=zip_file_paths[0]
Zip::File.open(file_name) do |zip_file|
# Handle entries one by one
zip_file.each do |entry|
# Extract to file/directory/symlink
puts "Extracting #{entry.name}"
entry.extract(test_home + "/" + entry.name)
# Read into memory
content = entry.get_input_stream.read
end
# Find specific entry
entry = zip_file.glob('*.csv').first
puts entry.get_input_stream.read
end
end
This solution works great!

How do I run multiple rake tasks at once?

I'm using a Rake task that runs multiple scraping scripts and exports category data for 35 different cities of a site to 35 different CSV files.
The problem I'm having is that when I run the master Rake task from the root directory of the folder, it creates a new file in the parent directory "resultsForCity.csv" instead of seeing the current CSV file within that given subfolder and adding the data to it. To get around it, I thought I should make my master Rake task (within the parent directory) run slave Rake tasks that then run the scraping scripts, but that didn't work either.
However, if I cd into one of the city folders and run the scraper or Rake task from there, it adds the data to the corresponding CSV file located within that subfolder. Am I not clearly defining dependencies or something else?
Things I've tried:
I've tried requiring each individual rakefile within my master rake task.
Tried iterating over all files and loading the rake tasks and received a stack too deep error.
Tried searching on Stackoverflow for 7 days now.
Here's my Rake task code:
require "rake"
task default: %w[getData]
task :getData do
Rake::FileList.new("**/*.rb*").each do |file|
ruby file
end
end
And here's my scraper code:
require "nokogiri"
require "open-uri"
require "csv"
url = "http:// example.com/atlanta"
doc = Nokogiri::HTML(open(url))
CSV.open("resultsForAtlanta.csv", "wb") do |csv|
doc.css(".tile-title").each do |item|
csv << [item.text.tr("[()]+0-9", ""), item.text.tr("^0-9$", "")]
end
doc.css(".tile-subcategory").each do |tile|
csv << [tile.text.tr("[()]+0-9", ""), tile.text.tr("^0-9$", "")]
end
end
Any help would be more than greatly appreciated.
What if you let your scraper script take an output filename and use the directory structure to help you build the output filenames.
Assuming you have a directory tree something like
Atlanta/scraper.rb
LosAngeles/scraper.rb
...
where scraper.rb is your scraping script, you should be able to write the task somewhat like this:
task :getData do
Rake::FileList.new("**/scraper.rb").each do |scraper_script|
dir = File.dirname(file)
city = File.basename(dir)
csv_file = File.join(dir, "resultsFor#{city}.csv")
ruby [scraper_script, csv_file].join(" ")
end
end
and then your Ruby script could just grab the filename off the command line like this:
CSV.open(ARGV[1], "wb") do |csv|
...
end

Anyway to reload the modified gem files in the REPL

While trying to build a Ruby gem (using Bundler), I tend to test the code using the REPL provided by Bundler - accessible via bundle console.
Is there any way to reload the entire project in it? I end up loading individual (changed) files again to test the new change.
The following hack works for a relatively simple gem of mine and Ruby 2.2.2. I'll be curious to see if it works for you. It makes the following assumptions:
You have the conventional folder structure: a file called lib/my_gem_name.rb and a folder lib/my_gem_name/ with any files / folder structure underneath.
All the classes you want to reload are nested within your top module MyGemName.
It will probably not work if in one of the files under lib/my_gem_name/ you monkey-patch classes outside of your MyGemName namespace.
If you're good with the assumptions above, put the following code inside the module definition in lib/my_gem_name.rb and give it a try:
module MyGemName
def self.reload!
Reloader.new(self).reload
end
class Reloader
def initialize(top)
#top = top
end
def reload
cleanup
load_all
end
private
# #return [Array<String>] array of all files that were loaded to memory
# under the lib/my_gem_name folder.
# This code makes assumption #1 above.
def loaded_files
$LOADED_FEATURES.select{|x| x.starts_with?(__FILE__.chomp('.rb'))}
end
# #return [Array<Module>] Recursively find all modules and classes
# under the MyGemName namespace.
# This code makes assumption number #2 above.
def all_project_objects(current = #top)
return [] unless current.is_a?(Module) and current.to_s.split('::').first == #top.to_s
[current] + current.constants.flat_map{|x| all_project_objects(current.const_get(x))}
end
# #return [Hash] of the format {Module => true} containing all modules
# and classes under the MyGemName namespace
def all_project_objects_lookup
#_all_project_objects_lookup ||= Hash[all_project_objects.map{|x| [x, true]}]
end
# Recursively removes all constant entries of modules and classes under
# the MyGemName namespace
def cleanup(parent = Object, current = #top)
return unless all_project_objects_lookup[current]
current.constants.each {|const| cleanup current, current.const_get(const)}
parent.send(:remove_const, current.to_s.split('::').last.to_sym)
end
# Re-load all files that were previously reloaded
def load_all
loaded_files.each{|x| load x}
true
end
end
end
If you don't want this functionality to be available in production, consider monkey-patching this in the bin/console script, but make sure to change the line $LOADED_FEATURES.select{|x| x.starts_with?(__FILE__.chomp('.rb'))} to something that will return a list of relevant loaded files given the new location of the code.
If you have a standard gem structure, this should work:
$LOADED_FEATURES.select{|x| x.starts_with?(File.expand_path('../../lib/my_gem_name'))} (make sure to put your monkey patching code before the IRB.start or Pry.start)

Split seeds.rb into multiple sections?

I'd like to split my seeds.rb file into multiple sections for ease of maintenance; seed all the A's in a.rb, the B's in b.rb, etc. The separate files are located in the db/ directory with seeds.rb. Each file consists of a bunch of "A.create" or "B.create" calls and I want to call those files from seeds.rb.
I've tried:
include 'a'
include 'b'
and
load 'a.rb'
load 'b.rb'
in my seeds.rb but they don't seem to be processed when I call "rake db:seed". This is probably more of a straight ruby question than a rails question but for completeness I'm using Ruby 1.9.2 and Rails 3 on a Mac.
In ./db/seeds/my_module.rb:
module MyModule
puts "In my_module.rb"
# add code here
end
In ./db/seeds.rb:
require File.expand_path('../seeds/my_module', __FILE__) # the ../ just removes `seeds.rb` filename from the path which is given by __FILE__
p "In seeds.rb"
# add code here
I would propose to create a new db/seeds/ directory where you can place your various seeds file:
db/seeds/01_stuff_that_comes_for_first.rb
db/seeds/02_stuff_that_comes_for_second.rb
...
And then edit your db/seeds.rb file with:
Dir[File.join(Rails.root, 'db', 'seeds', '*.rb')].sort.each { |seed| load seed }
So, you can load your seeds even in the order you prefer - that is often something requested.
This solution was originally proposed by nathanvda in this "duplicated" question.

Resources