Sunday, October 24, 2010

AAdmin - Flex on Rails Agile Admin Application

The AAdmin is a little project I'm developing on the side, for Valueshine which in essence is a fast Administration Application based on a Ruby on Rails back-end and a Flex Web front-end.

I love fast development mainly because I'm a lazy son of a batch file and for some reason, I feel that Ruby and Rails was made just for people like me.

Having a server side application that 70% of its tasks sum up to persistence functionality just screamed scaffolding to me. the only obvious difference is that for the sake of using a flex client, i would have to skip over the default view machinery, that are generated by the rails scaffold.

Pre Programming:
I've created the alternative controller template so scaffolding command would generate an XML based web service.
to match that I've written an ActionScript client side that talks CRUD on the one side and hands out a set of a-sync methods on the other side.

The application, is based on the two elements described above, let me have a RoR restful web services that would accommodate a rich client.

The server:
I have employed a standard scaffold script generation with a tweak to the controller template. this change bypasses the standard view that is created by Rails to relay on pure XML rendering.
there is one extra controller that is utilized for configuration data purpose. I use it for authentication, and to extract the entities structure xml file.

The Client:
This part is where the quick admin app comes to play. the AAdmin client enables all CRUD functionality on a list of entities, predefined in an entity xml.
the client logs in, extracts the entity xml file, and presents the table structure and functionality according to the definitional in the file.

Screen shoots:
AAdmin Login Screen.

The CRUD Data View

The Create and Edit screen















Resources:

Wednesday, October 20, 2010

Flex for Rails Scaffolding (cont) - the controller template

I've made a little improvement  to my development process, in such a way that the scaffolding i do for creating the web services I later use for my flex client are generated in their final form without the need to adjust them.
What i did was make some changes to the controller scaffold template.
The controller.rb template file is located at: [Ruby Home]\lib\ruby\gems\1.8\gems\rails-2.3.4\lib\rails_generator\generators\components\scaffold\templates

Backup the original (or pick it up from here).
Download the modified template


The Template should end up looking like:

class <%= controller_class_name %>Controller < ApplicationController
  # GET /<%= table_name %>
  # GET /<%= table_name %>.xml
  def index
    @<%= file_name %> = <%= class_name %>.all
   render :xml => @<%= file_name %>
  end

  # GET /<%= table_name %>/1
  # GET /<%= table_name %>/1.xml
  def show
    @<%= file_name %> = <%= class_name %>.find(params[:id])
    render :xml => @<%= file_name %>
  end

  # GET /<%= table_name %>/new
  # GET /<%= table_name %>/new.xml
  def new
   @<%= file_name %> = <%= class_name %>.new
   render :xml => @<%= file_name %>
  end

  # GET /<%= table_name %>/1/edit
  def edit
    @<%= file_name %> = <%= class_name %>.find(params[:id])
   render :xml => @<%= file_name %>
  end

  # POST /<%= table_name %>
  # POST /<%= table_name %>.xml
  def create
    @<%= file_name %> = <%= class_name %>.new(params[:<%= file_name %>])
    if @<%= file_name %>.save
      render :xml => {:notice => '<%= class_name %> was successfully created.'}
    else
      render :xml => {:notice => @<%= file_name %>.errors}
    end
  end

  # PUT /<%= table_name %>/1
  # PUT /<%= table_name %>/1.xml
  def update
    @<%= file_name %> = <%= class_name %>.find(params[:id])

    if <%= file_name %>.update_attributes(params[:<%= file_name %>])
      render :xml => {:notice => '<%= class_name %> was successfully updated.'}
    else
      render :xml => {:notice => @<%= file_name %>.errors}
    end
  end

  # DELETE /<%= table_name %>/1
  # DELETE /<%= table_name %>/1.xml
  def destroy
    @<%= file_name %> = <%= class_name %>.find(params[:id])
    @<%= file_name %>.destroy

    render :xml => {:notice => '<%= class_name %> was successfully deleted.'}
  end
end

Friday, September 24, 2010

Flex For Rails Scaffold

I’ve written a little component for connecting flex with rails scaffold as close as possible.

Step 1: Create a scaffold for Card

Within your rails application run the script:
./script/generate scaffold card id:integer timeStamp:timestamp data:text

(data types with Ruby and mySQL)


Step 2: Change the Card controller


Edit the Card Controller found at: myApp/app/controllers/cards_controller.rb and remove all view elements. this will make the controller omit pure XML structures


should result with the controller looking like:


class CardsController < ApplicationController
  # GET /cards
  # GET /cards.xml
  def index
    @cards = Card.all
    render :xml => @cards
  end

  # GET /cards/1
  # GET /cards/1.xml
  def show
    @card = Card.find(params[:id])
    render :xml => @card
  end


  # GET /cards/new
  # GET /cards/new.xml
  def new
    @card = Card.new
    render :xml => @card
  end


  # GET /cards/1/edit
  def edit
    @card = Card.find(params[:id])
    render :xml => @card
  end


  # POST /cards
  # POST /cards.xml
  def create
    @card = Card.new(params[:card])
    if @card.save
      render :xml => {:notice => 'Card was successfully updated.'}
    else
      render :xml => {:notice => @card.errors}
    end

  end


  # PUT /cards/1
  # PUT /cards/1.xml
  def update
    @card = Card.find(params[:id])

    if @card.update_attributes(params[:card])
      render :xml => {:notice => 'Card was successfully updated.'}
    else
      render :xml => {:notice => @card.errors}
    end

  end


  # DELETE /cards/1
  # DELETE /cards/1.xml
  def destroy
    @card = Card.find(params[:id])
    @card.destroy
    render :xml => {:notice => 'Card was successfully updated.'}

  end
end


Step 3: Client Side


To connect to the Rails server use an intermediate adapter called ActiveResourceClient.as

For testing, use the ServiceTester.mxml


good luck

Monday, September 13, 2010

Passing a Byte Array through JSON

Its a well known issue when communicating complex structures between client and server, using the JSON encoding.
I've encountered it when attempting to transfer an encrypted Byte Array back and forth between a client and server, that communicate via JSON.

What doesn't work:
Base64 encodings and conversions to string formats

What does work:
Converting the Byte[] to a number array and back

Here is an example code in Flex (works just as well in Java / PHP / Python etc)






















Independent on Sundays

Saturday, August 14, 2010

Flex List Item Renderer Repetition

The Flex implementation of lists, data grids, and advanced data grids generate a fixed amount of item renderer components that usually match the first visible set of elements in the list.
This implementation might cause that elements in the list seem to repeat them selves once you scroll down.

This is because although the items data is different, since its display object hasn't been properly refreshed, it shows the data it has from its previous appearance.
To solve this follow these guidelines:
1. do not set data inline i.e. mx:label text="{data.text}"
2. implement the renderers updateDisplayList method to set all the data in place

that's it,
good luck

Thursday, April 1, 2010

Flex Directory Compression

Here is an example for compression and decompression of files and directories using the DEFLATE compression algorithm. 

The structure I have created for the file structure in the compressed file is arbitrary.  for each file it describes the name and data witch is a byte array of the file content. Directories do not have a data attribute, but children that recursively describe files with in.  


Download the source code here

Download the example AIR application here

 
When running the example, drag and drop a file or directory into the upper box, this will catch the link and create a compressed version of the file in the application storage directory (i.e. /AppData/Roaming/Deflator/Local Store)

To extract the file back, click on the compressed file in the list and click the extract button. This will recreate the file or directory on your desktop.




Please note: that if the original file is still on the desktop when you extract, you will have an error. so if you deflated something from the desktop, make sure you rename it before you extract

Good luck.