分类目录归档:Ruby on Rails

learning ruby 6, about methods

De?ning a Method
Method names should begin with a lowercase letter.
Methods that act as queries are often named with a trailing ?,
Methods that are “dangerous,” or modify the receiver, may be named with a trailing !.
methods that can be assigned to end with an equals sign (=).

def cool_dude(arg1="Miles", arg2="Coltrane", arg3="Roach")
  "#{arg1}, #{arg2}, #{arg3}."
end

def my_other_new_method
  # Code for the method would go here
end

Variable-Length Argument Lists(*, asterisk ->Array)
def varargs(arg1, *rest)
  "Got #{arg1} and #{rest.join(', ')}"
end
varargs("one")                      "Got one and "
varargs("one", "two")    "Got one and two"
varargs "one", "two", "three"       "Got one and two, three"

Methods and Blocks
def take_block(p1)
  if block_given?
    yield(p1)
  else
    p1
  end
end
take_block("no block")                           "no block"
take_block("no block") {|s| s.sub(/no /, '') }   "block"

if the last parameter in a method de?nition is pre?xed with an ampersand(&),any associated block is converted to a Proc object, and that object is assigned to the parameter.

class TaxCalculator
  def initialize(name, &block)
    @name, @block = name, block
  end
  def get_tax(amount)
    "#@name on #{amount} = #{ @block.call(amount) }"
  end
end
tc = TaxCalculator.new("Sales tax") {|amt| amt * 0.075 }
tc.get_tax(100)       "Sales tax on 100 = 7.5"
tc.get_tax(250)       "Sales tax on 250 = 18.75"

Calling a Method

Method Return values
def meth_three
 100.times do |num|
   square = num*num
   return num, square if square > 1000
 end
end
meth_three → [32, 1024]
num, square = meth_three
num      → 32
square   → 1024

Expanding Arrays in Method Calls
def five(a, b, c, d, e)
  "I was passed #{a} #{b} #{c} #{d} #{e}"
end
five(1, 2, 3, 4, 5 )            "I was passed 1 2 3 4 5"
five(1, 2, 3, *['a', 'b'])       "I was passed 1 2 3 a b"
five(*(10..14).to_a)             "I was passed 10 11 12 13 14"

Making Blocks More Dynamic
    print "(t)imes or (p)lus: "
    times = gets
    print "number: "
    number = Integer(gets)
    if times =~ /^t/
      calc = lambda {|n| n*number }
    else
      calc = lambda {|n| n+number }
    end
    puts((1..10).collect(&calc).join(", "))
produces:
    (t)imes or (p)lus: t
    number: 2
    2, 4, 6, 8, 10, 12, 14, 16, 18, 20

Collecting Hash Arguments
class SongList
  def create_search(name, params)
    # …
  end
end

list.create_search('short jazz songs',
                   :genre              => :jazz,
                   :duration_less_than => 270)

发表在 Ruby on Rails | 留下评论

Learning Ruby 4, Regular Expressions

Regular expressions are objects of type Regexp.

create
a = Regexp.new(‘^\s*[a-z]‘)   /^\s*[a-z]/
b = /^\s*[a-z]/               /^\s*[a-z]/
c = %r{^\s*[a-z]}             /^\s*[a-z]/
options:
/i         case insensitive
/o         only interpolate #{} blocks once
/m         multiline mode – ‘.’ will match newline
/x         extended mode – whitespace is ignored
/[neus]    encoding: none, EUC, UTF-8, SJIS, respectively
e.g. b = /^\s*[a-z]/i

match operators
 =~ (positive match)
 !~ (negative match)

name = "Fats Waller"
name =~ /a/   →1
name =~ /z/   → nil
/a/ =~ name   →1

return the character position at which the match occurred.
$& receives the part of the string that was matched by the pattern
$` receives the part of the string thatpreceded the match,
$’ receives the string after the match.
The match also sets the thread-global variables $~ and $1 through $9.
$~ is a MatchData object

To illustrate how matching works, define a method:
def show_regexp(a, re)
  if a =~ re
    "#{$`}<<#{$&}>>#{$’}"
  else
    "no match"
  end
end
show_regexp(‘very interesting’, /t/)   very in<<t>>eresting
show_regexp(‘Fats Waller’, /a/)        F<<a>>ts Waller
show_regexp(‘Fats Waller’, /ll/)       Fats Wa<<ll>>er
show_regexp(‘Fats Waller’, /z/)        no match

Patterns
all characters except ., |, (, ), [, ], {, }, +, \, ^, $, *, and ? match themselves.
use ‘\’ to match these characters.
regular expression may contain #{…} expression substitutions.

Anchors

By default, a regular expression will try to ?nd the ?rst match for the pattern in a string.

The patterns ^ and $ match the beginning and end of a line
\A matches the beginning of a string,
\z and \Z match the end of a string. (Actually, \Z matches the end of a string unless the string ends with a
, it which case it matches just before the
.)

show_regexp("this is\n the time", /^the/)     this is\n<<the>> time
show_regexp("this is\n the time", /is$/)      this <<is>>\n the time
show_regexp("this is\n the time", /\Athis/)   <<this>> is \n the time
show_regexp("this is\n the time", /\Athe/)    no match

\b and \B match word boundaries and nonword boundaries
Word characters are letters, numbers, and underscores.
show_regexp("this is\n the time", /\bis/)   this <<is>>\n the time
show_regexp("this is\n the time", /\Bis/)   th<<is>> is\n the time

Character Classes
[aeiou] will match a vowel
[,.:;!?] matches punctuation

show_regexp(‘Price $12.’, /[aeiou]/)            Pr<<i>>ce $12.
show_regexp(‘Price $12.’, /[\s]/)               Price<< >>$12.
show_regexp(‘Price $12.’, /[[:digit:]]/)        Price $<<1>>2.
show_regexp(‘Price $12.’, /[[:space:]]/)        Price<< >>$12.
show_regexp(‘Price $12.’, /[[:punct:]aeiou]/)   Pr<<i>>ce $12.

           POSIX Character Classes
            Alphanumeric[:alnum:]
            Uppercase or lowercase letter[:alpha:]
            Blank and tab[:blank:]
            Control characters (at least 0×00–0x1f, 0x7f)[:cntrl:]
            Digit[:digit:]
            Printable character excluding space[:graph:]
            Lowercase letter[:lower:]
            Any printable character (including space)[:print:]
            Printable character excluding space and alphanumeric[:punct:]
            Whitespace (same as \s)[:space:]
            Uppercase letter[:upper:]
            Hex digit (0–9, a–f, A–F)[:xdigit:]

sequence c1 -c2 represents all the characters between c1 and c2
a = ‘see [Design Patterns-page 123]‘
show_regexp(a, /[A-F]/)            see [<<D>>esign Patterns-page 123]
show_regexp(a, /[A-Fa-f]/)   s<<e>>e [Design Patterns-page 123]
show_regexp(a, /[0-9]/)      see [Design Patterns-page <<1>>23]                       
show_regexp(a, /[0-9][0-9]/)    see [Design Patterns-page <<12>>3]

If you want to include the literal characters ] and – within a character class, they must appear at the start.
Put a ^ immediately after the opening bracket to negate a character class
a = ‘see [Design Patterns-page 123]‘
show_regexp(a, /[]]/)        → see [Design Patterns-page 123<<]>>
show_regexp(a, /[-]/)        → see [Design Patterns<<->>page 123]
show_regexp(a, /[^a-z]/)     → see<< >>[Design Patterns-page 123]
show_regexp(a, /[^a-z\s]/)   → see <<[>>Design Patterns-page 123]

                      Table 5.1. Character class abbreviations
Sequence As [ . . . ]        Meaning
         [0-9]               Digit character   \d
         [^0-9]              Any character except a digit   \D
         [\s\t\r\n\f]        Whitespace character   \s
         [^\s\t\r\n\f]       Any character except whitespace   \S
         [A-Za-z0-9_]        Word character   \w
         [^A-Za-z0-9_]       Any character except a word character   \W

show_regexp(‘It costs $12.’, /\s/)   It<< >>costs $12.
show_regexp(‘It costs $12.’, /\d/)   It costs $<<1>>2.

a period ( . ) appearing outside brackets represents any character except a newline
a = ‘It costs $12.’
show_regexp(a, /c.s/)   It <<cos>>ts $12.
show_regexp(a, /./)     <<I>>t costs $12.
show_regexp(a, /\./)    It costs $12<<.>>

Repetition * ? {m,n}
       matches zero or more occurrences of r.   r*
       matches one or more occurrences of r.    r+
       matches zero or one occurrence of r.     r?
       matches at least “m” and at most “n” occurrences of r.   r{m,n}
       matches at least “m” occurrences of r.    r{m,}
       matches exactly “m” occurrences of r.     r{m}
       matches zero or more occurrences of previous regular expression(non greedy) *?
       matches one or more occurrences of previous regular expression(non greedy) +?

a = "The moon is made of cheese"
show_regexp(a, /\w+/)             <<The>> moon is made of cheese  
show_regexp(a, /\s.*\s/)           The<< moon is made of >>cheese
show_regexp(a, /\s.*?\s/)          The<< moon >>is made of cheese
show_regexp(a, /[aeiou]{2,99}/)    The m<<oo>>n is made of cheese
show_regexp(a, /mo?o/)             The <<moo>>n is made of cheese

Alternation |
a = "red ball blue sky"
show_regexp(a, /d|e/)                  r<<e>>d ball blue sky
show_regexp(a, /al|lu/)                red b<<al>>l blue sky
show_regexp(a, /red ball|angry sky/)   <<red ball>> blue sky

Grouping ()
Everything within the group is treated as a single regular expression.

show_regexp(‘banana’, /an*/)         b<<an>>ana
show_regexp(‘banana’, /(an)*/)       <<>>banana
show_regexp(‘banana’, /(an)+/)       b<<anan>>a
a = ‘red ball blue sky’
show_regexp(a, /blue|red/)             <<red>> ball blue sky
show_regexp(a, /(blue|red) \w+/)       <<red ball>> blue sky
show_regexp(a, /(red|blue) \w+/)       <<red ball>> blue sky
show_regexp(a, /red|blue \w+/)         <<red>> ball blue sky
show_regexp(a, /red (ball|angry) sky/)       no match
a = ‘the red angry sky’
show_regexp(a, /red (ball|angry) sky/)       the <<red angry sky>>

within the pattern, the sequence \1 refers to the match of the ?rst group, \2 the second group, and so on. Outside the pattern, the special variables $1, $2, and so on, serve the same purpose.
"12:50am" =~ /(\d\d):(\d\d)(..)/     0
"Hour is #$1, minute #$2"            "Hour is 12, minute 50"
"12:50am" =~ /((\d\d):(\d\d))(..)/   0
"Time is #$1"                        "Time is 12:50"
"Hour is #$2, minute #$3"            "Hour is 12, minute 50"
"AM/PM is #$4"                       "AM/PM is am"

look for various forms of repetition.
# match duplicated letter
show_regexp(‘He said "Hello"’, /(\w)\1/)   He said "He<<ll>>o"
# match duplicated substrings
show_regexp(‘Mississippi’, /(\w+)\1/)      M<<ississ>>ippi

match delimiters
show_regexp(‘He said "Hello"’, /(["']).*?\1/)   He said <<"Hello">>
show_regexp("He said ‘Hello’", /(["']).*?\1/)   He said <<’Hello’>>

Pattern-Based Substitution
String#sub performs one replacement
String#gsub replaces every occurrence of the match

a = "the quick brown fox"
a.sub(/[aeiou]/, ‘*’)      "th* quick brown fox"
a.gsub(/[aeiou]/, ‘*’)     "th* q**ck br*wn f*x"
a.sub(/\s\S+/, ”)         "the brown fox"
a.gsub(/\s\S+/, ”)        "the"

block
a = "the quick brown fox"
a.sub(/^./) {|match| match.upcase }         "The quick brown fox"
a.gsub(/[aeiou]/) {|vowel| vowel.upcase }   "thE qUIck brOwn fOx"

def mixed_case(name)
  name.gsub(/\b\w/) {|first| first.upcase }
end
mixed_case("fats waller")               "Fats Waller"
mixed_case("louis armstrong")           "Louis Armstrong"
mixed_case("strength in numbers")       "Strength In Numbers"

Backslash Sequences in the Substitution
"fred:smith".sub(/(\w+):(\w+)/, ‘\2, \1′)   "smith, fred"
"nercpyitno".gsub(/(.)(.)/, ‘\2\1′)         "encryption"
\& (last match),
\+ (lastmatched group),
\` (string prior to match),
\’ (string after match),
\\ (a literal backslash)

str = ‘a\b\c’                "a\b\c"
str.gsub(/\\/, ‘\\\\\\\\’)   "a\\b\\c"

or
str = ‘a\b\c’            "a\b\c"
str.gsub(/\\/, ‘\&\&’)   "a\\b\\c"

or
str = ‘a\b\c’               "a\b\c"
str.gsub(/\\/) { ‘\\\\’ }   "a\\b\\c"

example:
n modi?er(japanese)
    def unescapeHTML(string)
      str = string.dup
      str.gsub!(/&(.*?);/n) {
         match = $1.dup
         case match
         when /\Aamp\z/ni           then ‘&’
         when /\Aquot\z/ni          then ‘"’
         when /\Agt\z/ni            then ‘>’
         when /\Alt\z/ni            then ‘<’
         when /\A#(\d+)\z/n         then Integer($1).chr
         when /\A#x([0-9a-f]+)\z/ni then $1.hex.chr
         end
      }
      str
    end
    puts unescapeHTML("1&lt;2 &amp;&amp; 4&gt;3")
    puts unescapeHTML("&quot;A&quot; = &#65; = &#x41;")
produces:
    1<2 && 4>3
    "A" = A = A

Object-Oriented Regular Expressions
re = /(\d+):(\d+)/     # match a time hh:mm
md = re.match("Time: 12:34am")
                        → MatchData
md.class
md[0]         # == $&   → "12:34"
md[1]         # == $1   → "12"
md[2]         # == $2   → "34"
md.pre_match # == $`    → "Time: "
md.post_match # == $’   → "am"

re = /(\d+):(\d+)/     # match a time hh:mm
md1 = re.match("Time: 12:34am")
md2 = re.match("Time: 10:30pm")
md1[1, 2]   → ["12", "34"]
md2[1, 2]   → ["10", "30"]

re = /(\d+):(\d+)/
md1 = re.match("Time: 12:34am")
md2 = re.match("Time: 10:30pm")
[ $1, $2 ]   # last successful match       ["10", "30"]
$~ = md1
[ $1, $2 ]   # previous successful match   ["12", "34"]


Regex Characters List
:
.          any character except newline
[ ]        any single character of set
[^ ]       any single character NOT of set
*          0 or more previous regular expression
*?         0 or more previous regular expression(non greedy)
+          1 or more previous regular expression
+?         1 or more previous regular expression(non greedy)
?          0 or 1 previous regular expression
|          alternation
( )        grouping regular expressions
^          beginning of a line or string
$          end of a line or string
{m,n}      at least m but most n previous regular expression
{m,n}?     at least m but most n previous regular expression(non greedy)
\A         beginning of a string
\b         backspace(0×08)(inside[]only)
\b         word boundary(outside[]only)
\B         non-word boundary
\d         digit, same as[0-9]
\D         non-digit
\S         non-whitespace character
\s         whitespace character[ \t\n\r\f]
\W         non-word character
\w         word character[0-9A-Za-z_]
\z         end of a string
\Z         end of a string, or before newline at the end
(?# )      comment
(?: )      grouping without backreferences
(?= )      zero-width positive look-ahead assertion
(?! )      zero-width negative look-ahead assertion
(?ix-ix)   turns on/off i/x options, localized in group if any.
(?ix-ix: ) turns on/off i/x options, localized in non-capturing group.

Special Character Classes:
[:alnum:]   alpha-numeric characters
[:alpha:]   alphabetic characters
[:blank:]   whitespace – does not include tabs, carriage returns, etc
[:cntrl:]   control characters
[:digit:]   decimal digits
[:graph:]   graph characters
[:lower:]   lower case characters
[:print:]   printable characters
[:punct:]   punctuation characters
[:space:]   whitespace, including tabs, carriage returns, etc
[:upper:]   upper case characters
[:xdigit:]  hexadecimal digits

发表在 Ruby on Rails | 留下评论

Learning Ruby 4, Number, String and Range

Numbers
Fixnum Bignum
123456                  => 123456   # Fixnum
0d123456                => 123456   # Fixnum
123_456                 => 123456   # Fixnum – underscore ignored
-543                    => -543     # Fixnum – negative number
0xaabb                  => 43707    # Fixnum – hexadecimal
0377                    => 255      # Fixnum – octal
-0b10_1010              => -42      # Fixnum – binary (negated)
123_456_789_123_456_789 => 123456789123456789 # Bignum

?a       => 97  # ASCII character
?
      => 10  # code for a newline (0x0a)
?\C-a    => 1   # control a = ?A & 0x9f = 0×01
?\M-a    => 225 # meta sets bit 7
?\M-\C-a => 129 # meta and control a
?\C-?    => 127 # delete character

iterators
    3.times        { print "X "}
    1.upto(5)      {|i| print i, " " }
    99.downto(95)  {|i| print i, " " }
    50.step(80, 5) {|i| print i, " " }
produces:
    X X X 1 2 3 4 5 99 98 97 96 95 50 55 60 65 70 75 80

Strings
Double-quoted & single-quoted strings
'escape using "\\"'   escape using "\"
                    →
'That\'s right'       That's right
                    →
"Seconds/day: #{24*60*60}"      Seconds/day: 86400
                              →
"#{'Ho! '*3}Merry Christmas!"   Ho! Ho! Ho! Merry Christmas!
                              →
"This is line #$."              This is line 3
                              →
#{ expr }. If the code is just a global variable, a class variable, or an instance variable,you can omit the braces.
    puts  "now is #{ def the(a)
                        'the ' + a
                      end
                      the('time')
                    } for all good coders…"
produces:
    now is the time for all good coders…

to construct string literals
%q/general single-quoted string/   general single-quoted string
                                 →
%Q!general double-quoted string!   general double-quoted string
                                 →
%Q{Seconds/day: #{24*60*60}}       Seconds/day: 86400
                                 →
string = <<END_OF_STRING
    The body of the string
    is the input lines up to
    one ending with the same
    text that followed the '<<'
END_OF_STRING

delimiter
 If it is an opening bracket “[”, brace “{”, parenthesis “(”, or less-than sign “<”, the string is read until the matching close symbol is found. Otherwise the string is read until the next occurrence of the same
1.8 delimiter. The delimiter can be any nonalphanumeric or nonmultibyte character.

mins, secs = length.split(/:/)
mins, secs = length.scan(/\d+/)

class WordIndex
  def initialize
    @index = {}
  end
  def add_to_index(obj, *phrases)
    phrases.each do |phrase|
      phrase.scan(/\w[-\w']+/) do |word|   # extract each word
        word.downcase!
        @index[word] = [] if @index[word].nil?
        @index[word].push(obj)
      end
    end
  end
  def lookup(word)
    @index[word.downcase]
  end
end
 the exclamation mark at the end of the ?rst downcase! method is an indication that the method will modify the receiver in place

Ranges
Ranges as Sequences
The two-dot form creates an inclusive range, and the three-dot form creates a range that excludes the speci?ed high value.
1..10
'a'..'z'
my_array = [ 1, 2, 3 ]
0…my_array.length

(1..10).to_a          [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
                    →
('bar'..'bat').to_a   ["bar", "bas", "bat"]
                    →

digits = 0..9
digits.include?(5)                   true
                                   →
digits.min                           0
                                   →
digits.max                           9
                                   →
digits.reject {|i| i < 5 }           [5, 6, 7, 8, 9]
                                   →
digits.each {|digit| dial(digit) }   0..9
   
                 
         
spaceship operator
<=> compares two values, returning −1, 0, or +1 depending on whether the ?rst is less than, equal to, or greater than the second.

class VU
  include Comparable
  attr :volume
  def initialize(volume)  # 0..9
    @volume = volume
  end
  def inspect
    '#' * @volume
  end
  # Support for ranges
  def <=>(other)
    self.volume <=> other.volume
  end
  def succ
    raise(IndexError, "Volume too big") if @volume >= 9
    VU.new(@volume.succ)
  end
end

medium_volume = VU.new(4)..VU.new(7)
medium_volume.to_a                    [####, #####, ######, #######]
                                    →
medium_volume.include?(VU.new(3))     false
                                    →

Ranges as Conditions

Ranges as Intervals
seeing if some value falls within the interval represented by the range.
(1..10)    === 5         true
                       →
(1..10)    === 15        false
                       →
(1..10)    === 3.14159   true
                       →
('a'..'j') === 'c'       true
                       →
('a'..'j') === 'z'       false

发表在 Ruby on Rails | 留下评论

Learning Ajax 3, Prototype Reference

http://www.sergiopereira.com/articles/prototype.js.html

Chapter 10. Prototype Reference
10.1. Ajax Support

Ajax.Request, Ajax.Updater, and Ajax.PeriodicalUpdaterall of which inherit from Ajax.Base. After that is the Ajax.Responders object, which handles global events related to Ajax calls.

callback
new Ajax.Request('/data.html', {
  method: 'get',
  onComplete: showResponse
});

// alert the returned value
function showResponse(request) {
  alert(request.responseText);
}

callback could also be defined inline.
====>
new Ajax.Request(' /data.xml', {
  method: 'get',
  onComplete: function(request){ alert(request.responseText); }
});

defined for specific HTTP response codes
new Ajax.Request(' /data.xml', {
  method: 'get',
  on404: function(request){ alert('Not found'); },
  on500: function(request){ alert('Server error'); }
});

Ajax Updaters

// <div id="target">(To be replaced)</div>

new Ajax.Updater('target', '/data.html', {method: 'get'});

This next example is the same as above, but it updates the element only if the request was successful and alerts the user if not:
// <div id="target"></div>

new Ajax.Updater({success: 'target'}, '/data.html', {
  method: 'get',
  onFailure: function(request) { alert('Sorry. There was an error.') }
});

Periodical Ajax Updaters
/ <div id="target"></div>

new Ajax.PeriodicalUpdater('target', '/data.html', {
  method: 'get',
  frequency: 2
});

Global Responders
Ajax.Responders.register({
  onCreate: function(  ){
    $('spinner').show(  );
  },
  onComplete: function(  ) {
    if(Ajax.activeRequestCount == 0)
      $('spinner').hide(  );
  }
});

10.2. DOM Manipulation
 $( )
document.getElementById( )
// <p id="one">One</p>
// <p id="two">Two</p>

$('one').toString(  );
// => '[object HTMLParagraphElement]'

$('one','two').toString(  );
// => [object P],[object P]

$($('one')).toString(  );
// => [object HTMLParagraphElement]

$F( )
$F( element ) returns the value of any  field input control
// <input type="text" id="userName" value="Joe Doe">
// <select id="state">
//   <option value="NY">New York</option>
//   <option value="CA" selected="selected">California</option>
// </select>

$F('userName');
// => "Joe Doe"

$F('state');
// => "CA"

Selector
The Selector class (and its accompanying $$( ) method) allows you to reference page elements by their CSS selectors

$$('form#foo input[type=text]').each(function(input) {
  input.setStyle({color: 'red'});
});

// By tag name, including wildcard
$$('strong')
$$('*')

// By id and class
$('#foo')
$$('.bar')

// By combinations of tag, id, and class
$$('strong#foo')
$$('string.bar')
$$('string.bar.baz')
$$('#foo.bar')
$$('.bar#foo')
$$('#foo.bar.baz')
$$('strong#foo.bar')
$$('strong.bar#foo')

// By ancestors
$$('#foo strong *')
$$('strong#foo span')

// By attribute existence
$$('h1[class]')

// By attribute value and negated value
$$('a[href="#"]')
$$('a[href!=#]')

// By whitespace-tokenized attribute value
$$('a[class~="internal"]')

// By hyphen-tokenized attribute value
$$('*')

// By multiple attribute conditions
$$('a[class~=external][href="#"]')

// Combining multiple expressions
$('#foo', '#bar')

 Examples
// Create a Selector instance
fooFinder = new Selector('.foo');

// Find all elements in the document with the class 'foo'
fooFinder.findElements(  );

// Find all elements within the 'container' element with the class 'foo'
fooFinder.findElements($('container'));

// Determine whether the 'bar' element has the class 'foo'
fooFinder.match($('bar'));

// Find all elements with class 'foo' from the descendants of 'container'
Selector.matchElements($('container').descendants(  ), '.foo');

// Find the first element with the class 'foo' from the descendants of 'container'
Selector.findElement($('container').descendants(  ), '.foo');

// Find the second element with the class 'foo' from the descendants of 'container'
Selector.findElement($('container').descendants(  ), '.foo', 1);

// Find all elements with the class 'foo' within 'container'
Selector.findChildElements($('container'), ['.foo']);

// Find all elements with the class 'foo' or the class 'bar' within 'container'
Selector.findChildElements($('container'), ['.foo', '.bar']);

Element Methods
Element.toggle('target');
var myElement = $('target2');
Element.update(myElement, 'Hello');

Alternatively
$('target').toggle(  );
var myElement = $('target2');
myElement.update('Hello');

$('target').update('Hello').addClassName('big').show(  );

10.2.5. class Element.ClassNames
10.2.6. Inserting Content

// <span id="name">Douglas</span>
new Insertion.Before('name', 'Hello, ');
new Insertion.Top('name', 'Scott ');
new Insertion.Bottom('name', ' Raymond');
new Insertion.After('name', '.');

10.2.7. Element Positioning

10.2.8. Form Observers

10.3. Core Extensions
10.3.1. Array Extensions
10.3.2. Hashes
10.3.3. Ranges
10.3.4. Enumerable
…..

发表在 Ruby on Rails | 留下评论

Learning Ruby 3, Containers, Blocks, and Iterators

with<Programming Ruby>
Chapter 4
Containers, Blocks, and Iterators

Containers

Arrays
a = [ 3.14159,  "pie", 99 ]
a.class         Array
           →
a.length        3
           →
a[0]            3.14159
           →

b = Array.new
b.length   →0
b[0] = "second"
b[1] = "array"
b          → ["second", "array"]

   Positive → 0                                         Negative
                      1     2     3     4    5      6
    indices                                        −1 ← indices
              −7     −6    −5    −4    −3   −2
          a = “ant” “bat” “cat” “dog” “elk” “?y” “gnu”
      a[2] →              “cat”
     a[-3] →                          “elk”
  a[1..3] →         “bat” “cat” “dog”
a[-3..-1] →                           “elk” “?y” “gnu”
 a[4..-2] →                           “elk” “?y”

the index to [ ]= is two numbers (a start and a length) or a range
a = [ 1, 3, 5, 7, 9 ]   [1, 3, 5, 7, 9]
                      →
a[2, 2] = ’cat’         [1, 3, "cat", 9]
                      →
                        [1, 3, "dog", "cat", 9]
a[2, 0] = ’dog’       →
                        [1, 9, 8, 7, "dog", "cat", 9]
a[1, 1] = [ 9, 8, 7 ] →
a[0..3] = []            ["dog", "cat", 9]
                      →
a[5..6] = 99, 98        ["dog", "cat", 9, nil, nil, 99, 98]
                      →

Hashes (associative arrays, maps, or dictionaries)
h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' }
h.length   →3
h['dog']   → "canine"
h['cow'] = 'bovine'
h[12]    = 'dodecine'
h['cat'] = 99
h          → {"cow"=>"bovine", "cat"=>99, 12=>"dodecine",
               "donkey"=>"asinine", "dog"=>"canine"}

Implementing a SongList Container

class SongList
  def append(song)
    @songs.push(song)
    self
  end
end

class SongList
  def delete_first
    @songs.shift
  end
  def delete_last
    @songs.pop
  end
end

class SongList
  def [](index)
    @songs[index]
  end
end

Blocks and Iterators

class SongList
  def with_title(title)
    @songs.find {|song| title == song.name }
  end
end
find is an iterator
iterator: a method that invokes a block of code repeatedly
    def three_times
      yield
      yield
      yield
    end
    three_times { puts "Hello" }
produces:
    Hello
    Hello
    Hello

i1, i2 = 1, 1 # parallel assignment (i1 = 1 and i2 = 1)

def fib_up_to(max)
  i1, i2 = 1, 1        # parallel assignment (i1 = 1 and i2 = 1)
  while i1 <= max
    yield i1
    i1, i2 = i2, i1+i2
  end
end
fib_up_to(1000) {|f| print f, " " }

if they appear for the ?rst time in the block, they’re local to the block. If instead they ?rst appeared outside the block, the variables will be shared between the block and the surrounding environment.
a = [1, 2]
b = 'cat'
a.each {|b| c = b * a[1] }
a                 [1, 2]
              →
b                 2
              →
defined?(c)       nil
              →

class Array
  def find
    for i in 0…size
      value = self[i]
      return value if yield(value)
    end
    return nil
  end
end
[1, 3, 5, 7, 9].find {|v| v*v > 30 }   7
                                     →
[ 1, 3, 5, 7, 9 ].each {|i| puts i }
["H", "A", "L"].collect {|x| x.succ } ["I", "B", "M"]

[1,3,5,7].inject(0) {|sum, element| sum+element}           16
                                                         →
[1,3,5,7].inject(1) {|product, element| product*element}   105
                                                         →

if inject is called with no parameter,it uses the ?rst element of the collection as the initial value and starts the iteration with the second value.
[1,3,5,7].inject {|sum, element| sum+element}           16
                                                      →
[1,3,5,7].inject {|product, element| product*element}   105
                                                      →

Blocks for Transactions
class File
  def File.open_and_process(*args)
    f = File.open(*args)
    yield f
    f.close()
  end
end

 *args, meaning “collect the actual parameters passed to the method into an array named args

Blocks Can Be Closures

songlist = SongList.new
class JukeboxButton < Button
  def initialize(label, &action)
    super(label)
    @action = action
  end
  def button_pressed
    @action.call(self)
  end
end
start_button = JukeboxButton.new("Start") { songlist.start }
pause_button = JukeboxButton.new("Pause") { songlist.pause }
                                                                         &action,Ruby looks for a code block whenever that method is called. That code block is converted to an object of class Proc and assigned to the parameter. You can then treat the parameter as any other variable. In our example, we assigned it to the instance variable @action. When the callback method button_pressed is invoked, we use the Proc#call method on that object to invoke the block.

method lambda, which converts a block to a Proc object.

def n_times(thing)
  return lambda {|n| thing * n }
end
p1 = n_times(23)
p1.call(3)   → 69
p1.call(4)   → 92
p2 = n_times("Hello ")
p2.call(3)   → "Hello Hello Hello "

发表在 Ruby on Rails | 留下评论

Learning Ajax 3, form and form observer

with <ajax on rails>

make fake form with the combination of link_to_remote and :submit option

3.4 Ajax Forms

form_for
remote_form_for

3.5

<%= form_tag :action => 'reverse' %>
  <p>Text to reverse: <%= text_field_tag 'text_to_reverse' %></p>
  <p id="reversed2"></p>
  <p><%= submit_to_remote 'submit', 'Reverse!',
          :update => 'reversed2',
          :url => { :action => 'reverse' } %></p>
<%= end_form_tag %>
the form can be submitted both via Ajax or non-Ajax methods. Consider this variation with two submit buttons
a common application for submit_to_remote would be checking a form for validity before actually submitting it for creation.

Form Observers

If :with doesn't contain an equal sign character (=), it's interpreted as a name for the parameterso foo becomes 'foo='+value. But if :with does contain an equal sign, it remains untouchedso foo=bar remains foo=bar.

:function => "alert(value)"

Observing an Entire Form
<form id="myForm">
  <p>Text to reverse: <%= text_field_tag 'text_to_reverse' %></p>
  <p id="reversed"></p>
</form>

<%= observe_form 'myForm',
      :update => "reversed",
      :url    => { :action => 'reverse' } %>
an observer for the form with the ID myForm, so that whenever any of its fields change, an Ajax.Updater call is created accordingly, which passes the serialized form values to the server.

发表在 Ruby on Rails | 留下评论

Learning Ajax 2, url, link and button

with <Ajax on Rails>
S2.3. Bringing Rails into the Picture

complex url_for example:
url_for :only_path => false, :protocol => ‘gopher:// ‘,
  :host => ‘example.com’, :controller =&gt; ‘chapter2′,
  :action => ‘myresponse’, :trailing_slash => true, :foo => ‘bar’,
  :anchor => ‘baz’
#=> ‘gopher://example.com/chapter2/myresponse?foo=bar/#baz’

ajax on rails(aor) alert:
<p><%= link_to_remote "Alert with javascript Helper", :url =>
   "/chapter2/myresponse", :success => "alert(request.responseText)" %></p>

aor insert:
<p><%= link_to_remote "Update  with javascript Helper", :url =>
  {:action => "myresponse"}, :update => "response5" %></p>
<p id="response5"></p>

Chapter 3. Introducing Prototype

3.2 Ajax Links

:method => :delete
<%= link_to "Delete", "/people/1", :method => :delete %>

==>
<a href="/people/1"
  onclick="var f = document.createElement(‘form’);
           f.style.display = ‘none’;
           this.parentNode.appendChild(f);
           f.method = ‘POST’;
           f.action = this.href;
           var m = document.createElement(‘input’);
           m.setAttribute(‘type’, ‘hidden’);
           m.setAttribute(‘name’, ‘_method’);
           m.setAttribute(‘value‘, ‘delete’);
           f.appendChild(m);
           f.submit(  );
           return false;">Delete</a>

Return false;
<a href="#"
   onclick="new Ajax.Updater(‘current_time’, ‘/chapter3/get_time’,
               {asynchronous:true, evalScripts:true});
            return false;">Check Time</a>
<div id="current_time"></div>
The link will only be followed if the expression evaluates true (or if the user has javascript turned off). That’s why the link_to_remote helper puts return false at the end of the onclick attribute.

Callbacks:
<%= link_to_remote "Check Time",
    :update   => ‘current_time’,
    :url      => { :action => ‘get_time’ },
    :before   => "$(‘indicator’).show(  )",
    :success  => "$(‘current_time’).visualEffect(‘highlight’)",
    :failure  => "alert(‘There was an error. ‘)",
    :complete => "$(‘indicator’).hide(  )" %>
<span id="indicator" style="display: none;">Loading…</span>
<div id="current_time"></div>

hide( ) and show( )
for an element to be dynamically shown via javascript, its CSS display: none property must be defined inline

this won’t work:
<style type="text/css">
  #indicator { display: none; }
</style>
<div id="indicator">Hidden DIV</div>
<script type="text/javascript">
  $("indicator").show(  ); // won’t work
</script>

But this will work:

<div id="indicator" style="display: none">Hidden DIV</div>
<script type="text/javascript">
  $("indicator").show(  ); // will work
</script>

:condition
<li><%= check_box_tag ‘checkbox’ %> Thing #1</li>
<%= link_to_remote "Delete checked items",
    :condition => "$(‘checkbox’).checked",
    :url       => { :action => ‘delete_items’ } %>

:submit
it allows you to simulate a form submission. By providing the ID of a page element, any fields contained in it will be sent along with the request.
<div id="fakeForm">
  <input type="text" name="foo" value="bar" />
</div>
<%= link_to_remote "Submit fake form",
       :submit   => "fakeForm",
       :url      => { :action => ‘repeat’ },
       :complete => "alert(request.responseText)" %>

nested forms

<form id="myForm">
  <input type="text" name="text_to_reverse" id="text_to_reverse" />
  <%= link_to_remote "Reverse field",
       :url      => { :action => ‘reverse’ },
       :submit   => "myForm",
       :complete => "$(‘text_to_reverse’).value=request.responseText" %>
  <input type="submit" />
</form>

:with
<%= link_to_remote "Link with params",
       :url      => { :action => ‘repeat’ },
       :complete => "alert(request.responseText)",
       :with     => "’foo=bar’" %>
two sets of quote marks. javascript expression

include references to javascript variables or DOM elements:
<input id="myElement" type="text" value="bar" />
<%= link_to_remote "Link with dynamic params",
       :url      => { :action => ‘repeat’ },
       :complete => "alert(request.responseText)",
       :with     => "’foo=’+escape($F(‘myElement’))" %>
escape it (so that it can safely be included in a URL query string)

link_to_function
<%= link_to_function "Toggle DIV", "$(‘indicator’).toggle(  )" %></p>
toggle( ), which hides and shows elements on the page.

button_to_function
<%= button_to_function "Greet", "alert(‘Hello world!’)" %>

combine with remote_function
<%= button_to_function "Check Time",
      remote_function(:update => "current_time",
        :url => { :action => ‘get_time’ }) %>

DIY button_to_remote
def button_to_remote(name, options = {})
  button_to_function(name, remote_function(options))
end
==>
<%= button_to_remote "Get Time Now",
      :update => "current_time",
      :url    => { :action => ‘get_time’ } %>

发表在 Ruby on Rails, 站长文档 | 留下评论

Ruby on Rails, Layout

<%= render :partial => "person" %>

the partial is named "person," the main template will look for an instance variable @person, and pass it to the partial as a local variable, person.if the instance variable doesn't match the name of the partial, you'd explicitly pass it, like this:

<%= render :partial => "person", :locals => { :person => @scott } %>
All the key/value pairs in the :locals hash will be made into local variables for the partial.

<%= render :partial => "person", :collection => @people %>
In this example, the main template has an array @people that will be looped through, passing a local variable person to the partial.

render :layout => false
def reverse
  @reversed_text = params[:text_to_reverse].reverse
  render :layout => false
end

发表在 Ruby on Rails | 留下评论

Learning Ajax 1, Prototype

with <Ajax on Rails>
Chapter 2 .Getting Our Feet Wet

S2.1. The Old-Fashioned Way
<p><a href="#" onclick="asyncAlert(  )">Call async server-side</a></p>
<script type="text/javascript">
  function asyncAlert(  ) {
    //Call server(IE-safe)
    function getRequestObject(  ) {
      try { return new XMLHttpRequest(  ) } catch (e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP") } catch (e) {}
      try { return new ActiveXObject("Microsoft.XMLHTTP") } catch (e) {}
      return false
    }
    var request = getRequestObject(  );
    request.open('get', '/chapter2/myresponse');
    //we define a function that checks to see if readyState is 4 (which means the request is complete)
    request.onreadystatechange = function(  ) {
      if(request.readyState==4) alert(request.responseText);
    }
    request.send(  );
  }
</script>

s2.2. javascript Libraries and Prototype
Prototype Way:
<script src="/javascripts/prototype.js" type="text/javascript">
</script>
<p><a href="#" onclick="prototypeAlert(  );">Call with Prototype</a></p>
<script type="text/javascript">
 function prototypeAlert(  ) {
  new Ajax.Request('/chapter2/myresponse', { onSuccess: function(request) {
   alert(request.responseText);
  }})
 }
</script>

Update a element's innerHTML
<p><a href="#" onclick="updateElement(  )">Update element </a></p>
<p id="response"></p>
<script type="text/javascript">
  function updateElement(  ) {
    new Ajax.Request('/chapter2/myresponse', { onSuccess: function(request) {
      $('response').update(request.responseText);
    }})
  }
</script>

================>
<p><a href="#" onclick="updater(  )">Update with Ajax.Updater</a></p>
<p id="response2"></p>
<script type="text/javascript">
  function updater(  ) {
    new Ajax.Updater('response2', '/chapter2/myresponse');
  }
</script>

insert content:
<p><a href="#" onclick="appendToElement(  )">Append to element</a></p>
<p id="response3"></p>
<script type="text/javascript">
  function appendToElement(  ) {
    new Ajax.Updater('response3', '/chapter2/myresponse',
      { insertion:Insertion.Bottom });
  }
</script>
//insertions: Before, Top, Bottom, and After.

===============>
<p><a href="#" onclick="new Ajax.Updater('response4',
'/chapter2/myresponse', { insertion:Insertion.Bottom });">
Append to element</a></p>
<p id="response4"></p>

发表在 Ruby on Rails | 留下评论

Learning Ruby 2 Classes, Objects, and Variables

with <Programming Ruby 2nd>
Chapter 3
Classes, Objects, and Variables
Class
class Song
  def initialize(name, artist, duration)
    @name     = name
    @artist   = artist
    @duration = duration
  end
end
initialize, which is always private
Instance variables are accessible to all the methods in an object, and each object has its own copy of its instance variables.

song.inspect → #<Song:0x1c7ca8 @name="Bicylops", @duration=260,
               @artist="Fleck">

In Ruby, classes are never closed.
class Song
  def to_s
    "Song: #@name–#@artist (#@duration)"
  end
end

Inheritance and Messages
class KaraokeSong < Song
      def initialize(name, artist, duration, lyrics)
        super(name, artist, duration)
        @lyrics = lyrics
      end
   
    def to_s
          super + " [#@lyrics]"
    end
end

If you don’t specify a parent when de?ning a class, Ruby supplies class Object as a default.

Ruby classes can include the functionality of any number of mixins (a mixin is like a partial class de?nition). This provides a controlled multiple-inheritance-like capability
with none of the drawbacks.

Objects and Attributes
class Song
  def name
    @name
  end
  def artist
    @artist
  end
  def duration
    @duration
  end
end

convenient shortcut:
class Song
  attr_reader :name, :artist, :duration
end
Symbol object — You can think of :artist as meaning the name of the variable artist, and plain artist as meaning the value of the variable.

Writable Attributes
class Song
  def duration=(new_duration)
    @duration = new_duration
  end
end
shortcut:
class Song
  attr_writer :duration
end

Virtual Attributes
class Song
  def duration_in_minutes
    @duration/60.0   # force floating point
  end
  def duration_in_minutes=(new_duration)
    @duration = (new_duration*60).to_i
  end
end
To the outside world, duration_in_minutes seems to be an attribute like any other. Internally, though, it has no corresponding instance variable.

Attributes, Instance Variables, and Methods
An attribute is just a method.
The internal state is held in instance variables. The external state is exposed through methods we’re calling attributes. And the other actions your class can perform are just regular methods.

Class Variables
A class variable is shared among all objects of a class.
class variables must be initialized before they are used.
class Song
  @@plays = 0
  def initialize(name, artist, duration)
    @name     = name
    @artist   = artist
    @duration = duration
    @plays    =0
  end
  def play
    @plays += 1   # same as @plays = @plays + 1
    @@plays += 1
    "This song: #@plays plays. Total #@@plays plays."
  end
end

Class Methods
class Example
  def instance_method      # instance method
  end
  def Example.class_method # class method
  end
end

class SongList
  MAX_TIME = 5*60           #  5 minutes
  def SongList.is_too_long(song)
    return song.duration > MAX_TIME
  end
end

Class Method De?nitions
class Demo
  def Demo.meth1
    # …
  end
  def self.meth2
    # …
  end
  class <<self
    def meth3
      # …
    end
  end
end

Singletons and Other Constructors
class MyLogger
  private_class_method :new #making MyLogger’s new method private
  @@logger = nil
  def MyLogger.create #provide a class method
    @@logger = new unless @@logger
    @@logger
  end
end

Access Control
• Public methods
• Protected methods
• Private methods
If a method is protected, it may be called by any instance of the de?ning class or its subclasses. If a method is private, it may be called only within the context of the calling object—it is never possible to access another object’s private methods directly, even if the object is of the same class as the caller.

Specifying Access Control
private         # subsequent methods will be 'private'
    def method3
      #…
    end
#….

or

class MyClass
  def method1
  end
  # … and so on
  public    :method1, :method4
  protected :method2
  private   :method3
end

class Account
  attr_reader :balance # accessor method 'balance'
  protected :balance   # and make it protected

Variables
person1 = "Tim"
person2 = person1
person1[0] = 'J'
person1       "Jim"
          →
person2       "Jim"
          →
variable isn't an object
variables hold references to objects, not the objects themselves.

you could avoid aliasing by using the dup method of String, which creates a new String object with identical contents.
    person1 = "Tim"
    person2 = person1.dup
    person1[0] = "J"
    person1   → "Jim"
    person2   → "Tim"
You can also prevent anyone from changing a particular object by freezing it

发表在 Ruby on Rails | 留下评论