Wednesday, April 29, 2009

ActiveJquery - Status

Current Things That Are Working:

Controller/Server
1. Can read full table
2. Can read using JqGrid Pager
3. Added Sort support, so server will honor the grid sort request
4. Added Delete,Add and Update support.
5. Auto Generates JqGrid Javascript from ActiveRecord
6 Added Total Records to XML so Pager works properly.

ActiveJquery Library/Client
1. Added support for string, integer, date.
2. Generates JSON Based Reader compatible with Rails JSON Format
3. Uses Humanize to handle automatic column names.
4. Uses JqueryUI for theming
5. InLine Edit Support

Things to Do:
1. Paste Controller code into prepared plugin
2. Add static data support
3. Add a bit of DSL(Domain Specific Language) to allow easy configuration
4. Add Master/Detail Support
5. Add Date Picker Plugin
6. Add Parent Table Dynamic Data Selector

ActiveJquery - Features

ActiveJquery is a Rails Plugin that combines the goodness of Jquery, Jquery UI, and JqGrid.






































FeatureDescription
RESTActiveJquery breaks your GUI into a javascript REST Client, and a Rails based REST JSON Server. This reduces
the overhead of our web app, and gives you better expandability, and better response time
DRYTired of repeating yourself, dont. ActiveJquery will find your Field Name, and configure the Grid for you.
CustomizableYou can configure grids in countless ways, allowing you easy control over what you want to see.
MultiGridNeed a butch of grids on one page? Not a problem. You can have any number of grids in one page. Each is named automatically for you.
Master/DetailYou Rails Associations are used to generate sub-grids or master-detail views of your data.
ThemingActiveJquery uses Jquery UI themes, so you can easily customize the look and color scheme of the grid
Menu's/TabsWant to have a easy to use menu system. ActiveJquery supports JqueryUI tabs, so you can do complex, but
easy to use apps.
Dynamic DataBy default data is read a screenful at a time, using the grid pager. This reduces the need to read large amounts of a big table. Also makes loading multiple grids very fast.
Static DataActiveJavascript can embed the table data directly in the javascript. This is great for tables that 1000 rows or less, and are read-only.

Jdgrid Pager Problem



Trying out the latest versions of jquery/jquery ui/jqgrid, and just cannot get the formatting right.

Lets see if we can figure out whats going on.

The html for the grid:
<html>
<head>
<title> Airstate </title>
</head>
<body>
<h2> Airstate </h2>
<script src="javascripts/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="javascripts/jquery-ui-1.7.1.custom.min.js" type="text/javascript"></script>
<script src="javascripts/jquery.layout.js" text="text/javascript"></script>
<script src="javascripts/jqModal.js" type="text/javascript"></script>
<script src="javascripts/jqDnR.js" type="text/javascript"></script>
<script src="javascripts/jquery.jqGrid.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" media="screen" href="themes/redmond/jquery-ui-1.7.1.custom.css" />
<link rel="stylesheet" type="text/css" media="screen" href="themes/ui.jqgrid.css" />
<style>
html, body {
margin: 0; /* Remove body margin/padding */
padding: 0;
overflow: hidden; /* Remove scroll bars on browser window */
font-size: 75%;
}
/*Splitter style */


#LeftPane {
/* optional, initial splitbar position */
overflow: auto;
}
/*
* Right-side element of the splitter.
*/

#RightPane {
padding: 2px;
overflow: auto;
}
.ui-tabs-nav li {position: relative;}
.ui-tabs-selected a span {padding-right: 10px;}
.ui-tabs-close {display: none;position: absolute;top: 3px;right: 0px;z-index: 800;width: 16px;height: 14px;font-size: 10px; font-style: normal;cursor: pointer;}
.ui-tabs-selected .ui-tabs-close {display: block;}
.ui-layout-west .ui-jqgrid tr.jqgrow td { border-bottom: 0px none;}
.ui-datepicker {z-index:1200;}
</style>

<script type="text/javascript">
var listlastsel;jQuery(document).ready(function(){
jQuery("#list").jqGrid({
url:'airstate.xml',
editurl:'airstate',
datatype: 'xml',
mtype: 'GET',
colNames:['Id','Created on','Whom','Logmessage'],
colModel :[
{name: 'id',index:'id',key:true,width:80,align:'right'},
{name: 'created_on',index:'created_on',key:false,width:90},
{name: 'whom',index:'whom',key:false,width:300,align:'left',editable:true},
{name: 'logmessage',index:'logmessage',key:false,width:300,align:'left',editable:true}],
pager: jQuery('#list-pager'),
onSelectRow: function(id){
if(id && id!==listlastsel){
jQuery('#list').restoreRow(listlastsel);
jQuery('#list').editRow(id,true);
listlastsel=id;
}
},
autowidth: true,
rowNum:10,
rowList:[10,20,30],
sortname: 'id',
sortorder: "desc",
viewrecords: true,
imgpath: 'themes/basic/images',
caption: 'Airstate',
xmlReader: {root: "root",
row: "syslog",
page:"root>page",
total:"root>total",
records:"root>records",
repeatitems:false
},
});
jQuery("#list").navGrid('#list-pager',{ edit:true,add:true,del:true,search:true });
});
</script>
<div id="list-pager" class="scroll"></div>
<table id="list" class="scroll"></table>

</body>
</html>


Now lets see if we can figure out whats going on.

Ok, Great support from jdquery. Seems like its a a bug in the latest v2 alfa test.
Alfa 3 should solve the problem.

Tuesday, April 07, 2009

Getting only the columns you want in Rails

A thing that is often missed when your doing a web service or a rails app is selecting only
the columns you need.

A traditional find:

user = User.find :all
render :xml => user.to_xml

Will give you the bloat of the whole user table.
If you only hae a few small columns then thats not so bad,
but I've seen legacy apps that have very large number of columns,
so it makes since then to control this better.

user = User.find(:all, :select = 'email')
render :xml => user

This also will make your resulting xml file alot more managable.
And since bandwidth is not free, it will help you handle more users
for less money.

Network Monitor as a Windows Service in Ruby

In reading thru the Ruby Google Group, there seems to be a lot of misconceptions about what should be done inside
of a Rails process and what should be done outside it. Generally if it take any time at all, you should be it outside
the Rails Web Server. In windows you can do a Windows Service, in Linux/Unix you would do a daemon.

This is a example of a windows service that scans cisco switches, finds new nodes, and keep track of there mac
address and there port. Even builds a network map.

The app consists of a Rails app to display the data, and take in configuration information. Which is put in a database,
such as sqlite3, and updated by this Windows Service.

As long as the Service is running, the data will be updated. If I was doing it again, I'd use rufus-scheduler to
wrap the scanning and the mapping.



require 'rubygems'
require 'win32/daemon'
include Win32
require 'logger'
require 'win32/process'
require 'net/ping'
#Note that most of your requires need to go in the service init

class IPAddr
def succ()
return self.clone.set(@addr + 1)
end
end

class AirstateDiscovery

def doscan()
ProcessNetworks()
ProcessDiscovery()
return
end


def ProcessDiscovery()
Mac.find(:all).each do |mymac|
mydevice = mymac.device
if mydevice
mynet = Network.find_network_by_ip(mymac.ip)
if mynet #Ok we have a valid network
Device.find_device_type(mymac.ip,mydevice)
end
end
end
end


def ProcessSwitches()
Switch.find(:all).each do |myswitch|
if myswitch.enabled
if myswitch.switch_type == "cisco"
cisco = CiscoSwitch.new(myswitch)
#begin
cisco.update_macs()
#rescue
# end # Rescue
cisco = nil
end #if myswitch.switch_type == "cisco"
end # myswitch.enabled
thegraph = SwitchGraph.new(myswitch)
thegraph.graph()
thegraph = nil
end # find do
end

def ProcessNetworks()
ProcessSwitches()
return

# Brute Force Scan
Network.find(:all).each do |mynet|
ProcessSwitches() # Networks is "long" running, Switch is "fast"
if mynet.enable
startip = mynet.ip_start
endip = mynet.ip_end
ip = IPAddr.new(startip)
while ip.to_s != endip
ProcessWmi(mynet,ip.to_s)
ip = ip.succ()
end
end
end
end # def Process Networks

end # class AirStateDiscovery

class Daemon
def service_init
end

def service_main

require 'ipaddr'
Dir.chdir("\\projects\\airstate")
require File.dirname(__FILE__) + '/../config/environment.rb'
require 'lib/cisco_phone'
require 'lib/managepc'
require 'lib/switchgraph'
@mywork = AirstateDiscovery.new
mylog = Syslog.new
mylog.whom = "AirStateDiscovery"
mylog.logmessage = "Discovery Starting"
mylog.save
while running?
@mywork.doscan()
sleep 3
end
end
end


# Test Code
# require 'ipaddr'
# Dir.chdir("\\projects\\airstate")
# require File.dirname(__FILE__) + '/../config/environment.rb'
# require 'lib/managepc'
# require 'lib/cisco'
# require 'lib/switchgraph'
# require 'lib/cisco_phone'
# @mywork = AirstateDiscovery.new
# while 1
# @mywork.doscan()
# end
# exit

Daemon.mainloop

Sunday, April 05, 2009

Rails - Useful Plugins

In updating myself I found some really useful Rals plugins for my next project.

Hoptoad Notifier
A Rails app is a very dynamic thing. Finding out when your users have errors, and what the pattern of errors is a must have. The traditional approach is to view the log files from time to time, or use a notifier that sends the errors to your email. Then go thru it as they come in. First, it not uncommon for a error to repeat. So you get log of junk in your email. A better approach is to use the hoptoad service/plugin. This way, you get nice reporting and analysis, and for a single project, its free. It consists of a hosted site web gui, and a rails plugin, and a optional local mac gui to show your croak's, ie the errors in your apps.

http://www.hoptoadapp.com/welcome
http://blog.railsrumble.com/2008/10/6/hoptoad
http://github.com/thoughtbot/hoptoad_notifier/tree/master
http://github.com/bricooke/croak-app/tree/master

Simple Ruby Rest Client
REST is a lovely way of doing Remote Procedure Calls. It the rails way of creating web services. Sometime its handy to have a simple REST-client.
There is a simple to Rest client done by Adam Wiggins

http://github.com/adamwiggins/rest-client/tree/master
http://rest-client.heroku.com/rdoc/

Now you can call a REST api even from IRC or rails console