Sunday, November 25, 2007

Announcements : Rails 1.2.6: Security and Maintenance Release

Ruby on Rails 1.2.6: Security and Maintenance Release has been released on November 24, 2007 by the rails core team to address a bug in the fix for session fixation attacks (CVE-2007-5380). The CVE Identifier for this new issue is CVE-2007-6077.

You should upgrade to this new release if you do not take specific session-fixation counter measures in your application. 1.2.6 also fixes some regressions when working with has_many associations on unsaved ActiveRecord objects.

As with other 1.2.x releases, this is intended as a drop in upgrade for users of earlier versions in the 1.2 series.

To upgrade, `gem install rails`, set RAILS_GEM_VERSION to ‘1.2.6’ in config/environment.rb, and `rake rails:update:configs`.

Sunday, November 18, 2007

Announcements : Aptana Radrails 0.9.1 Final Release

For Radrails users, there is happy news !

Aptana RadRails 0.9.1 Final Release has been released since 15th November 2007. Users who are still on 0.8.0 are highly recommended to upgrade.

Here's the Trac changelog: http://www.aptana.com/trac/milestone/RadRails%20IDE%200.9.1 And the ASAP one: http://support.aptana.com/issues/browse/ROR/fixforversion/10004

Saturday, November 10, 2007

Announcements : Rails 2.0 Release Candidate 1

Looks as if Rails 2.0 will be released soon if this post by DHH (creator of Rails) today at the Ruby on Rails : Talk Google Group is any indication :-

We're almost there. Really this time.
http://weblog.rubyonrails.org/2007/11/9/rails-2-0-release-candidate-1

BTW, the basic advice is to upgrade to 1.2.5 and get rid of all deprecation warnings.

Saturday, November 3, 2007

Advanced Rails : Testing a Ruby on Rails Application [Updated 30th August 2009]

Thanks to DHH and his team, Rails guides you to create a well-tested application by actively generating default test cases and setting up scripts and tools to run 3 different kinds of tests namely, unit testing, functional testing and integration testing.

For example, when you use script/generate to create your models and controllers, Rails also generates skeletal test files for you to flesh out with tests for your apps.

1) Unit Testing deals with tests on models.
2) Controllers are tested via Functional Testing
3) Integration Testing focuses on the testing of the interation between controllers

Rails has a number of features that make it easy to test your application. In particular, Rails uses a separate runtime database dedicated to testing and can automatically populate the test database with fresh sample data (that you provide) before each test.

This is how you execute the tests :-

a) Test all units and functionals
rake test

b) Run tests for functionals
rake test:functionals

c) Run tests for integration
rake test:integration

d) Run tests for units
rake test:units

Testing within Aptana RadRails
1) Select the Rails Project that is to be tested
2) Click the Tests Icon on the ToolBar Nb. Y0u have a choice to select All Tests, Unit Tests, Functional Tests and Integration Tests
3) If you select Unit Tests, you should see a dialog window showing progress with an option to run in the background.


4) On competion of the test, you should see the following result :-


Available assertions for rake test:units

assert_kind_of Class, @var # same class
assert @var # not nil
assert_equal 1, @p.id # equality

@product.destroy
assert_raise(ActiveRecord::RecordNotFound) { Customer.find( @customer.id ) }

Available assertions for rake test:functional

a) Requests

get :action # a get request of the specificed action

get :action, :id => 1,
{ session_hash }, # optional session variables
{ flash_hash } # optional messages in the flash
post :action, :foo => { :value1 => 'abc', :value2 => '123' },
{ :user_id => 17 },
{ :message => 'success' }
get, post, put, delete, head
assert_response :success

# possible parameters are:
# :success
# :redirect
# :missing
# :error


b) Redirects
assert_redirected_to :action => :other_action
assert_redirected_to :controller => 'foo', :action => 'bar'
assert_redirected_to http://crm4web.com.my/

c) Rendered with Template
assert_template "post/index"

d) Variable Assignments
assert_nil assigns(:some_variable)
assert_not_nil assigns(:some_variable)
assert_equal 11, assigns(:posts).size

e) Rendering of Specific Tags
assert_tag :tag => 'body'
assert_tag :content => 'Rails Plugins'
assert_tag :tag => 'div', :attributes => { :class => 'index_list' }
assert_tag :tag => 'head', :parent => { :tag => 'body' }
assert_tag :tag => 'html', :child => { :tag => 'head' }
assert_tag :tag => 'body', :descendant => { :tag => 'div' }
assert_tag :tag => 'ul',
:children => { :count => 1..3,
:only => { :tag => 'li' } }





More to come...

Wednesday, October 31, 2007

Rails Basics : Useful Helpers

In developing the e-CRM, I have found the following helper methods very useful :-

a) Hardcoded select list

def severity_form_column (record, name)
select_tag name, options_for_select(%w(Show-stopper Severe Nice-to-have Customisation Trivial), record.severity)
end

b) TextArea for edit/create

def blog_form_column(record, input_name) text_area_tag('record[blog]', @record.blog, :size=>"80x30")
end

c) checkbox for edit/create

def active_form_column(record, input_name)
check_box :record, :active, :name => input_name
end

e) checkbox for list
def active_column(record)
check_box_tag 'active', 1, record.active?, { :disabled => true }
end

f) date display for list
def bill_date_column(record)
if record.bill_date.nil?
record.bill_date= '-' #''&nbsp'
else
record.bill_date.strftime("%d/%m/%y")
end
end

g) Customising Rails date format

def mydate_form_column(record, input_name)
date_select(:record, :mydate :order =>
[:day, :month, :year], :start_year => 1970, :end_year => 2000)
end

h) Controlling Text Field Size

def name_form_column(record, input_name)
text_field_tag('record[name]', @record.name, { :autocomplete => "off", :size => 40, :class => 'text-input'})
end

Sunday, October 28, 2007

Advanced Rails : Why you should not use Global Variables ! [Updated 12th Sept 2009]

What are global variables in Ruby ?

A global variable has a name beginning with $. It can be referred to from anywhere in a program. Before initialization, a global variable has the special value nil.

Global variables should be used sparingly. They are dangerous because they can be written to from anywhere. Overuse of globals can make isolating bugs difficult; it also tends to indicate that the design of a program has not been carefully thought out. Whenever you do find it necessary to use a global variable, be sure to give it a descriptive name that is unlikely to be inadvertently used for something else later (calling it something like $foo as above is probably a bad idea).

When a global variable has been rigged to work as a trigger to invoke a procedure whenever changed, we sometimes call it an active variable. For instance, it is useful for keeping a GUI display up to date.

There is a collection of special variables whose names consist of a dollar sign ($) followed by a single character. For example, $$ contains the process id of the ruby interpreter, and is read-only. Here are the major system variables and their meanings (see the ruby reference manual for details):

$! latest error message
$@ location of error
$_ string last read by gets
$. line number last read by interpreter
$& string last matched by regexp
$~ the last regexp match, as an array of subexpressions
$n the nth subexpression in the last match (same as $~[n])
$= case-insensitivity flag
$/ input record separator
$\ output record separator
$0 the name of the ruby script file
$* the command line arguments
$$ interpreter's process ID
$? exit status of last executed child process

In the above, $_ and $~ have local scope. Their names suggest they should be global, but they are much more useful this way, and there are historical reasons for using these names.

Why you should not not use Global Variables

Let us assume that on login (say using Acts As Authenticated), you may be tempted to initialise say $is_admin = current_user.isadmin and then use $is_admin to control access to modules or whatever. This will work very nicely in development mode or even production mode under say Apache 2.x + 1 mongrel process.

However, once you use Apache 2.2x + a pack of mongrel processes, your security measure will fail miserably ! Why ?

Prior to using Apache+a pack of mongrels, I was succesfully using a home-made role-based authentication in conjunction with AAA.

What I did basically was to add roles in users (AAA table) via adding fields (such as is_admin, is_marketing, is_finance etc). The result is that a user can can have one or many roles.
With this concept, I could control access to modules using layouts and within each controller or model I can control access to specific actions.


1. Control access to specific actions via controller.

EXAMPLE in customers_controller.rb
layout 'customers'
active_scaffold :customer do config

if User.current_user.is_admin
config.nested.add_link("Receivables", [:receivables])
end

2. Control access to specific actions via model

has_many :receivables

def authorized_for_update?
current_user.is_finance
end

def authorized_for_destroy?
current_user.is_admin
end


Using 1-3 works perfectly on Apache+1 mongrel on a Windows 2003. But once I activate Apache + 2 or mongrels, the whole security system got thrashed !


Response from Jan (Mongrel FAQ)

Globals are not shared across different instance of mongrel. To have a global appear in all instances you need some form of permanent storage (filesystem or database). If it doesn't need to change over the lifetime of the program you can pass in the global at startup in an environment variable.

You would not want to use a global in this case, since it needs to change after start up and the other mogrels would not be aware of the change. Use permanent storage. File system, database, or perhaps even a cookie

Response from Luis (author of mongrel windows service)

As Jan pointed, global variables aren't shared across processes.
You need rely your authorization schema in something else instead a global variable, since 2 users could hit the same mongrel instance and both get great as admin.
You need to investigate further about authorization schemas and how session is handled (and could be used for your purpose).

First you need to move your session storage to ActiveRecord or cookie based (in case of 1.2.5 or edge). Then I suggest you take a look at the following plugins for Authentication:

RESTful Authentication:
http://railsify.com/plugins/3-restful-authentication

Acts as Authenticated:
http://technoweenie.stikipad.com/plugins/show/Acts+as+Authenticated

Later you will need some role management (to handle is_admin?) Take a look at the suggestion and the "Elsewhere" part from the Acts as Authenticated stikipad page.



My solution was to use the role_requirement plugin by Tim Harper.

This link is also relevant to our discussion here.

Saturday, October 27, 2007

Rails Basics : All about Validations

Irrespective of languages, frameworks and platforms, one cannot run away from providing validations to data input. How does Ruby on Rails do it ?

To be precise, Active Record, an integral part of RoR, provides validation support as follows :-

a) validates_acceptance_of(attribute, :message => "message", :accept => "1")
b) validates_confirmation_of(attribute, :message => "message")

c) validates_exclusion_of(attribute, :in => enumerable_object, :message => "message")
d) validates_inclusion_of(attribute, :in => enumerable_object, :message => "message")

e) validates_length_of(attribute, :maximum => max, :allow_nil => true, :message => "message")

f) validates_length_of(attribute, :minimum => min, :message => "message")
g) validates_length_of(attribute, :in => range, :message => "message")

h) validates_numericality_of(value, :message => "message")

i) validates_presence_of(attributes, :message => "message")

j) validates_size_of(attribute, :maximum => max, :message => "message")
k) validates_size_of(attribute, :minimum => min, :message => "message")
l) validates_size_of(attribute, :in => range, :message => "message")

m) validates_uniqueness_of(attributes, :message => "message", :scope => "condition")
n) validates_uniqueness_of(attributes, :message => "message", :scope => "condition")

Welcome to Rails.. Rails... Rails !

In 1995, I started the popular Clipper...Clipper... Clipper website (no blogs then) which was very popular and linked by virtually every Clipper-related site. When I switched to Windows via Delphi in 1997, I started the Delphi... Delphi... Delphi site. In June 2007, I discovered Ruby on Rails and no prize for guessing what I am gonna name this blog. which I started on 2nd October 2007.

As at 10th June 2010, we have 13,364 unique visitors from more than 84 countries such as Angola, Andorra, Argentina, Australia, Austria, Algeria,Barbados, Bosnia and Herzogovina, Belgium, Brazil, Bulgaria, Bangladesh, Belarus, Bolivia, Chile, Cambodia, Cape Vede, Canada, China, Colombia, Costa Rica, Croatia, Cyprus, Czech Republic, Denmark, Egypt, Estonia, Finland, France, Guadeloupe, Guatemala, Germany, Greece, Hong Kong, Hungary, India, Indonesia, Ireland, Israel, Italy, Japan, Kenya, Korea, Lithuania, Latvia, Malaysia, Mexico, Macao, Netherlands, Nepal, Norway, New Zealand, Oman, Panama, Peru, Poland, Portugal,Paraguay , Philippines, Romania, Russian Federation, Saudi Arabia, Singapore, Spain, Slovakia, Slovenia, Serbia, South Korea, Slovenia, South Africa, Spain, Switzerland, Sri Lanka, Sweden, Taiwan, Thailand, Turkey, United Arab Emirates, Ukraine, USA, UK, Venezuela, Vietnam

CCH
10th June 2010, 19:42