How to create a directory inside a directory with ruby and ARGV - ruby

I have a program that asks with the termial to write the name of the directory that the user wants, like this $ ruby app.rb mysuperdirectory
def get_ directory_name
return directory_name = ARGV.first
end
def create_ directory(name)
Dir.mkdir(name)
end
def perform
directory_name = get_ directory_name
create_ directory(directory_name)
end
perform
I will automatically want to create a lib directory Dir.mkdir("lib") and put it in the directory mysuperdirectory .
In this mysuperdirectory that the user has just created with lib inside, I would like to make a system("git init")and system("rspec --init")
How can I do all this?
Thanks

You can use Dir.chdir to change directory.
def perform
directory_name = get_ directory_name
create_ directory(directory_name)
create_ directory("#{directory_name}/lib")
Dir.chdir(directory_name) do
system("git init")
system("rspec --init")
end
end

Related

How to include code from a file in Ruby?

I'm new to Ruby and I'm figuring out how to include a file in a script. I tried require and include but it doesn't work.
Here's the file I'd like to include, worth noting that it's not a module.
# file1.rb
if Constants.elementExist(driver, 'Allow') == true
allowElement = driver.find_element(:id, 'Allow')
allowElement.click()
sleep 1
wait.until {
driver.find_element(:id, 'Ok').click()
}
username = driver.find_element(:id, 'UsernameInput')
username.clear
username.send_keys Constants.itech_email
password = driver.find_element(:id, 'PasswordInput')
password.clear
password.send_keys Constants.itechPass
driver.find_element(:id, 'Login').click
else
username = driver.find_element(:id, 'UsernameInput')
username.clear
username.send_keys Constants.itech_email
password = driver.find_element(:id, 'PasswordInput')
password.clear
password.send_keys Constants.itechPass
driver.find_element(:id, 'Login').click
end
That file contains several lines of codes that are reusable or repeatable in my case. It's not inside a class or a module. It's a straightforward Ruby script, and I'd like to use this on my second script inside a module.
# file2.rb
module File2
module IOS
# include file1.rb
end
end
This way, it should just run the code of file1.rb inside file2.rb.
How can I do this in Ruby?
According to the Ruby docs, require has the following behavior:
If the filename does not resolve to an absolute path, it will be
searched for in the directories listed in $LOAD_PATH ($:).
Which means that in order to run file1.rb's code inside file2.rb, where both files are in the exact same folder, you'd have to do the following:
# file2.rb
module File2
module IOS
# Absolute path to file1.rb, adding '.rb' is optional
require './file1'
end
end
use require_relative:
require_relative 'file1.rb'

Opening relative paths from gem

I'm writing a simple gem that can load from and save data to text files and zip archives. So, it has four methods: load_from_file, load_from_zip, save_to_file and save_to_zip respectfully. The problem is that I can't figure out how to specify relative paths for loading and saving for these methods. Here they go:
def load_from_file(filename)
File.open(filename) do |f|
f.each { |line| add(line) } # `add` is my another class method
end
end
def load_from_zip(filename)
Zip::File.open("#{filename}.zip") do |zipfile|
zipfile.each { |entry| read_zipped_file(zipfile, entry) } # my private method
end
end
def save_to_file(filename)
File.write("#{filename}.txt", data)
end
def save_to_zip(filename)
Zip::File.open("#{filename}.zip", Zip::File::CREATE) do |zipfile|
zipfile.get_output_stream('output.txt') { |f| f.print data }
end
end
private
def read_zipped_file(zipfile, entry)
zipfile.read(entry).lines.each { |line| add(line) }
end
So what I want basically is to allow this gem to load and save files by relative paths whereever it is used in system, e.g. I have an app located in /home/user/my_app with two files - app.rb and data.txt, and I could be able to read the file from this directory without specifying absolute path.
Example:
# app.rb
require 'my_gem'
my_gem = MyGem.new
my_gem.load_from_file('data.txt')
(Sorry for bad English)
UPD: This is not Rails gem and I'm not using Rails. All this is only pure Ruby.
Short answer
If I understand it correctly, you don't need to change anything.
Inside app.rb and your gem, relative paths will be understood relatively to Dir.pwd.
If you run ruby app.rb from inside /home/user/my_app :
Dir.pwd will be /home/user/my_app
both app.rb and my_gem will look for 'data.txt' inside /home/user/my_app.
Useful methods, just in case
Dir.chdir
If for some reason Dir.pwd isn't the desired folder, you could change directory :
Dir.chdir('/home/user/my_app') do
# relative paths will be based from /home/user/my_app
# call your gem from here
end
Get the directory of current file :
__dir__ will help you get the directory :
Returns the canonicalized absolute path of the directory of the file
from which this method is called.
Get the current file :
__FILE__ will return the current file. (Note : uppercase.)
Concatenate file paths :
If you need to concatenate file paths, use File.expand_path or File.join. Please don't concatenate strings.
If you don't trust that the relative path will be correctly resolved, you could send an absolute path to your method :
my_gem.load_from_file(File.expand_path('data.txt'))

How do I use a Chef Resource in a Library

How do I include a Chef Directory resource in a library? When executing the recipe below, the variables are assigned but the directories aren't created. I don't receive any error messages.
This is a simplified example. Trying to create multiple directories by passing the directory name to a library.
# create directories
# /var/www/domain
# /var/www/domain/production
# /var/www/domain/staging
The library
# directory library
class DirectoryStructure
attr_accessor :domain, :production, :staging
def initialize(domain)
#domain = "/var/www/#{domain}"
#staging = "##domain/staging"
#production = "##domain/production"
end
def create(dir_type,directory_path,username,group)
dir = Chef::Resource::Directory.new(:create)
dir.name(directory_path)
dir.owner(username)
dir.group(group)
dir.mode(2750)
dir
end
end
The recipe
web_dirs = DirectoryStructure.new(domain)
site_dirs.create(web_dirs.domain,username,deploy_group)
site_dirs.create(web_dirs.production,username,deploy_group)
site_dirs.create(web_dirs.staging,username,deploy_group)
I have tried to use this example but I am obviously missing something.
enter link description herehttps://docs.chef.io/lwrp_custom_resource_library.html
This looks like you should be creating a resource, either an LWRP or a normal Ruby class. In most cases the LWRP will be simpler and is probably what you want in this case.
cookbooks/mycook/resources/directory_structure.rb:
default_action :create
attribute :domain, name_attribute: true
attribute :owner
attribute :group
cookbooks/mycook/providers/directory_structure.rb:
action :create do
directory "/var/www/#{#new_resource.domain}" do
owner new_resource.owner
group new_resource.group
end
directory "/var/www/#{#new_resource.domain}/production" do
owner new_resource.owner
group new_resource.group
end
directory "/var/www/#{#new_resource.domain}/staging" do
owner new_resource.owner
group new_resource.group
end
end
cookbooks/mycook/providers/directory_structure.rb:
mycook_directory_structure 'example.com' do
owner 'me'
group 'mygroup'
end

config location ruby and using rake for unit test

Learning Ruby, my Ruby app directory structure follows the convention
with lib/ and test/
in my root directory I have a authentication config file, that I read from one of the classes in lib/. It is read as File.open('../myconf').
When testing with Rake, the file open doesn't work since the working directory is the root, not lib/ or test/.
In order to solve this, I have two questions:
is it possible, and should I specify rake working directory to test/ ?
should I use different file discovery method? Although I prefer convention over config.
lib/A.rb
class A
def openFile
if File.exists?('../auth.conf')
f = File.open('../auth.conf','r')
...
else
at_exit { puts "Missing auth.conf file" }
exit
end
end
test/testopenfile.rb
require_relative '../lib/A'
require 'test/unit'
class TestSetup < Test::Unit::TestCase
def test_credentials
a = A.new
a.openFile #error
...
end
end
Trying to invoke with Rake. I did setup a task to copy the auth.conf to the test directory, but turns out that the working dir is above test/.
> rake
cp auth.conf test/
/.../.rvm/rubies/ruby-1.9.3-p448/bin/ruby test/testsetup.rb
Missing auth.conf file
Rakefile
task :default => [:copyauth,:test]
desc "Copy auth.conf to test dir"
task :copyauth do
sh "cp auth.conf test/"
end
desc "Test"
task :test do
ruby "test/testsetup.rb"
end
You're probably getting that error because you're running rake from the projects root directory, which means that the current working directory will be set to that directory. This probably means that the call to File.open("../auth.conf") will start looking one directory up from your current working directory.
Try specifying the absolute path to the config file, for example something like this:
class A
def open_file
path = File.join(File.dirname(__FILE__), "..", "auth.conf")
if File.exists?(path)
f = File.open(path,'r')
# do stuff...
else
at_exit { puts "Missing auth.conf file" }
exit
end
end
Btw, I took the liberty of changing openFile -> open_file, since that's more consistent with ruby coding conventions.
I recommend using File.expand_path method for that. You can evaluate auth.conf file location based on __FILE__(current file - lib/a.rb in your case) or Rails.root depending on what you need.
def open_file
filename = File.expand_path("../auth.conf", __FILE__) # => 'lib/auth.conf'
if File.exists?(filename)
f = File.open(filename,'r')
...
else
at_exit { puts "Missing auth.conf file" }
exit
end
end

Create a file in a specified directory

How can I create a new file in a specific directory. I created this class:
class FileManager
def initialize()
end
def createFile(name,extension)
return File.new(name <<"."<<extension, "w+")
end
end
I would like to specify a directory (path) where to create the file. If this one doesn't exist, he will be created. So do I have to use fileutils as shown here just after file creation or can I specify directly in the creation the place where create the file?
Thanks
The following code checks that the directory you've passed in exists (pulling the directory from the path using File.dirname), and creates it if it does not. It then creates the file as you did before.
require 'fileutils'
def create_file(path, extension)
dir = File.dirname(path)
unless File.directory?(dir)
FileUtils.mkdir_p(dir)
end
path << ".#{extension}"
File.new(path, 'w')
end

Resources