Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Agile Web Development With Rails, 1st Edition (2005).pdf
Скачиваний:
28
Добавлен:
17.08.2013
Размер:
7.99 Mб
Скачать

REGULAR EXPRESSIONS

476

Ruby statement modifiers are a useful shortcut if the body of an if or while statement statement is just a single expression. Simply write the expression, followed

by if or while and the condition.

puts "Danger, Will Robinson" if radiation > 3000

A.8 Regular Expressions

A regular expression is a way of specifying a pattern of characters to be matched in a string. In Ruby, you typically create a regular expression by writing /pattern/ or %r{pattern}.

For example, you could write a pattern that matches a string containing the text Perl or the text Python using the regular expression /Perl|Python/.

The forward slashes delimit the pattern, which consists of the two things we’re matching, separated by a vertical bar (|). This bar character means “either the thing on the right or the thing on the left,” in this case either Perl or Python. You can use parentheses within patterns, just as you can in arithmetic expressions, so you could also have written this pattern as /P(erl|ython)/. Programs typically test strings against regular expressions using the =~ match operator.

if line =~ /P(erl|ython)/

puts "There seems to be a perturbation in the force" end

You can specify repetition within patterns. /ab+c/ matches a string containing an a followed by one or more b’s, followed by a c. Change the plus to an asterisk, and /ab*c/ creates a regular expression that matches one a, zero or more b’s, and one c.

Ruby’s regular expressions are a deep and complex subject; this section barely skims the surface. See the PickAxe book for a full discussion.

A.9 Blocks and Iterators

Code blocks are just chunks of code between braces or between do...end. A common convention is that people use braces for single-line blocks and do/end for multiline blocks.

{ puts "Hello" }

# this is a block

do

###

club.enroll(person)

# and so is this

person.socialize

#

end

###

Prepared exclusively for Rida Al Barazi

Report erratum

EXCEPTIONS 477

The only place a block can appear is after the call to a method; put the start of the block at the end of the source line containing the method call. For example, in the following code, the block containing puts "Hi" is associated with the call to the method greet( ).

greet { puts "Hi" }

If the method has parameters, they appear before the block.

verbose_greet("Dave", "loyal customer") { puts "Hi" }

A method can invoke an associated block one or more times using the Ruby yield statement. You can think of yield as being something like a method call that calls out to the block associated with the method containing the yield. You can pass values to the block by giving parameters to yield. Within the block, you list the names of the arguments to receive these parameters between vertical bars (|).

Code blocks appear throughout Ruby applications. Often they are used in conjunction with iterators: methods that return successive elements from some kind of collection, such as an array.

animals = %w( ant bee cat dog elk )

#

create an array

animals.each {|animal| puts animal }

#

iterate over the contents

Each integer N implements a times( ) method, which invokes an associated block N times.

3.times { print "Ho! " }

#=> Ho! Ho! Ho!

A.10 Exceptions

Exceptions are objects (of class Exception or its subclasses). The raise method causes an exception to be raised. This interrupts the normal flow through the code. Instead, Ruby searches back through the call stack for code that says it can handle this exception.

Exceptions are handled by wrapping code between begin and end keywords and using rescue clauses to intercept certain classes of exception.

begin

content = load_blog_data(file_name) rescue BlogDataNotFound

STDERR.puts "File #{file_name} not found" rescue BlogDataFormatError

STDERR.puts "Invalid blog data in #{file_name}" rescue Exception => exc

STDERR.puts "General error loading #{file_name}: #{exc.message}" end

Prepared exclusively for Rida Al Barazi

Report erratum

MARSHALING OBJECTS 478

A.11 Marshaling Objects

Ruby can take an object and convert it into a stream of bytes that can

be stored outside the application. This process is called marshaling. This marshaling saved object can later be read by another instance of the application (or

by a totally separate application), and a copy of the originally saved object can be reconstituted.

There are two potential issues when you use marshaling. First, some objects cannot be dumped: if the objects to be dumped include bindings, procedure or method objects, instances of class IO, or singleton objects, or if you try to dump anonymous classes or modules, a TypeError will be raised.

Second, when you load a marshaled object, Ruby needs to know the definition of the class of that object (and of all the objects it contains).

Rails uses marshaling to store session data. If you rely on Rails to dynamically load classes, it is possible that a particular class may not have been defined at the point it reconstitutes session data. For that reason, you’ll use the model declaration in your controller to list all models that are marshaled. This preemptively loads the necessary classes to make marshaling work.

A.12 Interactive Ruby

irb—Interactive Ruby—is the tool of choice for executing Ruby interactively. irb is a Ruby Shell, complete with command-line history, line-editing capabilities, and job control. You run irb from the command line. Once it starts, just type in Ruby code. irb shows you the value of each expression as it evaluates it.

% irb

irb(main):001:0> def sum(n1, n2) irb(main):002:1> n1 + n2 irb(main):003:1> end

=> nil

irb(main):004:0> sum(3, 4) => 7

irb(main):005:0> sum("cat", "dog") => "catdog"

You can run irb on Rails applications, letting you experiment with methods (and sometimes undo damage to your database). However, setting up the full Rails environment is tricky. Rather than do it manually, use the scripts/console wrapper, as shown on page 187.

Prepared exclusively for Rida Al Barazi

Report erratum

RUBY IDIOMS 479

A.13 Ruby Idioms

Ruby is a language that lends itself to idiomatic usage. There are many good resources on the web showing Ruby idioms and Ruby gotchas. Here are just a few.

http://www.glue.umd.edu/~billtj/ruby.html

http://www.rubygarden.org/faq

http://en.wikipedia.org/wiki/Ruby_programming_language

http://www.zenspider.com/Languages/Ruby/QuickRef.html

This section shows some common Ruby idioms that we use in this book.

methods such as empty! and empty?

Ruby method names can end with an exclamation mark (a bang method) or a question mark (a predicate method). Bang methods normally do something destructive to the receiver. Predicate methods return true or false depending on some condition.

a || b

The expression a || b evaluates a. If it isn’t false or nil, then evaluation stops and the expression returns a. Otherwise, the statement returns b. This is a common way of returning a default value if the first value hasn’t been set.

a ||= b

The assignment statement supports a set of shortcuts: a op= b is the same as a = a op b. This works for most operators.

count +=

1

# same as count = count +

1

price *=

discount

#

price = price *

discount

count ||= 0

#

count = count || 0

So, count ||= 0 gives count the value 0 if count doesn’t already have a value.

obj = self.new

(This idiom is somewhat advanced and can be safely skipped.)

Sometimes a class method needs to create an instance of that class.

class Person < ActiveRecord::Base def self.for_dave

Person.new(:name => 'Dave') end

end

This works fine, returning a new Person object. But later on, someone might subclass our class.

Prepared exclusively for Rida Al Barazi

Report erratum

RDOC DOCUMENTATION 480

class Employee < Person

# .. end

dave = Employee.for_dave # returns a Person

The for_dave( ) method was hardwired to return a Person object, so that’s what is returned by Employee.for_dave. Using self.new instead returns a new object of the receiver’s class, Employee.

require File.dirname(__FILE__) + ’/../test_helper’

Ruby’s require method loads an external source file into our application. This is used to include library code and classes that our application relies on. In normal use, Ruby finds these files by searching in a list of directories, the LOAD_PATH.

Sometimes we need to be specific about what file to include. We can do that by giving require a full filesystem path. The problem is, we don’t know what that path will be—our users could install our code anywhere.

Wherever our application ends up getting installed, the relative path between the file doing the requiring and the target file will be the same. Knowing this, we can construct the absolute path to the target by taking the absolute path to the file doing the requiring (available in the special variable __FILE__), stripping out all but the directory name and then appending the relative path to the target file.

A.14 RDoc Documentation

RDoc is a documentation system for Ruby source code. Just like JavaDoc, RDoc takes a bunch of source files and generates HTML documentation, using syntactic information from the source and text in comment blocks. Unlike JavaDoc, RDoc can produce fairly good content even if the source contains no comments. It’s fairly painless to write RDoc documentation as you write the source for your applications. RDoc is described in Chapter 16 of the PickAxe.

RDoc is used to document Ruby’s built-in and standard libraries. Depending on how your Ruby was installed, you might be able to use the ri command to access the documentation.

Prepared exclusively for Rida Al Barazi

Report erratum

 

RDOC DOCUMENTATION

481

dave> ri String.capitalize

 

 

-----------------------------------------------

String#capitalize

 

str.capitalize => new_str

 

-----------------------------------------------------------------

 

Returns a copy of str with the first character converted to

 

uppercase and the remainder to lowercase.

 

"hello".capitalize

#=> "Hello"

 

"HELLO".capitalize

#=> "Hello"

 

"123ABC".capitalize

#=> "123abc"

 

If you used RubyGems to install Rails, you can access the Rails API documentation by running gem_server and then pointing your browser at the URL http://localhost:8808.

The rake appdoc command creates the HTML documentation for a Rails project, leaving it in the doc/app directory.

Prepared exclusively for Rida Al Barazi

Report erratum

Appendix B

Configuration Parameters

As explained on page 180, the various Rails components can be configured by setting options in either the global environment.rb file or in one of the environment-specific files in the config/environments directory.

B.1 Active Record Configuration

ActiveRecord::Base.logger =logger

Accepts a logger object. This is used internally to record database activity. It is also available to applications that want to log activity.

ActiveRecord::Base.primary_key_prefix_type =option

If option is nil, the default primary key column for each table is id. If :table_name, the table name is prepended. Add an underscore between the table name and the id part by setting the option to the value :table_name_with_underscore.

ActiveRecord::Base.table_name_prefix ="prefix"

Prepend the given strings when generating table names. For example, if the model name is User and the prefix string is "myapp-", Rails will look for the table myapp-users. This might be useful if you have to share a database among different applications or if you have to do development and testing in the same database.

ActiveRecord::Base.table_name_suffix ="suffix"

Append the given strings when generating table names.

ActiveRecord::Base.pluralize_table_names = true | false

If false, class names will not be pluralized when creating the corresponding table names.

Prepared exclusively for Rida Al Barazi

ACTION PACK CONFIGURATION 483

ActiveRecord::Base.colorize_logging = true | false

By default, Active Record log messages use ANSI control sequences, which colorize certain lines when viewed using a terminal application that supports these sequences. Set the option to false to remove this colorization.

ActiveRecord::Base.default_timezone = :local | :utc

Set to :utc to have dates and times loaded from and saved to the database treated as UTC.

ActiveRecord::Locking.lock_optimistically = true | false

If false, optimistic locking is disabled. (See Section 14.5, Optimistic Locking, on page 213.)

ActiveRecord::Timestamp.record_timestamps = true | false

Set to false to disable the automatic updating of the columns created_at, created_on, updated_at, and updated_on. This is described on page 267.

ActiveRecord::Errors.default_error_messages =hash

A hash of standard validation failure messages. You can replace these with your own messages, perhaps for internationalization purposes. The default set are

ActiveRecord::Errors.default_error_messages = { :inclusion => "is not included in the list", :exclusion => "is reserved",

:invalid => "is invalid",

:confirmation => "doesn't match confirmation", :accepted => "must be accepted",

:empty => "can't be empty",

:too_long => "is too long (max is %d characters)", :too_short => "is too short (min is %d characters)",

:wrong_length => "is the wrong length (should be %d characters)", :taken => "has already been taken",

:not_a_number => "is not a number",

}

B.2 Action Pack Configuration

ActionController::Base.asset_host =url

Sets the host and/or path of stylesheet and image assets linked using the asset helper tags.

ActionController::Base.asset_host = "http://media.my.url"

ActionController::Base.view_controller_internals = true | false

By default, templates get access to the controller collections request, response, session, and template. Setting this option to false removes this access.

Prepared exclusively for Rida Al Barazi

Report erratum

ACTION PACK CONFIGURATION 484

ActionController::Base.consider_all_requests_local = true | false

Set to false in production to stop users from seeing stack backtraces. This is discussed in more depth in Section 22.3, Handling Errors, on page 450.

ActionController::Base.debug_routes = true | false

If true, gives detailed information when the routing component fails to parse an incoming URL. Turn off for production.

ActionController::Base.logger =logger

Sets the logger used by this controller. The logger object is also available to your application code.

ActionController::Base.template_root =dir

Template files are looked for beneath this directory. Defaults to app/views.

ActionController::Base.template_class =class

Defaults to ActionView::Base. You probably don’t want to change this.

ActionController::Base.ignore_missing_templates = false | true

If true, no error will be raised if a template cannot be found.

ActionController::Base.perform_caching = true | false

Set to false to disable all caching.

ActionController::Base.page_cache_directory =dir

Where cache files are stored. Must be the document root for your web server.

ActionController::Base.page_cache_extension =string

Overrides the default .html extension used for cached files.

ActionController::Base.fragment_cache_store =caching_class

Determines the mechanism used to store cached fragments. Fragment cache storage is discussed on page 369.

ActionView::Base.cache_template_loading = false | true

Turn on to cache the rendering of templates, which improves performance. However, you’ll need to restart the server should you change a template on disk.

ActionView::Base.field_error_proc =proc

This proc is called to wrap a form field that fails validation. The default value is

Proc.new do |html_tag, instance|

%{<div class="fieldWithErrors">#{html_tag}</div>} end

Prepared exclusively for Rida Al Barazi

Report erratum

ACTION MAILER CONFIGURATION 485

B.3 Action Mailer Configuration

These settings are described in Section 19.1, E-mail Configuration, on page 399.

ActionMailer::Base.template_root = directory

ActionMailer::Base.logger = logger object

ActionMailer::Base.server_settings = hash

ActionMailer::Base.raise_delivery_errors = true | false

ActionMailer::Base.delivery_method = :smtp | :sendmail | :test

ActionMailer::Base.perform_deliveries = true | false

ActionMailer::Base.default_charset = "string"

B.4 Test Case Configuration

The following options can be set globally but are more commonly set inside the body of a particular test case.

# Global setting

Test::Unit::TestCase.use_transactional_fixtures = true

# Local setting

class WibbleTest < Test::Unit::TestCase self.use_transactional_fixtures = true

# ...

use_transactional_fixtures = true | false

If true, changes to the database will be rolled back at the end of each test (see Section 12.7, Transactional Fixtures, on page 170).

use_instantiated_fixtures = true | false | :no_instances

Setting this option to false disables the automatic loading of fixture data into an instance variable. Setting it to :no_instances creates the instance variable but does not populate it.

pre_loaded_fixtures = false | true

If true, the test cases assume that fixture data has been loaded into the database prior to the tests running. Use with transactional fixtures to speed up the running of tests.

Prepared exclusively for Rida Al Barazi

Report erratum