Writing a ruby script to find and replace a file
Published: 2020-08-20 16:16:20

This article is targeted for teachers and someone who works with beginners. If someone forked a project and started to work on it, but you have found a mistake in it and need to fix it, here is a way of fixing a specific file by replacing a file in a rails project by creating a command-line script for students and beginners to run. 

First, create your fix. An example of this would be if I wrote a bad test and wanted to replace my test file with my new one.  I would link directly to the raw ruby file. It is important to keep track of this URL.  Here is a link to a [ruby file](https://raw.githubusercontent.com/pmckernin/dotfiles/master/ruby_file.rb). The one I have linked here is just a simple script that prints "Hello World".  Usually, your script on Github would be the exact file you are working on with the fix.  Also, to be clear, this script will replace a file, not amend it.  
Second, we will need to write our script. Here is an example script, let's break down what each line does.  
```
#!/usr/bin/env ruby
#wget  -O bin/hello_world "url" && chmod 777 bin/hello_world && bin/hello_world
require "open-uri"
spec_path = "spec/features/user_auth_spec.rb"

format_file = File.open(spec_path, File::RDWR)

text = File.open(spec_path).read
url="https://raw.githubusercontent.com/pmckernin/dotfiles/master/ruby_file.rb"
new_content = open(url).read

File.open(format_file, "w") { |file| file << new_content }
```
` #!/usr/bin/env ruby`
* This is commented out because it does not run in the script but should run in the terminal. I keep this in the script so I don't have to continually look up what to run. This line will allow us to call the name of our script without having to type `ruby` in front of it.  Just as when we run `bin/setup` we don't have to call `ruby bin/setup`. 

` #wget  -O bin/hello_world "url" && chmod 777 bin/hello_world && bin/hello_world `
* This line is also commented out because it is not meant to run in the script, but is meant for the students to run at their command line. 
* `wget -0` is a bash command for downloading files from the internet, with `-0` will allow us to name the file that you download from the URL. [Here is more on wget](https://stackoverflow.com/questions/9830242/what-does-wget-o-mean/16765470#16765470).  
* The first `bin/hello_world` is creating a file in our bin folder. We can name this whatever we would like, but eventually what we run at the command line to execute the script.  
* `url` is the URL that we are going do download from, in our case, the URL would be replaced with the one I have linked above. 
* ` chmod 777 bin/hello_world ` will make sure that we have admin access to the `hello_world` file. The `chmod` command has other numeric values that determine what you can execute from the command line, [here is further reading](https://www.computerhope.com/unix/uchmod.htm). 
* The second `bin/hello_world`, will run the name of the file you have created. 
* Just a reminder but the `&&` allow you to run multiple bash commands on the same line. 

`require "open-uri"`
*  We need to require "open-uri" in order to be able to open files from URLs as well as files in our project.

`spec_path = "spec/features/user_auth_spec.rb"`
* We will set the `spec_path` variable as the path to the file we want to replace, in this case, it would go to our spec folder, into the features folder and look for a file called `user_auth_spec.rb`. 

`format_file = File.open(spec_path, File::RDWR)`
* This line creates the `format_file` variable using the built-in ruby class `File.open` passing in our `spec_path` and giving the file read and write privileges.  Here is more about the ruby [File class](https://ruby-doc.org/core-2.5.0/File.html#method-c-open)

`text = File.open(spec_path).read`
* This will use the ruby `File.open` to go to our path for our project and save what it reads as the `text` variable. 


`url="https://raw.githubusercontent.com/pmckernin/dotfiles/master/ruby_file.rb"`
* The `url` variable will point us to the file we want to input into our project. 

`new_content = open(url).read`
* The `new_content` will go to the `url` we have defined and read the content

`File.open(format_file, "w") { |file| file << new_content }`
* This line will replace the content from our defined path with the content we downloaded from the URL. The shovel operator will overwrite the content of the file we just opened with our new content. 

Finally, at the command line, we will have the student run the script. The script is `wget  -O bin/hello_world "https://raw.githubusercontent.com/pmckernin/dotfiles/master/ruby_file.rb" && chmod 777 bin/hello_world && bin/hello_world`