ActiveScaffold and Unobtrusive Javascript

2 Comments

Rails 3.0 started using unobtrusive javascript. However, what does that actually mean for activescaffold? Well, basically it means that there should nt be any javascript code in our partials. Looks easy at the first glance, however, if you start actually to implement it..
Big advances of unobtrusive javascript are:

  • application works without javascript
  • html code seperated from javascript code
  • html id attribute is nt needed anymore for many operations

I ve mentioned at the beginning that going unobtrusive is nt that easy as it seems. The big issues you have are:

  • How to cleanly separate javascript code?
  • How may application work if javascript is disabled?
  • It s easy to manage click events, unobtrusively, but how to manage load events for ajax calls?

In this post I will focus on the last bullet point. It took a while until I was able to manage that issue.
Unobtrusive javascript needs a trigger event to add the javascript functionality. For example when you click a button. However, if you would like to add javascript functionality on load you are in kind of trouble for ajax applications, because load events of browsers do only fire if the whole page is loaded and not if snippets of html code are changed or added during an ajax call.

I ve solved that issue at least for activescaffold as follows.

ActiveScaffold will trigger the following events in case of page load and ajax load:

  • as:list_row_loaded
  • as:form_loaded
  • as:form_element_loaded

ActiveScaffold will trigger the following events in case of page unload and ajax unload:

  • as:list_row_unloaded
  • as:form_unloaded
  • as:form_element_unloaded

A simple use case would be the following: list columns may be configured for inplace editing, which is a pure javascript feature including the need to add it to the specified columns during as:list_row_load event:

$('tr.record').live('as:list_row_loaded', function(event) {
  $(this).closest("tr").find('td > span.in_place_editor_field').each(function(index) {
    ActiveScaffold.create_inplace_editor($(this));
  });
  return true;
});

In my next post I will show you how I ve migrated the tiny_mce bridge to unobtrusive javascript.

Hope you will benefit from this new javascript events, cause it will make the step to unobtrusive javascript a lot easier using activescaffold.

ActiveScaffold: Single Table Inheritance (STI)

6 Comments

Today, I would like to show you an improved way to manage Single Table Inheritance with ActiveScaffold. It s a real time safer.
STI Models should hopefully have a big overlap of attributes, which is the base assumption for my implementation of STI in ActiveScaffold.

Basically, we will show an index view of parent sti controller, in which member actions such as edit, show,delete are linking to corresponding specific sti controller. Create link opens a popup menu showing the different sti models.

That s the concept let s try it out. I will use an example from the book: “Agile Web Development with Rails” written by Dave Thomas and David Heinemeier Hansson.
That example consist of the following models:

  1. Person (sti_parent)
  2. Customer
  3. Employee (Parent of Manager)
  4. Manager

It s quite tedious to set up an application with these models, therefore we will shorten that process.

Setup Example Application

  1. Download: one_step_active_scaffold
  2. Download: sti_blog.rb and rename it to model_setup.rb
  3. Execute following command: ruby one_step_activescaffold.rb sti jquery

Great, we ve prepared our example application, now we have to configure our controllers

Controller Inheritance

ActiveScaffold configuration can be inherited, which is quite useful for sti, because many columns are shared.

class CustomersController < PeopleController
class EmployeesController < PeopleController
class ManagersController < EmployeesController

Definition of column set for each Controller

We have to define for each controller, which columns we would like to use. Please note that we do not have to define anything specific for manager controller because it should use same settings as employee controller.

class PeopleController < ApplicationController
  active_scaffold :person do |conf|
    conf.columns = [:type, :name, :email]
  end
end 
class CustomersController < PeopleController
  active_scaffold :customer do |conf|
    conf.columns = [:type, :name, :email, :balance]
    conf.update.columns = [:name, :email, :balance]
    conf.create.columns = [:name, :email, :balance]
  end
end
class EmployeesController < PeopleController
  active_scaffold :employee do |conf|
     conf.columns = [:type, :name, :email, :boss, :department]
     conf.update.columns = [:name, :email, :boss, :department]
     conf.create.columns = [:name, :email, :boss, :department]
  end
end 

Parent Controller STI Child Models

One last step, we have to tell the parent controller, which sti_models he should be able to manage.

class PeopleController < ApplicationController
  active_scaffold :person do |conf|
    ....
    conf.sti_children = [:employee, :customer, :manager]
    ....
  end

Our Application is ready, start the server and go to: localhost:3000/people.

Hopefully, you will benefit as much as I did.

ActiveScaffold and RecordSelect

8 Comments

Today, I would like to show how you my integeate recordselect into activescaffold for rails3.
I will use my players/team example as usual.
My example will show you how to use :record_select instead of :select for team association in players controller.

Let s start by adding recordselect to our application

rails plugin install https://github.com/vhochstein/recordselect.git 

Adding recordselect includes to application layout

<%= active_scaffold_includes %>
<%= record_select_includes %> 

Enabling recordselect in teams_controller

teams_controller.rb 

  class TeamsController < ApplicationController 
    record_select :per_page => 3, :search_on => [:name], : order_by => 'name' 
    ...

Adding recordselect routes for teams_controller

routes.rb 

  resources :teams do 
    as_routes
    record_select_routes 
  end 

Changing form_ui to :record_select for team column

players_controller.rb 

  active_scaffold :player do |conf| 
    conf.columns[:team].form_ui = :record_select
    ...

Restart your application and you should be able to choose a team for a player using record_select.

One Step rails app with activescaffold installation

5 Comments

At the beginning I thought, great my process described in my post how to setup activescaffold with rails 3 is quite easy and only consists of a view steps. Unfortunetly, I had to realize that even these few steps are too many if you have to do that frequently.

Therefore I ve tried to further reduce steps it takes to install my little howto application. I ve managed to get it down to one step (if you do not count downloading a ruby script :-))

That s a real time safer for me and will be for you if you are following my posts and try these things out. In addition it can be used to install any new activescaffold enabled rails 3 app.

You may find that install script at the following location: One Step Activescaffold

If you want to try it out just download the following file: https://github.com/vhochstein/one_step_active_scaffold/raw/master/one_step_activescaffold.rb and run it on your computer without any options.

At the end you are a proud creator of my little how-to application. you just have to call ‘rails s’ to start the application.

If you like it you can use it even for your own apps. This little script takes several arguments, these empower you to set application name, js_library, your preferred database system and db user and password.
If you would like to create your own models instead of my player and team ones… Sure no problem. You just have to create a special file in the same directory which includes the required commands to create these models.

Let’s take a look at some examples:

ruby one_step_activescaffold_app.rb

That s the default, which creates my little how-to.

ruby one_step_activescaffold_app.rb my_new_app jquery mysql

Creates my little how-to with the name ‘my_new_app’ using mysql and jquery.

ruby one_step_activescaffold_app.rb my_new_app jquery postgres john top_secret

Same as before, but using postgres and db_user is ‘john’ and password is ‘top_secret’

model_setup.rb:
puts %x[rails g active_scaffold coach name:string]

ruby one_step_activescaffold_app.rb

Creates my little how-to, but instead of creating team and player model, we create a coach model.