Graphs with Gruff (followup)

Posted by Daniel Wanja Fri, 14 Apr 2006 06:49:00 GMT

The solution from the source ;-) I checked it out and it now works as advertised, just add g.minimum_value = 0 to the Gruff::Bar before rendering it (g.to_blob).

Note that axis starting at zero.

Without the minimum_value With the minimum_value set to zero

LAUNCH time.onrails.org, time tracking made simple! 2

Posted by Daniel Wanja Thu, 13 Apr 2006 20:41:00 GMT

We call it time.onrails.org. It’s a new FREE online time tracking product for the consultant and programmer that bills by the hour or works on multiple projects.

We (Lee and I) have been using it for awhile now to track our Rails consulting work. It’s really the fastest way to count your hours across multiple projects. And we tried many of the solutions out there.

See time.onrails.org for an overview or go straight to signup and be up and running in 5 seconds.

Let us know what you think at time@onrails.org.

Enjoy! Daniel

CSS Transparent Rollovers 3

Posted by Daniel Wanja Mon, 10 Apr 2006 20:31:00 GMT

I was trying to implement some rollover effects when I stumbled over this article at mandarindesign. I wrapped this functionality in the helper here after

The css
1
2
3
4
5
6
<style type="text/css">
<!--
div.transOFF {width: 100%; background-color: silver; border:1px solid black;}
div.transON  {width: 100%; background-color: silver;opacity:.50;filter: alpha(opacity=50); -moz-opacity: 0.5; }
-->
</style>
The rhtml template
1
2
3
4
5
6
7
8
9
10
11
12
13
<table width="200" border="0" style="border:1px solid black;">
  <tr>
    <td>Project</td>
    <td>Dashboard</td>
    <td>Charts</td>
  </tr>
  <tr>
    <td><%= rollover_image('/images/index/project_icon.png', true) %></td> 
    <td><%= rollover_image('/images/index/dashboard_icon.png') %></td> 
    <td><%= rollover_image('/images/index/graph_icon.png') %></td> 
  </tr>
</table>
The Helper
1
2
3
4
5
6
7
8
  def rollover_image(src, over=false)
    transON, transOFF  =  over ? ['transOFF', 'transON'] : ['transON', 'transOFF']
    content_tag "div", 
                image_tag(src, :onmouseover => "this.className='#{transOFF}'", :onmouseout => "this.className='#{transON}'" ), 
                :class => transON, 
                :onmouseover => "this.className='#{transOFF}'",
                :onmouseout => "this.className='#{transON}'"  
  end
Project Dashboard Charts
Project_icon
Dashboard_icon
Graph_icon

Managing Rails Plugins dependencies 1

Posted by Daniel Wanja Sat, 04 Mar 2006 09:26:00 GMT

Rails has a nice plugin system allowing to add common code to a project. A plugin should really be independent from any other plugins. But we also use plugins to share code among different projects we are working on and our code depends on existing plugins. The Rails development team want’s to keep the plugin system simple and didn’t provide an explicit way to handle these dependencies, which I believe is a good decision. There is a solution. Simply name the plugins in order off the dependencies you have. Let’s assume you want to add “my_very_own_plugin” plugin that depends on the enumation_mixin, then simply organize the /vendor/plugins folder as follows, et Voila!:.

/myrailsapp
    /vendor
        /plugins
            /01_acts_as_taggable
            /01_enumations_mixin 
            /01_acts_as_versioned
            /02_my_very_own_plugin

If we look at the Rails::Initializer we can see why this works. Note, this is only an extract of the full class that Rails provides to bootstrap your rails applicaton. The sort on line 4 here after allows this trick.

1
2
3
4
5
6
7
8
module Rails
  class Initializer
    def load_plugins
      find_plugins(configuration.plugin_paths).sort.each { |path| load_plugin path }
      $LOAD_PATH.uniq!
    end
  end
end

A source code browser 1

Posted by Daniel Wanja Mon, 20 Feb 2006 21:55:00 GMT

Browse::Source is a simple source code browsing application. It’s 100% based on Collaboa, it’s mostly the source code browser functionality but uses the file system rather than connecting to subversion.

I recently got a request from Justin to have access to some ‘old’ rails code (flexonrails) we wrote a while ago, and also Todd asked for the source code of autumnriders. So I tried Collaboa but it requires to compile subversion from the source in order to have swig-rb. So I extracted the source code browser from Collaboa and removed the dependency on swig-rb. Now if all you need is to add simple source code browsing…then Browse::Source is what you need.

Well, we haven’t posted yet the two code bases mentionned above, but have a look at the source code browser source code Browse::Source

Graphs with Gruff 4

Posted by Daniel Wanja Mon, 20 Feb 2006 12:10:00 GMT

class GraphController < BaseTimeController
   def pages
      g = Gruff::Pie.new("500x350")
      g.title = "All Pages" 
      @current_user.pages.each do |page|
        g.data(page.title, [page.total]) 
      end
      send_data(g.to_blob, 
                :disposition => 'inline', 
                :type => 'image/png', 
                :filename => "timers.png")
    end
end
Pretty easy! Wasn’t it. Note the code above shows only the first of the graphs. Now if only I could find out how to set the minimum of the Bar chart to 0 instead of the minimum of the serie. Any help is appreciated?

Auto-login 29

Posted by Daniel Wanja Sat, 18 Feb 2006 13:41:00 GMT

One of my midnight Rails projects is a “time tracking” application for which I needed auto-login. You know, the “Remember me” check box so that you don’t have to login each time you visit the application. I found a nice article written by Matt McCray describing how this was implemented for TaskThis.com at http://www.mattmccray.com/archives/category/software/rails/taskthis/. Even further he provides the full source code for the application. I didn’t take directly his auto_login.rb module but was greatly inspired by it. I also used the Login Engine Plugin that was not providing this feature, maybe this changed, so it could be simpler, but how simple implementing the auto-login can be. Note these are not the full classes just pertinent code extracts.

1. Remember me

When the user login and checks the “Remember me” checkbox, the :save_login parameter is set, the User instance remember_me method invoked and the :auth_token cookie set.

class AccountController < ApplicationController
  def login
    case @request.method
      when :post
      if @session[:user] = User.authenticate(@params[:user_login], @params[:user_password])
        flash['notice']  = "Login successful"
        if @params[:save_login] == "1"
          @session[:user].remember_me
          cookies[:auth_token] = { :value => @session[:user].remember_token , :expires => @session[:user].remember_token_expires }
        end
        redirect_back_or_default :controller => "time"
      else
        flash.now['notice']  = "Login unsuccessful"
        @login = @params[:user_login]
      end
    end
  end

  def logout
    @session[:user].forget_me if @session[:user]
    @session[:user] = nil
    cookies.delete :auth_token
  end
end

2. login_from_cookie

The next time the user visits the website the “login_from_cookie” filter is triggered. This method checks that the user is not logged in and that the :auth_token cookie is set. If that’s the case the user matching the :auth_token is searched and the token_expiration verified the the user is automatically logged in. Et voila! I guess auto_login would be more appropriate as method name.

class ApplicationController < ActionController::Base
   before_filter :login_from_cookie
   def login_from_cookie
      return unless cookies[:auth_token] && @session[:user].nil?
      user = User.find_by_remember_token(cookies[:auth_token]) 
      if user && !user.remember_token_expires.nil? && Time.now < user.remember_token_expires 
         @session[:user] = user
      end
   end
end

3. the User class

The User class has two methods to set and remove the token from the database. It’s pretty secure as from the token the user cannot be identified without having the salt, the email, and the token expiration, which is most unlikely to be recreated. It could be even more secure by just encrypting some random unique identifier. The only issue I encountered was that the user class always forces the password validation and encryption when saving. For now I just bypass validation and encryption when setting and clearing the remember_me token.

class User < ActiveRecord::Base
  def remember_me
    self.remember_token_expires = 2.weeks.from_now
    self.remember_token = Digest::SHA1.hexdigest("#{salt}--#{self.email}--#{self.remember_token_expires}")
    self.password = ""  # This bypasses password encryption, thus leaving password intact
    self.save_with_validation(false)
  end

  def forget_me
    self.remember_token_expires = nil
    self.remember_token = nil
    self.password = ""  # This bypasses password encryption, thus leaving password intact
    self.save_with_validation(false)
  end
end

inline RJS 2

Posted by Daniel Wanja Fri, 20 Jan 2006 19:04:00 GMT

In my previous article I was playing with RJS templates and finding easy way to generate them. Well Thomas just posted some new goodies see http://mir.aculo.us/articles/2006/01/21/new-inline-rjs-for-rails. For quick updates no need to have a separte .rjs file.

class UserController < ApplicationController 
  def refresh 
    render :update do |page| 
      page.replace_html('user_list', 
        :partial => 'user', :collection => @users) 
      page.visual_effect :highlight, 'user_list' 
    end 
  end 
end

.rjs and link_to_function 3

Posted by Daniel Wanja Thu, 12 Jan 2006 05:57:00 GMT

A neat little trick is that .rjs templates can be used to generate local javascript functions and be invoked without doing a server roundtrip.

playground_controller.rb
class PlaygroundController < ApplicationController
  def rjs
     response.headers['content-type'] = 'text/html'
  end
end
rjs.rhtml
<html>
<head>
  <%= javascript_include_tag :defaults %>    
</head>
<body>
<h1 id='header'>Javascript function test</h1>

<%= link_to_function('Add', 'add_item()' ) -%> | 
<%= link_to_function('Clear', 'clear_list()') %>
    <ul id='list' />
<script type='text/javascript'>
  <%= render :partial => 'functions', :type => 'rjs' %>
</script>
    <script type='text/javascript'>
    <%= # Note: following javascript is run when the page is loaded.
        update_page do |page|
            3.times { page.call 'add_item' }
        end
    %>
    </script>    
</body>
</html>

The rjs method in the PlaygroundController set’s the content-type as we perform a render of an rjs from within a .rhtml and this seems to change the content-type, so we need to reset it.

_function.rjs
page << 'function add_item() {'
    page.insert_html :bottom, 'list', content_tag('li', 'item', :id => 'list_item' )
    page.visual_effect :highlight, 'list', :duration => 3
page << '}'

page << 'function clear_list() {'
    page.replace_html :list, ""
    page.visual_effect :highlight, 'list', :duration => 3
page << '}'

In the partial _function.rjs we insert the function declaration before writing to the page object. This allows us to invoke the add_item _ and clear_list _ methods using the link_to_function _ from in the .rhtml file. Note also in the .rhtml file we invoke directly the update_page method to insert three calls to add_item().

The generated html files looks like this

<html>
<head>
  <script src="/javascripts/prototype.js" type="text/javascript"></script>
<script src="/javascripts/effects.js" type="text/javascript"></script>
<script src="/javascripts/dragdrop.js" type="text/javascript"></script>
<script src="/javascripts/controls.js" type="text/javascript"></script>    
</head>
<body>
<h1 id='header'>Javascript function test</h1>

<a href="#" onclick="add_item(); return false;">Add</a> | 
<a href="#" onclick="clear_list(); return false;">Clear</a>
    <ul id='list' />
<script type='text/javascript'>
  function add_item() {
new Insertion.Bottom("list", "<li id=\"list_item\">item</li>");
new Effect.Highlight('list',{duration:3});
}
function clear_list() {
Element.update("list", "");
new Effect.Highlight('list',{duration:3});
}
</script>
    <script type='text/javascript'>
    add_item();
        add_item();
        add_item();
    </script>    
</body>
</html>

Xml Builder

Posted by Daniel Wanja Tue, 10 Jan 2006 21:10:00 GMT

I created the new Playground category on this blog to expose various aspects regarding Ruby On Rails that I am exploring. It may raise more questions than provide answers, but in any case don’t hesitate to jump in and add your 2 cents.

The xml_builder method here after uses the render_to_string method to create some xml structure. The xml_string could as well have been in a separate .rxml file and and a simple _render statement instead of render_as_string could have saved one line of code. But hey, that’s what the playground is for!

class PlaygroundController < ApplicationController

  def xml_builder
    xml_string = <<-XML_END
        xml.test do
          xml.language(name)
          xml.description("Rocks!")
        end
    XML_END
    result = render_to_string(:inline => xml_string, :locals => { :name => 'Ruby'}, :type => :rxml) 
    render_text result
  end

end
The output:
<test>
  <language>Ruby</language>
  <description>Rocks!</description>
</test>

Older posts: 1 ... 16 17 18 19