Sunday, April 13, 2008

Rails attr_accessor is an instance variable

It took me some time to truly understand rails attr_accessor macro method though I've already used it a lot before.

Attr_accessor, along with attr_reader and attr_writer, they are in fact ruby things not rails. Attr_accessor defines instance variables and builds the get/set methods for each instance variable.

To know the difference between ActiveRecord's attribute (for table field) and the attr_accessor, the best way is to give an example, let's see:

class User > ActiveRecord::Base
attr_accessor :password #password is not a user's table field
validates_presence_of :login
end

##########################

[/home/jack/test_app]$ script/console
Loading development environment (Rails 2.0.2)
>> user = User.new(:login => "jimmy", :password => "railsrocks")
=> #
### password is not a field

>> user.instance_variables
=> ["@attributes_cache", "@attributes", "@password", "@new_record"]
>> user.instance_variable_get :@login
=> nil
>> user.instance_variable_get :@password
=> "railsrocks"
>> user.has_attribute? "login"
=> true
>> user.has_attribute? "password"
=> false
### login is an attribute, while password is a instance variable

>> user.login
=> "jimmy"
>> user.password
=> "railsrocks"
>> user.send 'login'
=> "jimmy"
>> user.send 'password'
=> "railsrocks"
### both getter/setter are working
### in some situation, for example, the field name itself is a variable
### you can use: user.send method_name

>> user[:login]
=> "jimmy"
>> user.attributes
=> {"login"=>"jimmy"}
>> user[:password]
=> nil
### oops, I can not get password by this way

>> user.attributes={:login => "grissom", :password => "rubyrocks"}
=> {:password=>"rubyrocks", :login=>"grissom"}
>> user.password
=> "rubyrocks"
### well, to assign value is working

Thursday, April 10, 2008

Design Free Administration Back Office For Rails Application

There are some common concerns to build a back office for a rails project. Not like the front pages, which are usually designed by professional web designers, back office pages often need to be scratched by programmers. It often takes me a lot of time to do the layout, HTML structures, header and footer, div content boxes, list table styles and form field styles. Though I am familiar with CSS, I still troubled a lot with the overall look and feel because of my lack of the web design gene. So I am writing here to conclude a way to be design fee....

1. Install my plugin uni_admin for admin layout, table styles:

http://code.google.com/p/ruby-on-rails-plugin-uni-admin/

2. Install uni-form and my uni-form-patch for form styles

http://code.google.com/p/rails-uni-form-patch/

3. Install plugin restful authentication for basic authentication

http://xiaoboonrails.blogspot.com/2008/02/install-and-config-rails-plugin.html

4. If you have installed comatose, it is easy to integrate comatose_admin with uni_admin layout
rake comatose:admin:customize
update related content of layouts/uni_admin_layout.html.erb to layouts/comatose_admin.rhtml

Rails Plugin Uni_Form_Patch for Plugin Uni-Form

UniFormPatch
============
A small patch plugin for Marcus Irven's uni-form plugin.

Code home: http://code.google.com/p/rails-uni-form-patch/

Fix the following features:
  • Make the form show properly
  • Show field focus and error background images
  • Show error and success form messages properly

Installation
=========
If you havn't installed uni-form, install it at first:
script/plugin install http://uni-form.rubyforge.org/svn/trunk/plugins/uni-form/

Follow the installation notes in Marcus's uni-form README to finish installation

Install uni_form_patch:
script/plugin install http://rails-uni-form-patch.googlecode.com/svn/trunk/uni_form_patch

The installation will automatically copy/update/delete files:
Copy public/images/uni-form/*.png
Update public/stylesheets/uni-form.css
Delete public/stylesheets/uni-form-generic.css

Example
=======
For the usage of uni-form, read Marcus's uni-form README.

Show uni-form style messages:
<% uni_form_for :user do |form| %>

<%= uniform_success_message flash[:notice] if flash[:notice] %>
<%= uniform_error_messages [@user] %>
<%= uniform_error_messages [@user, @address] %>

<% form.fieldset :type => "block", :legend => "cool stuff" do %>
<%= form.text_field :first_name, :required => true, :label => "Your first name" %>
<%= form.text_field :last_name %>
<% end %>
<%= form.submit "save" %>
<% end %>

Ruby On Rails Plugin Uni Admin For Admin Layout

Today I code a new simple plugin Uni_Admin. Uni Admin is a simple administration layout support for ruby on rails web application. Now it includes:
  • an admin base controller and dashboard action
  • a simple admin layout
  • a simple admin CSS file
  • an integrated admin menu
  • a record list table style
Demo:


More details please see the code page:

http://code.google.com/p/ruby-on-rails-plugin-uni-admin/

Wednesday, April 9, 2008

KikOut.com Beta Version 0.2 Released

My ruby on rails project KikOut.com released beta version 0.2.

It is a search engine to help you facilitate your web searching, for example, using youtube:keyword to search youtube directly. You will dig more fun after using it. More information about Kikout please check out the Kikout why&howto page.

Welcome make your own search definitions or share your experiences/submit your comments.

Wednesday, March 19, 2008

Rails ActiveMerchant Patch For BeanStream

I submitted the patch to active merchant plugin for Canada payment gateway BeanStream. I guess that it will take some time to get reviewed, tested and accepted ( or not accepted because the remote test can not be passed without beanstream's test account which it doesn't provide it to me), so I uploaded the patch to a google code project:

http://code.google.com/p/activemerchant-patch-for-beanstream/

The installation, description and a simple example have been already written in the project home page. Issue your bug or give me your feedback if you encounter any problem when using it.

A Rails Plugin table_styles to let you easily use up to 42 different css styles for HTML table.

Today I wrote a rails plugin based on CSS Table Gallery .

I upload to google code: http://code.google.com/p/rails-plugin-table-styles/

Installation
script/plugin install http://rails-plugin-table-styles.googlecode.com/svn/trunk/table_styles

Usage

* Use the demo to find one of your favorable style.
# Start your server: >script/server
# Visit http://localhost:3000/table_styles_demo/
# Remember to add map.connect :controller/:action in your routes.rb

* Choose one of table styles in your layout header, use "tagbox" as an example.
<%= table_stylesheet_link_tag "tagbox" %>

* Just use table tag it in your view

* Use form helper if you want to let admin user to choose table style in user preferences page.
table_style_select or table_style_options_for_select

Rails irb or script/console tips in one glimpse

Summarize most basic tips of using script/console here:
  • # script/console (note: start it)
  • # script/console production (note: start it with production environment)
  • # script/console -s (note: run in sandbox, all change to data records will rollback)
  • >>$LOAD_PATH (note: see the load_path of current environment)
  • >>reload! (note: reload the environment)
  • >>clear
  • >>$ (note: use TAB key to see all environment variables)
  • >>Str (note: use TAB key to auto complete)
  • >>@hello = "Hello word!" (note: define variable)
  • >>@hello = Object.new (note: define variable)
  • >>@order = Order.find(1) (note: get an order object, order.rb should be in one of app models)
  • >>app.get "/articles/1234" (note: run controller by route path)
  • >>app.post "/login", {:login => "xiaobozz", :password => "12345"}
  • >>helper.image_tag "logo.gif" (note: run any method of actionview helpers)
  • >>y @order (note: YAML style output)

The best way to get familiar with these tips is to use them now :-)

Monday, March 17, 2008

Rails send emails with actionmailer and gmail

The first step is to configure your rails application to work with gmail, I just copied the 2 simple steps from the Preston Lee's article:

1. Save this code as lib/smtp_tls.rb within your rails app;
2. Add this code to config/environment.rb

The second step is to learn to use actionmailer, just follow the document "How to send emails with action mailer" to do it then you will understand how it works pretty fast.

1. ruby script/generate mailer Notifier signup order_created
2. add code to your app/models/notifier.rb, such as

def signup( user )
# Email header info MUST be added here
recipients user.email
from "accounts@mywebsite.com"
subject ¡°Thank you for registering with our website¡±
# Email body substitutions go here
body :user=> user
end

3. add code to /app/views/notifier/signup.erb
Dear <%= @user.first_name %> <%= @user.last_name %>,
Thanks for signing up with My Website!

4. use the mailer in where you want.
Notifier.deliver_signup(user)

Wednesday, March 12, 2008

How to restart Webmin

Webmin provides a stop and start command itself, while it is not in any bin path. It is in the initial installation path.
su
cd /usr/libexec/webmin
webmin-init stop
webmin-init start

Done!

Tuesday, March 11, 2008

A special post to claim on Technorati

This is a special post to claim on Technorati:

Technorati Profile

Rails Mongrel and Apache servers work with SSL, certificates and https

I am already running Apache as the front end server and Mongrel Rails Cluster Servers as the back end. To make them work with SSL, certificates and HTTPS, there are several easy steps to finish.

# 1. make a directory to store ssl key and certificates
mkdir /etc/httpd/conf/ssl

# 2. create openssl key and make it secure
cd /etc/httpd/conf/ssl
openssl genrsa -des3 -out yourdomain.key 1024
chmod 600 yourdomain.key

# 3. create CSR file (certificates signing request)
# Common name is your domain name without http:// but with www.
openssl req -new -key yourdomain.key -out yourdomain.csr

# 4. I bought godaddy's ssl certificate
# And got the certificate by email in 5 mins after I submitted the CSR.
Download the CSR zip file, unzip the two certs into ssl directory

# 5. Config apache's yourdomain config part
# Assuming that you have configurated yourdomain.common and yourdomain.cluster_proxy.conf properly.
virtualhost
ServerName www.yourdomain.com:443
Include /etc/httpd/conf/yourdomain.common

RequestHeader set X_FORWARDED_PROTO 'https'

ErrorLog logs/yourdomain_ssl_errors_log
CustomLog logs/yourdomain_ssl_log combined

SSLEngine on
SSLCertificateFile /etc/httpd/conf/ssl/yourdomain.crt
SSLCertificateKeyFile /etc/httpd/conf/ssl/yourdomain.key
SSLCertificateChainFile /etc/httpd/conf/ssl/gd_intermediate_bundle.crt
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
/virtualhost

# 6. install and use plugin ssl_requirement
script/plugin install ssl_requirement
include SslRequirement (in your application.rb)
ssl_required :login, :orders (in your controller with those actions)

Saturday, March 1, 2008

Fast install SVN server on linux

It is crazy easy to build SVN server, much easier than CVS server. Just do the following steps:

  • su root
  • # download the relatest stable version of SVN source code
  • wget http://subversion.tigris.org/downloads/subversion-1.4.6.tar.gz
  • tar xzvf subversion-1.4.6.tar.gz
  • cd subversion-1.4.6
  • ./configure
  • make & make install
  • svnserver --version # check the installation result
  • svnadmin create /svnrepos
  • vi /svnrepos/conf/svnserve.conf
  • # uncomment and edit in this config file
  • anon-access = none
  • auth-access = write
  • password-db = passwd
  • # add your username and password
  • vi /svnrepos/conf/passwd
  • # start server as a daemon
  • svnserve -d
  • # use it like:
  • svn co svn://server_ip_address/svnrepos/myproject


Reference:
Setup a Subversion Server in 4 Minutes

Tuesday, February 26, 2008

The way to have global constants in rails application

I don't know if there is a better or formal way to keep global constants for rails application. If I want to the global constants to be used only by controllers and views, the best way is to declared them in application helper. If active record is also to use them, I have to put the definitions in environment.rb. Like the following:

# Global constant for this application
# I define an array here
SOME_GLOBAL_INSTANT = [100, 300, 500, 800, 1000]

I googled by "rails global constants" but get no better solutions. Anyone knows this please tell me.

Another way to load config into controllers is to use YAML file, check out this blog post:

http://snippets.dzone.com/posts/show/287

3 easy steps to do Rails 2.0 pagination

Forget about the kind of awkward pagination of rails 1.x, now you need 3 easy steps to do Rails 2.0 pagination.

1. Install the pagination plugin:

ruby script/plugin install svn://errtheblog.com/svn/plugins/will_paginate

2. Type the following in your controller:

@products = Product.paginate(:page => params[:page], :per_page => 25)

3. Type the following in your view:

<%= will_paginate @products %>

The better thing comparing to rails 1.x pagination is that it is now easier to understand and remember. Isn't it more conventional?

Monday, February 25, 2008

A local Ruby script example with fileutils, open-uri, rmagick and mysql

##################################
# a code example for writing a ruby script to be running locally
# to do some regular local jobs such as:
# 1, download files or images from Internet
# 2, local file operations like mkdir, cp and remove
# 3, access or store data into local database like mysql
# 4, image resizing or cropping using image-magick
##################################
require 'open-uri'
require 'fileutils'
require 'RMagick'
require 'mysql'

# init local directories
FileUtils.mkdir_p "original/montreal"
FileUtils.mkdir_p "thumbnailed/montreal"

# init the database access
db = Mysql::new('127.0.0.1', 'root', '12345', 'test')

# init links to Internet
base_url = "http://farm1.static.flickr.com/"
image_urls = ['40/123180238_552597a079_b.jpg',
'146/390735501_54f0b2e826_b.jpg',
'50/131278273_4ce6400bfa_b.jpg']

# create a table to store image names
db.query("DROP TABLE IF EXISTS images")
db.query("CREATE TABLE images (name VARCHAR(64))")
image_urls.each do |image|
db.query("INSERT INTO images (name) VALUES ('#{image}')")
end

# download images from Internet
for i in 0..2
open("original/montreal/#{i}.jpg", 'wb').write(open("#{base_url}#{image_urls[i]}").read)
end

# resize and crop images
for i in 0..2
image = Magick::Image.read("original/montreal/#{i}.jpg").first
image.crop_resized!(150, 150, Magick::NorthGravity)
image.write("thumbnailed/montreal/#{i}.jpg")
end
References:

Ruby MySQL: http://www.tmtm.org/en/mysql/ruby/
RMagick: Making thumbnails with RMagick
FileUtils: http://www.ruby-doc.org/stdlib/libdoc/fileutils/rdoc/index.html
Ruby OpenURI: http://www.ruby-doc.org/core/classes/OpenURI.html

Basic flow to use rails file_column plugin

1. Create your table with a string field to store file name. For example:

create_table :products do |t|
t.string "name"
t.string "model"
t.string "image"
t.timestamps
end

2. Install file_column plugin:

script/plugin install http://opensvn.csie.org/rails_file_column/plugins/file_column/trunk

3. Install ImageMagick to your system and plugin RMagick

Visit http://rmagick.rubyforge.org/ for more detail

4. Put file_column description for model field into your model code. For example here, add to product.rb:

file_column :image, :magick => {
:versions => { "thumb" => "60x60", "medium" => "320x240"}
}

5. Generate controller and views for your model. I use rails 2.0 scaffold generator here:

script/generate scaffold product --skip-migration
add layout and authentication before_filter to product controller if needed
add _form.html.erb with form fields for new.html.erb and edit.html.erb to use
edit index.html.erb to show the list of products, such as <%= f.text_field :name %>

6. Show and upload image of product, edit in the _form.html.erb:

remove <%= f.text_field :image %>
add:
<% if !@product.id.nil? # in the case of edit %>
<%= image_tag url_for_file_column("product", "image", "medium") %>
<% end %>
<%= file_column_field "product", "image" %>

7. Add multipart to form tag in the edit and new files.

<% form_for(@product, :html => {:multipart => true}) do |f| %>

8. To show image in the list:

<% @product = product %>
<%= image_tag url_for_file_column("product", "image", "thumb") %>

Sunday, February 24, 2008

Tips to use scaffold generator of rails 2.0

There are big differences for the scaffold between rails 2.0 and rails rails 2.0 scaffold", like me, you can find a lot of good blogs or articles to learn about the new ways to use rails 2.0 scaffold. Anyhow, I would like to add some basic tips here, which I used a lot.

Number one tip is to use the help from rails itself:
script/generate scaffold -h

In rails 1.x, I created model and table in db firstly then do the scaffold, now the generator can do the model and table in the same time. The way to keep your old habit is to use:
> script/generate scaffold category(or other model name) --skip-migration

In the views, I need add the _form.html.erb by myself.

The generator will also put a map.resources in your routes.rb. If I want to add new actions such as batch_new and batch_create into this categories_controller. Config the routes.rb:
map.resources :categories,
:collection => {:batch_new => :get, :batch_create => :post}

Wednesday, February 20, 2008

Rails 2.0 tip: Create a new application with MySQL support

In rails < 2.0, when I create a rails new application by the rails command, the configuration of database.yml supports MySQL by default. While in rails 2.0, it will generate default configuration database.yml for Sqlite3. To make it default as MySQL, run with -d mysql.
rails -d mysql your_application_name

Thursday, February 14, 2008

Install and config rails plugin restful_authentication

Ruby on rails plugin Restful_authentication is a basic plugin useful for most of rails applications. It is very easy to intall and config it:
script/plugin source http://svn.techno-weenie.net/projects/plugins
script/plugin install restful_authentication
script/generate authenticated user sessions
rake db:migrate

Check the code in your routes.rb which is automatically added by the generation
map.resources :users
map.resource :session

Add more route mapping if your want
map.signup '/signup', :controller => 'users', :action => 'new'
map.login '/login', :controller => 'sessions', :action => 'new'
map.logout '/logout', :controller => 'sessions', :action => 'destroy'

Visit http://localhost:3000/users/new or http://localhost:3000/signup

Then to make it work with Comatose, add comatose config to evironment.rb of your app:
Comatose.configure do |config|
# Includes AuthenticationSystem in the ComatoseAdminController
config.admin_includes << :authenticated_system

# Calls :login_required as a before_filter
config.admin_authorization = :login_required
end