Ruby out of the Rails - Nitro and Og

The Ruby language, started to grow inside the enterprises and to be “the topic” in many blogs after the Rails framework showed up, but Rails is not the only option for developing web applications with Ruby, there are other frameworks, and one of “the others” is called “Nitro Framework“, thsi one has almost the same age as Rails but it has a lot less documentation and AFAIK a lot less users too.

This post is about my first 30 minutes with Nitro.

One of the better things about rails, and one of the things that you can not do with Nitro is just to change a class while the server is running, and see the change after a refresh in the browser window, but I’ll talk about these problems later …

The Nitro framework, goes through a path different from Rails, while Rails tell you where to put your models, where to put your controllers, where to put your views, …

What I think is a great feature, since when you start working in a new project you already know where every thing is, Nitro let you put your stuff just where you want it to be.

What is a nice feature too, but if I want to put things where I want them to be, I’ll use Java as I’m doing for the last 5 years :D

Nitro is almost a two framework in one, with Nitro you can develop MVC style applications like Rails, but you can write page oriented applications like in PHP or ASP too, and the best thing is that you can mix the two styles too, of course it will increase the complexity of your application, but it can make it a lot easier to work too, you can write what you need using the easier way to accomplish that task.
To start playing with Nitro just run the following commands:

  • gem install -y nitro (this one will install Nitro and all its dependencies)
  • gen app rocketpower (now let’s create a Nitro application called “rocketpower”m I know they tell you in the home page that it is not rocket science but the name is fun :D)
  • cd rocketpower
  • ruby run.rb (I needed to edit the file for it to work, just open it in any editor and add “require ‘rubygems’” in the second line)
  • point your browser to http://locahost:9000

Every thing ready, you are running your first Nitro application!

Until now, I think that nitro is more complicated than Rails, probably the lack of documentation contributed a lot to this, the terrible examples have their share in this responsibility too, but Nitro has some cool things too.

If you want to create a page based application, you just need to create some “.xhtml” files and place your Ruby code between <?r and ?>, or if you just want to display some string, do it just like in any Ruby String, placing your code between #{ … }.

Since nitro does not have a fixed directory structure, you need to “require” some of your Ruby files from inside the “run.rb” code, I think that this is the cause of the lack of automatic reloading of your code.

Nitro uses Og for persistence, and Og does not need your persistent objects to extend any class, it will persist any object that uses any of it’s “property definition helpers”, itlooks for an automatic created method called “serializable_attributes”, I think it is more the “ruby way”, since it uses “Duck Typing” instead of hierarchy.

Nitro does not have any thing like “migrations”, at least I did not find it yet, and I really like Rails Migrations.

I found the source code for Nitro and Og easier to read and understand than the Rails code, but the code for the Rails applications is a lot cleaner and easier to read.

One thing that I found cool about nitro is that they use the explicit parameters for almost all methods, when rails use hashes for almost every thing, both approaches have advantages …

The example I wanted to write for this post will be published another time, because I need to study a little more about Nitro and Og to develop any thing that I’m not ashamed of publishing.

They do not follow a standard directory structure even in the sample applications, in some of them the code is in the source directory, in others it is in the app directory, the only standard is that the public things (style sheets, images, …) are in a directory called public.

For now, they (Nitro and Og) looks like they need more work, they stopped in time for a while, and the development restarted now with the “Rails Boom“.

Nitro has some cool things, but at least for now, I’ll use Rails for my projects (at least the ones that aren’t in Java) :D

Portuguese version Here.

If you enjoyed this post, make sure you subscribe to my RSS feed!

A very simple login example with Rails

This is just a little step by step on how to create a simple login with Rails, of course you can use a plugin to do it for you, but this way you can understand what the plugin is doing.

Let’s start creating a new Rails application:

$rails applicationName

Then we create a controller with a view for the login:

$script/generate controller login login

The code for the login_controller.rb will be the following:

class LoginController < ApplicationController
def index
render :action => 'login'
end
def login
end
def do_login
username = params[:username]
password = params[:password]
if username.nil? || password.nil? || username==password
redirect_to :action => "login"
flash[:notice] = 'Unknown user or invalid password'
else
session["user_id"] = username
redirect_to :controller => "secure", :action => "index"
end
end
end

Basically the controller has to implement only the do_login method, this is the one that will authenticate the user, in this example it only validates if the user filled the username and password fields, but later you can search the database for it.

The login view will have the following code:

<% form_tag :action => 'do_login' do %>
<table class="loginForm" align="center"><tbody>
<tr>
<td>Login</td>
<td><input name="username" type="text" /></td>
</tr>
<tr>
<td>Password</td>
<td><input name="password" type="password" /></td>
</tr>
<tr>
<td colspan="2"><%= submit_tag "Login" %></td>
</tr>
</tbody></table>
<table><% end %>

It is a simple view, with only two fields and since we do not have a user model I did not used the rails form helpers …

Ok, perfect until now, but how do I use it?

let’s change the application.rb file, the code will be the following:

class ApplicationController < ActionController::Base
# Pick a unique cookie name to distinguish our session data from others'
session :session_key => '_untitled6_session_id'
before_filter :authorize
protected
# Override in controller classes that should require authentication
def secure?
false
end
private
def authorize
if secure? &amp;&amp; session["user_id"].nil?
session["return_to"] = request.request_uri
redirect_to :controller => "login", :action => "login"
return false
end
end
end

The code above adds a before filter to every method of every controller in your application (since all controllers extends ApplicationController), this method will intercept the calls and if the controller is “secure” and the user did not authenticated yet, the user will be redirected to the login page, otherwise the filter will do nothing. To secure a controller you just need to override the “secure?” method and return true.

Now let’s create a simple controller that will need authentication …

$script/generate controller secure index

This line above creates a new controller with only an index action.

Now let’s edit the secure_controller.rb file

class SegureController < ApplicationController
def index
end
protected
def secure?
true
end
end

Overriding the “secure?” method to return true we tell the application that all actions in this controller need authentication.

But if we and only a few actions to need authentication? Than we can use some thing like the code bellow!

protected
def secure?
["secureMethod","anotherSecureMethod"].include?(action_name)
end

This way only the “secureMethod” and the “anotherSecureMethod” will need authentication.

Every thing ready, now we have a login implemented in a rails application …

Try starting the server (ruby script/server from the application’s directory) and access http://localhost:3000/secure and you will see the login screen instead of the index.rhtml contents.

Of course we can improve this example in many ways, for example:

  • in the method do_login we can use the session[”return_to”] to redirect the user to the first requested page.
  • We can create a users/groups structure and implement the authorization using that

And you, how would you improve the example above?

Do you see any problem in this example?

If you enjoyed this post, make sure you subscribe to my RSS feed!

What do you think about turning your Rails application into an executable?

As stated in the title: What do you think about turning your rails application into an executable? For example to show it to a client that has no environment (ruby, database) installed?

I just found that it is possible :D

To start we will need the following tools:

  • Tar2RubyScript - this is a tool that turns your entire ruby application into only one .rb file.
  • RubyScript2Exe - this is a tool that turns one ruby script into an executable (no cross compiling yet, if you use linux you can only create linux executables, if you use windows just windows executables), with a great advantage, it includes the interpreter and all the libraries your application need, and filters only the used core classes.

Let’s install them:

$sudo gem install tar2rubyscript
$sudo gem install rubyscript2exe

Now let’s create a Ruby On Rails application, and as we want to carry everything with us, we will use the SQLite3 database (that way the client does not need to have a database server).

Creating the application

$rails demo
$cd demo
$ruby script/server

Now test the application pointing your browser to the address: http://localhost:3000/.

Creating the database

$irb

irb(main):005:0> require 'sqlite3'
irb(main):006:0> SQLite3::Database.new("demo_dev.db").execute(
irb(main):007:1* "create table books (id integer primary key,
irb(main):008:1"                      title varchar(255),
irb(main):009:1"                       author varchar(255));")

And now we copy the database to the production and test environments:

$cp demo_dev.db demo_test.db
$cp demo_dev.db demo_prod.db

Developing the Rails application

$vi config/database.yml

Replace the content of this file with something like this:

development:
  adapter: sqlite3
  database: demo_dev.db
test:
  adapter: sqlite3
  database: demo_tst.db

production:
  adapter: sqlite3
  database: demo_prd.db

Let’s create the model and the controller:

$script/generate model Book
$script/generate controller Book
$vim app/controllers/book_controller.rb

And now lets change the controller code to something like this:

class BookController < ApplicationController
scaffold :book
end
$script/server

Now try this address in your browser to make sure it is working http://localhost:3000/book.

Creating the Ruby Archive

Now the real tip (Now talking serious, even my cat knows how to create a CRUD with scaffold :D )

The Tar2RubyScript command creates a package for the application, but when it is executed , it unpacks every thing in a temporary directory and after the execution it cleans the temporary directory again. This is not exactly the behavior we wait for a database, so let’s move the database to a secure place before the execution…

$vi config.environment.rb

Let’s add the following code to the begining o the file:

module Rails
  class Configuration
    def database_configuration
      conf = YAML::load(ERB.new(IO.read(database_configuration_file)).result)
      if defined?(TAR2RUBYSCRIPT)
        conf.each do |k, v|
          if v["adapter"] =~ /^sqlite3/
            v["database"] = oldlocation(v["database"]) if v.include?("database")
            v["dbfile"]   = oldlocation(v["dbfile"])   if v.include?("dbfile")
          end
        end
      end
      conf
    end
  end
end

It will change the way Rails looks for the database, it originally was this way:

module Rails
  class Configuration
    def database_configuration
      YAML::load(ERB.new(IO.read(database_configuration_file)).result)
    end
  end
end

What exactly we did? When a RBA (Ruby Archive) is executed, it needs to handle two diferent directories, the one where the application is running (temp directory) and the one where the application really is, referenced by “oldlocation”. The presented code changed the configuration inside the database.yml file, pointing the databases to the full path to the database files (where the application really is), this way we do not loose the data after the end of the application.

The Tar2RubScript needs a file called init.rb, what will be the entry point to the application, so let’s create it with the following code:

$vi init.rb

at_exit do
  require "irb"
  require "drb/acl"
  require "sqlite3"
end

load "script/server"

The ‘require’ in the beginning are there just to make the script’s work a little easier, and the load “script/server” will start the Rails server (WEbrick or mongrel depending on your environment).

Now lets create the application package:

$cd ..
$tar2rubyscript demo
$cp demo/demo_* .

Almost ready, now we can test our Ruby Archive with the following command:

$ruby demo.rb

And again, test your application with the following URL: http://localhost:3000/book

Creating an executable to carry with you in your flash drive (outside Brazil it is called pendrive too?)

Creating the executable is very simple, you just need to run this command line:

$rubyscript2exe demo.rb

After the rails application starts up, navigate a little within your application and then press CTRL+C, it will create a file names demo.exe, or demo_linux if you are running a linux box like me.

Now just copy the generated file and the database file to your flash drive and run it on your friends computer of your client meeting to make some money :D

Conclusions

When you get in the meeting you do not need to install Ruby, RubyGems, Rails, and other Gems, …

Just an executable file and some database files and you are ready to demo your application to clients and friends :D

What do you want better than that?

Talking the truth, I still want the possibility to create windows executables into my Linux box, but it still a very good solution :D

If you enjoyed this post, make sure you subscribe to my RSS feed!