How to start Rack application with frozen string literals? - ruby

I'm trying to run our application under ruby 2.3 using the new ruby feature for automatic frozen strings turned on globally. (Ruby 2.3) This is normally done by passing the argument to a ruby script when starting as follows:
ruby --enable-frozen-string-literal ruby_code_file.rb
Unfortunately, our application is started using rackup, and I've tried the following command:
rackup --enable-frozen-string-literal
But this does not appear to work. How do I pass that parameter into Rack?

You can't pass parameters for ruby to rackup, unfortunately. However, rackup is really, really simple:
#!/usr/bin/env ruby
require "rack"
Rack::Server.start
The simplest solution, then, is to duplicate this file in your project (in, say, bin/frozen_rackup) but change the first line to this:
#!/usr/bin/env ruby --enable-frozen-string-literal
Then make sure the file is executable (chmod u+x bin/frozen_rackup) and run bin/frozen_rackup instead of rackup.
P.S. I'm guessing that --enable-frozen-string-literal doesn't apply to gems your script requires, since it would break a lot of gems, but I haven't tested this and YMMV.

Related

RSpec basics: bin/rspec --format doc

I've installed RSpec on a win7 lappy and am following along the http://rspec.info/ homepage tutorial to make sure everything works. If I am reading their demo correctly bin/rspec --format doc should run the specification test file.
Instead, I get a system prompt for a text editor... ? I am confused.
Any explanation of what is going on or guidance about how to get my RSPEC configuration working in accordance to the makers homepage would be great.
FWIW Ruby 2.2.5p319, Bundler version 1.13.1 and gem -v tells me 2.6.7 (originally I had 2.4 but that is broken on windows, so I upgraded according to http://guides.rubygems.org/ssl-certificate-update/) Also, I have basic RSpec functionality and have completed the tutorial here: https://www.tutorialspoint.com/rspec/rspec_writing_specs.htm
Ah, I figured out what I need to do... I just need to explicitly call ruby:
ruby bin/rspec --format doc
...and the test gets run - YaY!
Per #JörgWMittag, I confirmed my Environment Variable Path to make sure ruby.exe was in there (C:\Ruby22\bin;).
Then looking at my Program Defaults, I thought that maybe I could tell win7 to associate any file named "rspec" with ruby.exe per https://support.microsoft.com/en-us/help/18539/windows-7-change-default-programs ...but I couldn't actually add file type "extensions" or "protocols" - I could only change the association of existing ones, but .rb and .rbw were in there... Maybe there is a way to do this manually, but I am not a windows expert.
Thinking on all this it occurred to me that I just needed to explicitly tell ruby to ingest the command... Heh.
I apologize if this is off-topic.

How can I run a terminal command from a program?

I have a small ruby program that I'm working on at the moment (Pure ruby, not rails), which crawls a small portion of the web for certain movies. Is there a recommended way to, for example, when I run the script from my windows terminal, that it will open up a browser with the url that I extracted?
I know start http://example.com works from the windows terminal but im just wondering if there's a way to invoke a method like this directly from a ruby script.
I've found a nice gem called launchy to do this (at least opening a url)
http://www.rubydoc.info/gems/launchy/2.4.3
In the terminal :
gem install launchy
then:
require 'launchy'
Launchy.open("url")

Automatically run RSPec when plain-old Ruby (not Rails) files change

I am writing a Ruby script designed to run from the command line. The script has a corresponding RSpec file that verifies its functionality. The folder structure is:
./main_script.rb
./spec/main_script_spec.rb
Running rspec spec in the top level directory works as expected. Test results from the ./spec/main_script_spec.rb file are shown. I'd like to avoid running this manually every time I change either the main script file or the spec file. All my search results turn up things like guard which (as far as I can tell) are all designed for Rails apps.
How do I setup RSpec to watch for script or spec changes and run automatically with non-Rails Ruby code?
Like David said, Guard can be used to watch a wide variety of files and perform actions when those files are modified. It does not have to be used with a Rails app. I have set up something similar in the past using guard. Here is what I did:
Place the following in your Gemfile:
source 'https://rubygems.org'
gem 'guard'
gem 'guard-shell'
gem 'rspec'
gem 'rb-fsevent', '~> 0.9'
Then run:
$ bundle install
Create a Guardfile in your home directory with:
$ guard init
In the Guardfile, comment out the examples and add this:
guard :shell do
watch(%r{^*\.rb}) { `bundle exec rspec spec/` }
end
This tells guard to watch for modifications to any ruby files in the directory and execute the command bundle exec rspec spec/ when they change (the backticks are used to execute the command in the shell).
Then open up a new terminal window in your current directory and start a guard server to start watching the files:
$ bundle exec guard
Now your Rspec test suite should automatically run when you modify ruby files in the directory.
I used guard at the past, but now I'm using a combination of rspec focus feature and watch command.
It's very simple, just add an f before a describe of it block you want to run the test. So it would becomes fdescribe or fit block. This is the same as adding a tag :focus => true to your block.
We can then filter specs with the focus tag: rspec -t focus
Now, to keeping running theses specs (every 0.5 seconds) with focus tag we call it with watch command:
watch -n 0.5 rspec -t focus
But with that the output won't show colors. So, we need to use with unbuffer.
sudo apt-get install expect
With a little customization:
watch -n 0.5 --color 'unbuffer bundle exec rspec -t focus'
Since it's annoying to type this all, I made two alias at my ~/.bash_aliases file (your can use .bashrc as well):
alias focus="watch -n 0.5 --color 'unbuffer bundle exec rspec -t focus'"
alias focuss="bundle exec rspec -t focus"
Now I can type focus to keep running it, or for a single focus execution I type focuss
Guard can be used for plain old ruby. I generally have trouble with guard so I like to use watchr, another gem. With a few lines of code you can tell watchr to watch for changes to your files and run a command when they change.
For an example of guard with plain ruby, see the shuhari gem.
update on watchr gem: There appears to be an issue with this gem, perhaps with versions of ruby >= 2.0. The observr gem addresses this issue and works as expected in ruby 2.3.
I have used guard and the guard-rspec addition with great results, and I don't believe it to be Rails-specific. Other Ruby/RSpec projects should work equally well.
The guard documentation recommends the use of Bundler and to "always run Guard through Bundler to avoid errors". I.e. you install it through your Gemfile and always run it with bundle exec guard (or use rubygems-bundler to avoid the bundle exec part).

run all selenium ruby webdriver scripts at a time.

Currently, I'm running each my Selenium Ruby Webdriver script (*.rb) on Ruby command prompt window with the syntax, ex: ruby test.rb. It works well.
However, I also have some other scripts and now I want to run all scripts once instead of calling ruby test1.rb, then wait for this script done, then continue to run: ruby test2.rb.....then, ruby test3.rb.....
Anybody please guide me a way to run all scripts I created at a time? Thanks so much.
You can use the rake gem, for this you need to create a file named rakefile.rb, and paste the below content:
task :default do
FileList['file*.rb'].each { |file| ruby file }
end
Now call rake in your terminal, you should be good.
What about making a feature file and running the entire feature?
Just create a ruby file like this:
require './Test1.rb'
require './Test2.rb'
Run it and see the result

Are bundle exec and require 'bundler/setup' equivalent?

Do these things accomplish exactly the same?
starting a ruby process with bundle exec ruby foo.rb
having require "bundler/setup" as the first line of foo.rb
In your specific example they can be considered the same, however in reality they are not the same.
bundle exec makes some changes to the environment that bundler/setup does not make. If your foo.rb never runs a subshell, or never tries to run other ruby executables in subshells, then both versions are equivalent (they will both load bundled gems correctly and work exactly the same).
The whole idea with bundle exec is to enable you to run executables that were not originally designed with bundler in mind. Like rspec, rails, rackup. If your own app (foo.rb) does not try to run such executables that might be dependent on your bundles, then it makes no difference either way. Since all you want to make sure with bundler is that you load the correct gems, and for that bundler/setup works exactly as expected in your case.
From the bundler docs when talking about running ruby system executables:
In some cases, running executables without bundle exec may work, if the executable happens to be installed in your system and does not pull in any gems that conflict with your bundle.
However, this is unreliable and is the source of considerable pain. Even if it looks like it works, it may not work in the future or on another machine.
Then from the manpage of bundle exec you can get some additional clues as to what bundle exec actually does:
ENVIRONMENT MODIFICATIONS
make sure that it's still possible to shell out to bundle from inside a command invoked by bundle exec (using $BUNDLE_BIN_PATH)
put the directory containing executables (like rails, rspec, rackup) for your bundle on $PATH
make sure that if bundler is invoked in the subshell, it uses the same Gemfile (by setting BUNDLE_GEMFILE)
add -rbundler/setup to $RUBYOPT, which makes sure that Ruby programs invoked in the subshell can see the gems in the bundle
So if you build your app with bundler support in mind, then you never need to bundle exec your app.
But if you need to use other tools that load your app code that might load gems before they load your app code (which then might pull in a wrong non-bundled gem), then you need to use bundle exec.

Resources