How do I run a ruby script from a webpage? - ruby-on-rails

I'm a total newb when it comes to programming and I'm trying to connect to a rest API with ruby on rails since it seemed like a good option to pick.
Before I try to connect to the API i'm just trying to figure out how to run a script from a webpage but it just tries to save the .rb file when I navigate to it in a browser. The code i have in the file is:
puts "hello world"
I uploaded the .rb file to my web server and went to the URL and it just tries to save the file. Sorry for the stupid question but I can't figure out how to do it!

In general, to run off simple commands like that, you can run ruby scripts via the terminal:
ruby /path/to/ruby/script.rb
Otherwise, if you insist on using a webserver for such purpose (or, if your use-case requires so), you should look at simple ruby-based web servers/frameworks like rack, sinatra, etc.
Particularly, in rack, you can save the following file (lets, say as: hello.rb):
require 'rubygems'
require 'rack'
def application(env)
[200, {"Content-Type" => "text/html"}, "Hello world."]
end
Rack::Handler::Mongrel.run method(:application), :Port => 9292
Then, you can run the above file using terminal:
ruby /path/to/hello.rb
And, this will create a local web server with port 9292, and you can open the above page at: http://127.0.0.1:9292/, and the page will say: Hello world.

You need an app server in order to serve a web page. Look at sinatra, rails and rack.
http://m.onkey.org/ruby-on-rack-1-hello-rack

A classic web server (like Apache, nginx, Tomcat, etc.) do exactly what you are describing, as well as do many other functions. To run ruby scripts, you'll need a Ruby application server, and the web server needs to reverse-proxy requests to that server. Definitely take a some tutorials around Rails and you'll see tons of examples.

If you want to run a Ruby script on the client-side (instead of on a server), you can use a Ruby-to-JavaScript compiler such as Opal or ruby2js, or a Ruby-to-WebAssembly compiler such as run.rb.
For example, Opal translates puts "hello world" into
/* Generated by Opal 0.11.0 */
(function(Opal) {
var self = Opal.top, $nesting = [], nil = Opal.nil, $breaker = Opal.breaker, $slice = Opal.slice;
Opal.add_stubs(['$puts']);
return self.$puts("hello world")
})(Opal);

Related

Automatic Reloading of Sinatra App mounted inside Rails App

I've run into what I hope is an easy-ish fix for someone more experienced than me when adding a Sinatra app to an existing Rails app.
I currently have a large rails monolith that I am planning to break apart into an SPA backed by a JSON API. Since I will still need to support the monolith until the API is completed I would like to mount the API (written in Sinatra) inside the existing Rails app as I port functionality over with a goal of removing the Rails app itself in a few months. The reason I've mounted the Sinatra app inside Rails instead of setting it up as a separate service was that I wanted easy code sharing between the two as I intend to continue using ActiveRecord as my ORM in Sinatra once the migration is complete.
I've mounted the Sinatra mockup inside the Rails app without any issues using the Rails routes.rb file as:
Rails.application.routes.draw do
mount API::Core, at: '/api'
...
end
I'm not doing any work with config.ru as mounting the API inside the routes.rb file seemed to suit my needs. If I need to put in some more legwork to get this running properly that is not an issue.
The entrypoint for the sinatra app is also fairly simple with just a couple controllers loaded in to segment the routing:
require 'sinatra/base'
require 'sinatra/json'
require_relative 'controllers/first_controller'
require_relative 'controllers/second_controller'
module API
class Core < Sinatra::Base
register Sinatra::FirstControllerApi
register Sinatra::SecondControllerApi
end
end
The problem I'm running into is one I expected with Sinatra but haven't been able to flex my google-fu enough to find a solution. Rails automatically reloads code on each change/request as expected but Sinatra does not. Every time I change controller code in the Sinatra API I need to restart the entire Rails server to serve the new content. Since my dev environment runs in docker containers this can take a while to start up each time and is becoming cumbersome.
Is there a 'canonical' solution to the problem of automagically reloading the Sinatra app mounted inside the Rails app or am I just over-complicating the problem? I know there are some gems for Sinatra that apply to this space but I haven't seen any info in how to get them working in this 'odd' edge case.
Please let me know if you need any more info, hopefully I've provided enough for someone to comprehend my issues.
Just like with a Sinatra app on it's own, a Sinatra app mounted inside o rails will not automatically reload as you make changes. Typically in Sinatra people would use external tools to help solve this problem, so they might set up something like Shotgun to watch the directory and restart the server any time a change has happened.
But, like most things in Rails, there is a way hook into it's functionatly for your own programming benefit.
ActiveSupport::FileUpdateChecker
Rails has a handy ActiveSupport::FileUpdateChecker that can watch a file, or a list of files. When they change it will call back to a block. You can use this to reload the Sinatra app -- or anything else for that matter.
In your case you might want to add the following to config/environments/development.rb in the config block for the application:
Rails.application.configure do
# ...
sinatra_reloader = ActiveSupport::FileUpdateChecker.new(Dir["path/to/sinatra/app/**"]) do
Rails.application.reload_routes!
end
config.to_prepare do
sinatra_reloader.execute_if_updated
end
end
Robert Mosolgo has a good write up on his blog: Watching Files During Rails Development. His approach is a little more thorough, but more complicated.

How to use Nokogiri to scrape data on a cloud development environment (Cloud9)

I'm currently using Cloud9 as a cloud-based IDE, but unfortunately it seems like running things on Cloud9 adds a layer of complexity that I don't quite understand.
For example, the following code, despite being copied and pasted from a tutorial, will not generate any output in the terminal:
require 'rubygems'
require 'nokogiri'
require 'open-uri'
url = "http://stats.nba.com/player/#!/203096/stats/"
data = Nokogiri::HTML(open(url))
puts data
This leads to two questions:
Do I need to deploy this code via something like Heroku, before it can access URLs on the internet? Or will it only work locally until I do that?
Where, exactly, is the output supposed to be when I'm not openly running a Ruby console? I'm simply running the file in bash.
Yes, you can do it:
Goto C9.io and login
Click "Workspace" and choose "Custom Template"
mkdir scrape && cd $_
touch scrape.rb
Paste your code into scrape.rb
Run: ruby scrape.rb
There you go, everything should be fine.
Because you are using OpenUri to get the webpage, this will work on Heroku or on any machine. But you don't need to use Heroku, as you are already able to scrape nba.com on Cloud9.
You said the code you are using doesn't print to console, but it does for me.
It depends what you want to do with the data you parse using Nokogiri. Do you want to save it to a database or file? Look into writing files instead of using the puts command to print to the screen.
This code outputs to the console.
First make sure you installed the Nokogiri gem, and you have full Internet connectivity.
Second start debugging. To debug a program you can use a gem like byebug that gives you an interactive debugger at runtime. Otherwise, as your code is short, you can add a bunch of puts "point x" to actually see where your program halts or break.
Third pay attention to any error or warning you see on the screen.

How do you spawn an EventMachine "inside" a Rails app?

I've got a Rails application, and am looking to add some sort of WebSocket support to it. From various googling, it appears that the best Ruby based WebSocket solution is em-websocket running on EventMachine.
I was wondering if there was a way to "integrate" an EventMachine reactor into Rails? Where do I put the initialization code? Is this the proper way to accomplish this?
I've seen this example that falls back on Sinatra to do an EventMachine GET request, but that isn't quite what I'm looking for.
Any help is appreciated.
You cannot run the Eventmachine engine inside of Rails itself as it is a persistent run loop that would block one of your Rails processes permanently. What is usually done is there's a side-process that uses Eventmachine and Rails communicates with it through sockets to send notifications.
Juggernaut serves as an example of this kind of thing where it implements a Websocket client and a Rails hook to send notifications to it. The project has since deprecated the Ruby version in favor of a JavaScript Node.js version but this still serves as a very thorough example of how Eventmachine can be used.
If you run rails application in a thin server (bundle exec thin start) thin server run EventMachine for you and then your rails application can execute EM code wherever you need.
By example:
A library o initializer with that code:
EM.next_tick do
EM.add_periodic_timer(20) do
puts 'from Event Machine in rails code'
end
end
not blocks rails processes application.
Don't know if this is what you are after. But if you would like to do provide some kind of socket-messaging system.
Have a look at Faye. It provides message servers for Node.js and Rack. There is also a rails cast for this by Ryan Bates which should simplify the implementation.
Hope that helps.
I spent a considerable amount of time looking into this. EventMachine need to run as a thread in your rails install (unless you are using Thin,) and there are some special considerations for Passenger. I wrote our implementation up here: http://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html
UPDATE
We pulled this configuration out into a gem called Momentarily. Source is here https://github.com/eatenbyagrue/momentarily
I'd try using em-synchrony to start a reactor in a fiber. In a rails app you can probably start it in an initializer since it sounds like you just want to leave the reactor running to respond to websocket requests. As suggested by the other answers I think you want to either setup socket communication with your reactor or use one of the asynchronous clients to a data store which both your reactor and rails code can read from and write to to exchange data.
Some of my coworkers put together some examples of starting EM reactors on demand in ruby code to run their tests within EventMachine. I'd try using that as a possible example; raking and testing with eventmachine
I'd consider looking into Cramp. It's an async framework built on top of EventMachine, and it supports Thin server:
Rack Middlewares support + Rainbows! and Thin web servers
You probably shouldn't use EM any more if you can help it, it seems to no longer be maintained - if you encounter a bug - you're on your own.
Most of the answers above don't work in JRuby due to https://github.com/eventmachine/eventmachine/issues/479 - namely the pattern:
Thread.new{ EM.run }
used by EM::Synchrony and various answers found around the internet (such as EventMachine and Ruby Threads - what's really going on here?) are broken under JRuby eventmachine implementation (fibers are threads in jruby and there's currently no roadmap on when this will change).
JRuby messaging options would be
deploy with TorqueBox (which comes bundled with HornetQ), http://torquebox.org/news/2011/08/15/websockets-stomp-and-torquebox/, impressive and enterprisey but not really elegant unless you're coming from a Java background
newer versions of Faye should work with JRuby, Faye in jruby on rails
note for the future, keep an eye on the celluloid community, some interesting distributed solutions are coming from there https://github.com/celluloid/reel/wiki/WebSockets, https://github.com/celluloid/dcell
?
I had same problem and found solution. First, put your code in lib dir (for example /lib/listener/init.rb) and create one class method that run EM, for example Listener.run.
#!/usr/bin/env ruby
require File.expand_path('../../config/environment', File.dirname(__FILE__))
class Listener
def self.run
# your code here
# you can access your models too
end
end
After that I used dante gem. Create /init/listener file. The code may be like that:
#!/usr/bin/env ruby
require File.expand_path('../../lib/listener/init.rb', __FILE__)
log_file = File.expand_path('../../log/listener.stdout.log', __FILE__)
pid_file = File.expand_path('../../tmp/listener.pid', __FILE__)
listener = Dante::Runner.new('listener')
if ARGV[0] === 'start'
listener.execute(daemonize: true,
pid_path: pid_file,
log_path: log_file) { Listener.run }
elsif ARGV[0] === 'restart'
listener.execute(daemonize: true,
restart: true,
pid_path: pid_file,
log_path: log_file) { Listener.run }
elsif ARGV[0] === 'stop'
listener.execute(kill: true, pid_path: pid_file)
end
Now you can run you code like that: ./bin/listener start, ./bin/listener restart, ./bin/listener stop
You can use god for monitoring your listener is running. But make sure you're using same pid file (/tmp/listener.pid).

I'm a bit lost: how to render rails/ruby on a website?

Ok, long time php guy doing my best to pick up ruby on rails by developing a small website for myself using only ror instead of php.
However i'm a bit stuck, and i think it is because i'm not exactly understanding how rails actually works.
I am running centos 5.5 / apache2. I have successfully installed ruby, rubygems, and subsequently rails and passenger. All these are 'working', i can run ruby commands, gem commands etc.
But how do I start using rails on my website? If I create an .erb or .rb file with some simple ruby commands, it just displays as plain text when I navigate to it.
Do I need to configure apache to 'execute' .rb or .erb files (similar to the way .php files execute?).
Any help would be GREATLY appreciated!!
You might check out the Rails Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
I suggest you read a huge tutorial on this topic: http://guides.rubyonrails.org/getting_started.html.
Ruby is the language, and Ruby on Rails is a framework. From the guide:
Rails is a web application development
framework written in the Ruby
language. It is designed to make
programming web applications easier by
making assumptions about what every
developer needs to get started. It
allows you to write less code while
accomplishing more than many other
languages and frameworks. Experienced
Rails developers also report that it
makes web application development more
fun.
I'd read Chapter 4, if you already know all this, as it talks about the actual webserver.
Rails comes with it's own webserver, so Apache isn't needed.
Sounds like you need to really get a handle on Rails and what it is first. This site has some great information for beginners, and should help you understand what you are working with and your next steps to get an application running:
http://guides.rubyonrails.org/getting_started.html
I've also heard some good things about the information here:
http://railsforzombies.org/
Check out Ruby on Rails Tutorial for getting started in Rails.
As #Blender mentioned, rails comes with an in build web server called webrick. (Think of it same as apache .. for now)
so all you have to do is go to the rails project directory, and run the command
if you are using rails < 3.x
ruby script/server
if you are using rails > 3.x
rails server
once u done this your rails project will start in webrick server and by default in port 3000
http://localhost:3000
you may consider apache/ some other rails server setup for production deployment, but to get started you dont need apache at all
and welcome to ruby world ! :D
HTH
sameera

Viewing a Ruby on Rails script in my native browser

I'm new to developing in Ruby and have mostly been using irb to experiment with code. For longer scripts, it would be helpful to be able to run them in my native browser (similar to how I run php scripts through MAMP). I believe there is a way to do this using localhost:3000 but I have not been able to get it to work. So my question is, what is the best way to view Ruby scripts in my native browser?
Well, running some Ruby code in IRB has nothing to do with using the Rails framework.
Follow a tutorial (for example this one) to learn the Rails framework itself now you have some understanding of the Ruby language.
Good luck.
I don't see how this would really be helpful to you, but it would be pretty easy to put your code into a simple Sinatra route and have that serve the result of the code into a browser if you want. Then you can just…
require 'rubygems'
require 'sinatra'
get '/' do
"Hello World! This is file #{$0} live from Boulder!"
end
And when you access the server on your local computer, it will print whatever you put in the method.
I would be interested to hear why you want to do this rather than IRB, though. This seems like kind of a perverse way to code in most cases.
Rack is a Ruby webserver interface, you probably want to use that to hook your ruby script up with a server.

Resources