Rails 3学習ノート1、中秋休暇


コードを書くのは久しぶりで、手がかゆくてたまらない.間もなく来る長期休暇に直面して、Rails 3をよく勉強するつもりで、自分のRails 2も菜鳥のレベルであることを考慮して、まず態度を正して、よく勉強して、毎日向上します.次に学習方法論は依然として戦争の中で戦争を学び、まず会社の内部プロジェクトを持って刀を切った.
くだらないことは言わないで、
参照
Terminal=》ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]
OK、Rails 3の要求に合って、Gemsを更新します...
まずrailsコマンドのヘルプrails-hを見て、何があるか見てみましょう.
参照
Usage:
  rails new APP_PATH [options]
  -J, [--skip-prototype]      # Skip Prototype files
  -T, [--skip-test-unit]      # Skip Test::Unit files
ええ、Prototypeは私のもっとよく知っているJqueryに変えて、Test::UnitはRspecに変えて、よしこのようにします
参照
rails new Capricorn -TJ
mate .
コード生成が完了し、public/javascripts/次のcontrolsを見てみました.js,dragdrop.js,effects.js,prototype.jsはありません.同時にtestディレクトリもありません.
2つ目は、Gemfileを処理することです.これは理解しやすいです.RubyのMavenです.
gem 'unicorn'
gem 'haml-rails'
gem 'jquery-rails'
group :development, :test do
  gem "rspec-rails", ">= 2.0.0.beta.22"
  gem 'autotest'
  gem 'rails3-generators'
  gem 'factory_girl_rails'
  gem 'webrat'
end

unicornはMongrelのようなもので、socketとkill-USR 2 master_が特徴です.pid masterのNginxのような起動方法が気に入りました.
haml-railsとjquery-railsはrails 3-generatorsから分離されており、Rails 3とHaml、Jqueryの特別な統合に便利です.
rspec-railsは言うまでもありません.
Autotestはコードの変更を自動的に監視し、テストを自動的に実行するので、Command+tのTerminalウィンドウだけでいいです.
rails 3-generatorsの存在はfactoryのためです.girl_Rails,後者はRails 3が持参したfixturesを置き換える.
webratも何も言うことはありません.
うんてん
参照
bundle install
依存関係の構成
rspecのインストール
参照
rails g rspec:install
{
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  autotest
      create  autotest/discover.rb
}
Jqueryのインストール
参照
rails g jquery:install
{
      remove  public/javascripts/controls.js
      remove  public/javascripts/dragdrop.js
      remove  public/javascripts/effects.js
      remove  public/javascripts/prototype.js
      create  public/javascripts/jquery.min.js
      create  public/javascripts/jquery.js
      create  public/javascripts/rails.js
}
factoryの設定girl、アプリケーションを変更します.rb、追加
config.generators do |g|
  g.fixture_replacement :factory_girl, :dir => "spec/factories"
end

rspec_の変更helper.rb、置換
config.fixture_path = "#{::Rails.root}/spec/factories"

次に、本格的にやるべきで、まずユーザーログインモジュールをやります.
参照
rails g model User login:string name:string email:string crypted_password:string salt:string
出力結果の表示
参照
      invoke  active_record
      create    db/migrate/20100924033208_create_users.rb
      create    app/models/user.rb
      invoke    rspec
      create      spec/models/user_spec.rb
      invoke      factory_girl
      create        spec/factories/users.rb
額、結果から見ると、RspecとFactory_girlは構成OKです.
JavaのTDDの経験から教えてもらい、まずはuser_からspec.rbが手を打つ.ええと、ルビーコードを書くのはあまり力がありませんね.千言万語は何から言えばいいか分かりませんが、TMDはまずJAVAの経験でカバーしましょう.他の人のコードがどのように書かれているかを見てみましょう.写すことができたら写してください.生きている人はおしっこを我慢できません.ローマも一日で建てられるわけではありません.ゆっくりしてください.

  describe 'being created' do
    before do
      @user = nil
      @creating_user = lambda do
        @user = create_user
      end
    end

    it 'increments User#count' do
      @creating_user.should change(User, :count).by(1)
    end
  end

  protected

  def create_user(options = {})
    u = User.new({ :login => 'PenG', :email => '[email protected]', :password => 'peng82', :password_confirmation => 'peng82' }.merge(options))
    u.save! if u.valid?
    u
  end

まずこのようにして、運行してみてからにしましょう.
参照
autotest
ええ、Usersが見つかりません.ああ、rake db:migrateとrake db:test:prepareを忘れました.2回連続してControl+cがautotestを中断し、再実行
参照
rake db:migrate
rake db:test:prepare
autotest
ああ!
いつものようなことをしている.
  it 'requires login' do
    lambda do
      create_user(:login => nil).should_not be_valid
    end.should_not change(User, :count)
  end

  describe 'allows legitimate logins:' do
    ['123', '1234567890_234567890_234567890_234567890', 
      '[email protected]'].each do |login_str|
      it "'#{login_str}'" do
        lambda do
          u = create_user(:login => login_str)
          u.errors[:login].should be_empty
        end.should change(User, :count).by(1)
      end
    end
  end

  describe 'disallows illegitimate logins:' do
    ['12', '1234567890_234567890_234567890_234567890_', "tab\t", "newline
", "Iñtërnâtiônàlizætiøn hasn't happened to ruby 1.8 yet", 'semicolon;', 'quote"', 'tick\'', 'backtick`', 'percent%', 'plus+', 'space '].each do |login_str| it "'#{login_str}'" do lambda do u = create_user(:login => login_str) u.errors[:login].should_not be_empty end.should_not change(User, :count) end end end it 'requires password' do lambda do u = create_user(:password => nil) u.should_not be_valid end.should_not change(User, :count) end it 'requires password confirmation' do lambda do u = create_user(:password_confirmation => nil) u.should_not be_valid end.should_not change(User, :count) end it 'requires email' do lambda do u = create_user(:email => nil) u.should_not be_valid end.should_not change(User, :count) end describe 'allows legitimate emails:' do ['[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '1234567890-234567890-234567890-234567890-234567890-234567890-234567890-234567890-234567890@gmail.com', '[email protected]', 'uucp%[email protected]', '[email protected]', '[email protected]'].each do |email_str| it "'#{email_str}'" do lambda do u = create_user(:email => email_str) u.errors[:email].should be_empty end.should change(User, :count).by(1) end end end describe 'disallows illegitimate emails' do ['[email protected]', '[email protected]', '[email protected]', '[email protected]', 'Iñtërnâtiônàlizætiø[email protected]', 'need.domain.and.tld@de', "tab\t", "newline
", '[email protected]', '1234567890-234567890-234567890-234567890-234567890-234567890-234567890-234567890-234567890@gmail2.com', '[email protected]', 'semicolon;@gmail.com', 'quote"@gmail.com', 'tick\'@gmail.com', 'backtick`@gmail.com', 'space @gmail.com', 'bracket<@gmail.com', 'bracket>@gmail.com'].each do |email_str| it "'#{email_str}'" do lambda do u = create_user(:email => email_str) u.errors[:email].should_not be_empty end.should_not change(User, :count) end end end describe 'allows legitimate names:' do ['Andre The Giant (7\'4", 520 lb.) -- has a posse', '', '1234567890_234567890_234567890_234567890_234567890_234567890_234567890_234567890_234567890_234567890'].each do |name_str| it "'#{name_str}'" do lambda do u = create_user(:name => name_str) u.errors[:name].should be_empty end.should change(User, :count).by(1) end end end describe "disallows illegitimate names" do ["tab\t", "newline
", '1234567890_234567890_234567890_234567890_234567890_234567890_234567890_234567890_234567890_234567890_'].each do |name_str| it "'#{name_str}'" do lambda do u = create_user(:name => name_str) u.errors[:name].should_not be_empty end.should_not change(User, :count) end end end

以上のコードはrestfulからコピーされています.authentication,修正点はu.errorsのAPIがRails 3で変更されていることである.Rails 3は[]を返します.つまり、ここでの判定はbe_です.nilはだめです.基本的に変えなければなりません.
上記のコードと私が以前書いたRspecコードには3つの明らかな利点があると思います.
  def clean_user(options = {})
    user = User.new({:name => 'Tom.Zhao', :email => '[email protected]', :password => 'Tom.Zhao'}.merge(options))
  end

  it 'should require name, email password' do
    clean_user(:name => '').should_not be_valid
    clean_user(:email => '').should_not be_valid
    clean_user(:password => '').should_not be_valid
  end

  it 'has lengh 5 ~ 40 of password' do
    clean_user(:password => '1234').should_not be_valid
    clean_user(:password => '1234' * 10 + '1' ).should_not be_valid
    clean_user(:password => '12345').should be_valid
    clean_user(:password => '1234' * 10).should be_valid
  end

1:lambda匿名関数によって検証テストを実行し、Procオブジェクトを返してsaveかどうかを直接検証します.
2:大量の条件検証,[].each do |name_str|の使い方の結果はより直感的で、コードの可読性が高い.
3:modelのvalidates:format=>{:with=>RE_EMAIL_OK、:message=>MSG_EMAIL_BAD}では、返されたエラーメッセージを直接検証できます.
テストが終わったら、モデルに何かを追加しなければなりません.Rails 3はvalidatesを発売しました.私たちの書き方をもっとセクシーにすることができます.使用できるパラメータは
参照
    * :acceptance => Boolean
    * :confirmation => Boolean
    * :exclusion => { :in => Ennumerable }
    * :inclusion => { :in => Ennumerable }
    * :format => { :with => Regexp }
    * :length => { :minimum => Fixnum, maximum => Fixnum, }
    * :numericality => Boolean
    * :presence => Boolean
    * :uniqueness => Boolean
ユーザーの変更rb
  include ApplicationHelper
 
  validates :login, :presence => true, 
                    :uniqueness => { :case_sensitive => false },
                    :length => {:minimum => 3, :maximum => 40},
                    :format => {:with => RE_LOGIN_OK, :message => MSG_LOGIN_BAD}
                    
  validates :email, :presence => true, 
                    :uniqueness => { :case_sensitive => false },
                    :length => {:minimum => 6, :maximum => 100},
                    :format => {:with => RE_EMAIL_OK, :message => MSG_EMAIL_BAD}
                    
  validates :name,  :length => {:maximum => 100},
                    :format => {:with => RE_NAME_OK, :message => MSG_NAME_BAD}
         
  validates :password,  :presence => true
  
  validates :password_confirmation,  :presence => true
                            
  attr_accessor :password, :password_confirmation

Rails 3の新しいvalidatesはとても好きで、作用は一目瞭然で、しかもとてもセクシーです.ちなみに
:format=>{:with=>EmailRegexp}ここでは、よく使われる検証、例えばEmailについて、抽出してlibディレクトリの下にemail_を追加することができます.validator.rb
class EmailValidator < ActiveModel::EachValidator

  EmailAddress = begin
    qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
    dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'
    atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-' +
      '\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'
    quoted_pair = '\\x5c[\\x00-\\x7f]'
    domain_literal = "\\x5b(?:#{dtext}|#{quoted_pair})*\\x5d"
    quoted_string = "\\x22(?:#{qtext}|#{quoted_pair})*\\x22"
    domain_ref = atom
    sub_domain = "(?:#{domain_ref}|#{domain_literal})"
    word = "(?:#{atom}|#{quoted_string})"
    domain = "#{sub_domain}(?:\\x2e#{sub_domain})*"
    local_part = "#{word}(?:\\x2e#{word})*"
    addr_spec = "#{local_part}\\x40#{domain}"
    pattern = /\A#{addr_spec}\z/
  end

  def validate_each(record, attribute, value)
    unless value =~ EmailAddress
      record.errors[attribute] << (options[:message] || "is not valid") 
    end
  end
  
end

ここのコードは直接このように書くことができます
validates :email, :presence => true, 
                    :length => {:minimum => 3, :maximum => 254},
                    :uniqueness => true,
                    :email => true

現在のコードに戻ります.
ApplicationHelperで定数を定義する
  unless defined? CONSTANTS_DEFINED
      RE_LOGIN_OK     = /\A\w[\w\.\-_@]+\z/
      MSG_LOGIN_BAD   = "use only letters, numbers, and .-_@ please."

      RE_NAME_OK      = /\A[^[:cntrl:]\\<>\/&]*\z/
      MSG_NAME_BAD    = "avoid non-printing characters and \\&gt;&lt;&amp;/ please."

      RE_EMAIL_NAME   = '[\w\.%\+\-]+'
      RE_DOMAIN_HEAD  = '(?:[A-Z0-9\-]+\.)+'
      RE_DOMAIN_TLD   = '(?:[A-Z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum)'
      RE_EMAIL_OK     = /\A#{RE_EMAIL_NAME}@#{RE_DOMAIN_HEAD}#{RE_DOMAIN_TLD}\z/i
      MSG_EMAIL_BAD   = "should look like an email address."

      CONSTANTS_DEFINED = 'yup'
    end

保存後、autotestウィンドウのテストがすべて合格したのを見て、OK!
次にパスワードの暗号化とEmailのアクティブ化を処理し、Rails 3が持参したステータスマシンを使うか、state_を使うかマシーンは?これは問題です.
10月1日に次のステップを完了します.