[newbie] Selecting technology to write small web application

Hello,
I am going to write a little web application which parse one easy form
using some data being read from files on server and returns output to
user. Of course I would love to use Ruby, but as I mentioned in subject
I am a beginner in Ruby<->web world so I do not want to fail in the
design phase.
How would this kind of application be done by experienced Ruby
developer? Is it a good idea to use CGI or eRuby? If yes then what
configuration of those two is recommended?
When it comes to configuration of server there is no difference for me
which is easier since I am trying to achieve this on my own machine that
I configure myself.

Tomasz Strojny wrote in post #1155158:

Hello,
I am going to write a little web application which parse one easy form
using some data being read from files on server and returns output to
user. Of course I would love to use Ruby, but as I mentioned in subject
I am a beginner in Ruby<->web world so I do not want to fail in the
design phase.
How would this kind of application be done by experienced Ruby
developer? Is it a good idea to use CGI or eRuby?

I would use CGI. It is simple and at the very least learning CGI will
teach you some basics. If the app were a little more complex, then
Sinatra would be a good choice. It would be good practice to write your
app with CGI, then rewrite it with Sinatra. Learning the basics of
Sinatra is very easy:

http://www.sinatrarb.com/intro.html

eRuby, or ERB as it’s more commonly referred to, is a template system
which allows you to keep your html in a different file than your
application code. That is considered good practice, however I would
forgo erb for now as it complicates things slightly. ERB would be
something else
to try after you’ve written your app using basic CGI. So this might be
a good
progression:

  1. CGI script
  2. CGI script with erb
  3. Sinatra script
  4. Sinatra script with erb

If yes then what
configuration of those two is recommended?

I’m not sure what you mean. Just look up a ruby CGI tutorial, like this
one:

and get started.

When it comes to configuration of server

Okay, by 'configuration of CGI/ERB, you appear to be asking how to
setup a server on your own machine. One of the nice things about
Sinatra is that it comes prepackaged with a server, so you don’t have to
setup a server yourself–you just run your Sinatra program, and
a server starts automatically.

A more complex option would be to install the free Apache server on
your local machine, but setting it up can take some time. I set up
Apache when I was a beginner, so it is possible for a beginner.

Another option is to use the WEBRick server, which comes with ruby. If
you look at the ruby docs for WEBRick, you can create a server with this
code:

#my_server.rb
require 'webrick'

root = File.expand_path '~/ruby_programs/public_html'

server = WEBrick::HTTPServer.new(
  :Port => 6789,
  :DocumentRoot => root
)

trap 'INT' do  #This allows you to stop the server by hitting Ctrl+C
  server.shutdown
end

server.start

If you run that program:

$ ruby my_server.rb

it will print out some information, then hang.

Then if you put a file called page1.html in the directory:

~/ruby_programs/public_html   # ~  is the path to your Home dir

which is the directory specified in my_server.rb, then you can retrieve
the page by entering the following url in a browser:

htpp://localhost:6789/page1.html

(6789 is the Port specified in my_server.rb) Because that is so simple,
I suggest you use WEBRick for a CGI script.

7stud – wrote in post #1155328:

Another option is to use the WEBRick server, which comes with ruby. If
you look at the ruby docs for WEBRick, you can create a server with this
code:

Here are some corrections that are needed to execute cgi scripts–
rather than just returning their text:

#my_server.rb
require 'webrick'
include WEBrick

root_dir = File.expand_path '~/ruby_programs/public_html'
server = WEBrick::HTTPServer.new(
  :Port => 6789,
  :DocumentRoot => root_dir
)

#Setup a directory so that webrick will execute the
#requested files rather than returning their text
#(the files must have a .cgi extension):

cgi_dir = File.expand_path("~/ruby_programs/cgi_scripts")
server.mount("/cgi", HTTPServlet::FileHandler, cgi_dir)

trap 'INT' do   #Can stop server by hitting Ctrl+C
  server.shutdown
end

server.start

That tutorial I linked to won’t even produce a basic script that runs
without getting the error:

Internal Server Error
bad header ‘HTTP/1.0 200 OK\n’

Here is a cgi script called my_prog.cgi, which will work:

#!/usr/bin/env ruby
require ‘cgi’

#The following line causes the error:
#puts “HTTP/1.0 200 OK\n”

puts “Content-type: text/html\n\n”
cgi = CGI.new

puts <<END_OF_HTML

Name: #{cgi['name']}
Age: #{cgi['age']}
END_OF_HTML

Put the cgi script in the cgi_dir specified in my_server.rb:

~/ruby_programs/cgi_scripts

(~ is the path to your Home directory)

Then run the server script:

$ ruby my_server.rb

Then open a browser and enter the url:

http://localhost:6789/cgi/my_prog.cgi?name=Tomasz&age=20

You should see:

Name: Tomasz
Age: 20

Check the CGI docs for other ways to output html:

http://docs.ruby-lang.org/en/2.1.0/CGI.html

See the section: “Print http header and html string”

Note that for html5, you would do this(which should most likely be your
default code):

cgi = CGI.new(‘html5’)

You can actually test your cgi script without first serving up an html
page with a form, filling out the form, then submitting your form to the
cgi script. To do that you just use ruby to run your cgi script, like
this:

~/ruby_programs/cgi_scripts$ ruby my_prog.cgi
Content-type: text/html

(offline mode: enter name=value pairs on standard input)
name=Tomasz #<= I entered this
age=20 #<=I entered this

#This is the start of the response
Name: Tomasz
Age: 20

After you are done entering name/value pairs hit Ctrl+D.

Okay, final answer…

This is the simplest code for a webrick server:

require 'webrick'
include WEBrick

root_dir = File.expand_path '~/ruby_programs/public_html'
server = WEBrick::HTTPServer.new(
  :Port => 6789,
  :DocumentRoot => root_dir
)

trap 'INT' do  #This allows you to stop the server by hitting Ctrl+C
  server.shutdown
end

server.start

With that code, webrick will execute files with a .cgi extension that
are in the public_html directory, which is the directory specified as
the root directory.

The url to execute a cgi program for that server code is:

http://localhost:6789/my_prog.cgi?name=Tomasz&age=20

YOU MUST MAKE SURE that your cgi program has executable
permissions:

$ chmod a+x my_prog.cgi

The url to request an html page in the public_html
directory is:

http://localhost:6789/page1.htm

If you want to specify another directory to put your cgi files in
instead of the public_html directory, then you have to add this
code:

#To setup a separate directory for your cgi programs
#(the files must have a .cgi extension):

cgi_dir = File.expand_path("~/ruby_programs/cgi_scripts")
server.mount("/cgi", HTTPServlet::FileHandler, cgi_dir)

With that server code, the url to execute a cgi program in the cgi_dir
is:

 http://localhost:6789/cgi/my_prog.cgi?name=Tomasz&age=20

7stud – wrote in post #1155331:

After you are done entering name/value pairs hit Ctrl+D.

More specifically, after entering the last name/value pair hit Return so
you leave that line, then hit Ctrl+D.

Thanks 7stud for very comprehensive answer(s)! I am sure that your work
will explain the basics not only for me.
Excuse me if there were some things in my question hard to understand, I
have not been using English for a long time. I promise I will get better
:wink:
Actually, the server-configuration part was the easier one for me since
I am sort of system administrator. Before you replied I managed to run
sinatra in my Apache using RVM.
What is more, I tried CGI some time ago, but I did not like the
structure:
cgi.html { cgi.body + … etc.
The problem I have tried to describe writing “configuration of those
two” was the thing I did not fully understand how I am going to send the
form data to my script and return some output to webpage. You answered
100% helpfully.

Furthermore, I was wondering if there is some easier ruby-style way to
help me with forms and I found simple_form gem dedicated for Rails. And
now I am trying to achieve something like described here:
http://nicksda.apotomo.de/2012/06/using-rails-gems-like-simple_form-in-sinatra-or-anywhere/
Thanks a lot again.

Tomasz Strojny wrote in post #1155340:

What is more, I tried CGI some time ago, but I did not like the
structure:
cgi.html { cgi.body + … etc.

Yeah, I’ve never found a need to use that feature of cgi either.
That feature is an
attempt to shorten how much you have to type when writing html.
But instead of that, you can use raw html–as the example in
one of my previous posts uses. After you get that to work,
then you can use ERB, and take advantage of some of the
features of ERB to make things shorter, like loops.

Furthermore, I was wondering if there is some easier ruby-style way to
help me with forms and I found simple_form gem dedicated for Rails. And
now I am trying to achieve something like described here:

http://nicksda.apotomo.de/2012/06/using-rails-gems-like-simple_form-in-sinatra-or-anywhere/

Thanks a lot again.

I find most things rails related to be so complex as to be almost
unusable. A form is just html, so you should study ‘html forms’ to
learn how to write forms. The rails way of writing forms actually
requires MORE typing than just using an html form, and I think you need
to be using rails Models to get any benefit out of rails form methods,
which is a whole other can of worms.

Now if you are trying to write a form with 100 input elements, then it
would be helpful to be able to loop over some data and generate the
input elements–and ERB can do that. See here:

http://www.stuartellis.eu/articles/erb/

Sinatra allows you to choose among many template languages. See
the template section here:

http://www.sinatrarb.com/intro.html#Erb%20Templates

So if you are already tired of cgi, use Sinatra. If you need a Sinatra
example I can post one.

Here is a simple Sinatra example using an erb template for the form:

$ tree ~/ruby_programs/sinatra_1app/
/Users/7stud/ruby_programs/sinatra_1app/
├── public
│ └── cool_stuff.html
├── routes.rb
└── views
└── form1.erb

2 directories, 3 files

Anything in the public directory can be accessed directly, e.g.

http://localhost:4567/cool_stuff.html

…you do not have to create a route in routes.rb.

Here are the files:

#routes.rb:

require ‘sinatra’

get ‘/drink_form’ do
erb :form1, #Sinatra looks for a file named views/form1.erb
:locals => {:drinks => [‘coffee’, ‘tea’, ‘Coke’, ‘7up’]}
#^^^ creates a variable named drinks in form1.erb
end

post ‘/process_form1’ do
“Enjoy your #{params[:drink_select]}!”
end

======

#views/form1.erb:

<% drinks.each do |drink| %> <%= drink.capitalize %> <% end %>
</form

===

  1. Start the server:

    ~/ruby_programs/sinatra_1app$ ruby routes.rb

  2. To display the form in your browser use the following url

    http://localhost:4567/drink_form

Sinatra will render(or execute) the erb template, and send the
resulting string, which contains html, as the response.

  1. Select a drink, then click the submit button.

The form’s action attribute is:

action="/process_form1

…so submitting the page will request the
url ‘/process_form1’, which matches the post route in
routes.rb. Inside the block for the post route, Sinatra will
extract the form variable named ‘drink_select’, which is the
name attribute for the tag:

<select name='drink_select'>

and insert its value into the response message, which your
browser will then display as:

Enjoy your 7up!

Thanks a lot again. Your help is priceless.
I have another question about my application. The problem is that the
user of my form have to have functionality of adding some options
dynamically.
According to your example, what I am trying to explain is form in which
he can choose ‘7up’, than click plus icon and select in next “select
field” ‘coffee’, than (if he wants) click plus icon again and select
‘tea’ in third one.
I am aware that this material is JavaScript, but I am curious how is it
possible to get dynamic JS form and Sinatra (erb) talking.
Thanks in advance.