Upload
yuichiro-masui
View
15.631
Download
5
Embed Size (px)
DESCRIPTION
2007/08/11 ワイズノット社内勉強会第1回
Citation preview
development: adapter: mysql database: todo_development username: root password: hostname: localhost
test: adapter: mysql database: todo_test username: root password: hostname: localhost
production: adapter: mysql database: todo_production username: root password: hostname: localhost
開発環境のDB設定
テスト環境のDB設定
製品環境のDB設定
development: ← Railsの環境 adapter: mysql ← 接続するDB database: todo_development ← DB名 username: root ← ユーザ名 password: ← パスワード hostname: localhost
development: ← 3つの環境とも adapter: mysql database: todo_development username: todo ← ユーザ名 password: todopass ← パスワード hostname: localhost encode: utf8 ← 追加
# 要求するRailsのバージョンRAILS_GEM_VERSION = '1.2.3' unless defined? RAILS_GEM_VERSION
# 起動ファイルrequire File.join(File.dirname(__FILE__), 'boot')
# Railsの初期設定Rails::Initializer.run do |config|
end
config/environment.rb
# 要求するRailsのバージョンRAILS_GEM_VERSION = '1.2.3' unless defined? RAILS_GEM_VERSION
# 起動ファイルrequire File.join(File.dirname(__FILE__), 'boot')
# Railsの初期設定Rails::Initializer.run do |config| config.action_controller.session_store = :active_record_store ← コメントを消すend
config/environment.rb
class AddSessions < ActiveRecord::Migration def self.up create_table :sessions do |t| t.column :session_id, :string t.column :data, :text t.column :updated_at, :datetime end
add_index :sessions, :session_id add_index :sessions, :updated_at end
def self.down drop_table :sessions endend
db/migrate/001_add_sessions.rb
> ruby script/console>> t = Todo.new>> t.savephpMyAdminで確認>> t.description = ‘hoge’>> t.savephpMyAdminで確認
>> Todo.find(:all)[#<Todo:0x26efa10 @attributes={"id"=>"1", "description"=>"hoge"}>, #<Todo:0x26ef970 @attributes={"id"=>"2", "description"=>"new todo"}>]
class TodoController < ApplicationController def index list render :action => 'list' end
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) verify :method => :post, :only => [ :destroy, :create, :update ], :redirect_to => { :action => :list }
def list @todo_pages, @todos = paginate :todos, :per_page => 10 end
def show @todo = Todo.find(params[:id]) end
def new @todo = Todo.new end
def create @todo = Todo.new(params[:todo]) if @todo.save flash[:notice] = 'Todo was successfully created.' redirect_to :action => 'list' else render :action => 'new' end end
def edit @todo = Todo.find(params[:id]) end
def update @todo = Todo.find(params[:id]) if @todo.update_attributes(params[:todo]) flash[:notice] = 'Todo was successfully updated.' redirect_to :action => 'show', :id => @todo else render :action => 'edit' end end
def destroy Todo.find(params[:id]).destroy redirect_to :action => 'list' endend
class TodoController < ApplicationController def index list render :action => 'list' end
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) verify :method => :post, :only => [ :destroy, :create, :update ], :redirect_to => { :action => :list }
def list @todo_pages, @todos = paginate :todos, :per_page => 10 end
def show @todo = Todo.find(params[:id]) end
def new @todo = Todo.new end
def create @todo = Todo.new(params[:todo]) if @todo.save flash[:notice] = 'Todo was successfully created.' redirect_to :action => 'list' else render :action => 'new' end end
def edit @todo = Todo.find(params[:id]) end
def update @todo = Todo.find(params[:id]) if @todo.update_attributes(params[:todo]) flash[:notice] = 'Todo was successfully updated.' redirect_to :action => 'show', :id => @todo else render :action => 'edit' end end
def destroy Todo.find(params[:id]).destroy redirect_to :action => 'list' endend
短いと言っても長い
Controller
MVCの流れ
Model
View
Model.find,model.save
params[]URLやフォームで渡される値
インスタンス変数
URLからコントーラとアクションを決定
Controller
MVCの流れ
Model
View
Model.find,model.save
params[]URLやフォームで渡される値
インスタンス変数
アクション名のテンプレ
URLからコントーラとアクションを決定
class TodoController < ApplicationController ...end
コントローラを定義するには、コントローラ名+ContollerのクラスをActionController::Baseを継承して作る。ApplicationControllerが、ActionController::Baseを継承している。Todoコントローラは、TodoControllerとなる。
def index list render :action => 'list' end
アクションはその名前のpublicメソッドが呼び出される。その為indexアクションはindexメソッドが呼ばれる。ここでは、listメソッドを呼び、ビューをlistアクションのテンプレートを使って実行している。
def list @todo_pages, @todos = paginate({:todos, :per_page => 10})end
第一引数で指定したモデルを:per_pageの件数だけ取得する。第一返値には、Paginator管理オブジェクト、第二返値に取得したモデルデータの配列が返ってくる。URLのパラメータでpageが指定されていた場合、page*per_page件目からのデータが取得される
Railsの便利機能
def index list render :action => 'list' end
デフォルトでは、Viewでアクション名のテンプレートファイルが呼ばれるが、今回はrender命令を使いテンプレートファイルをlistに指定しているので、listアクションのテンプレートが実行される
<h1>Listing todos</h1><table> <tr> <% for column in Todo.content_columns %> <th><%= column.human_name %></th> <% end %> </tr>
<% for todo in @todos %> <tr> <% for column in Todo.content_columns %> <td><%=h todo.send(column.name) %></td> <% end %> <td><%= link_to 'Show', :action => 'show', :id => todo %></td> <td><%= link_to 'Edit', :action => 'edit', :id => todo %></td> <td><%= link_to 'Destroy', { :action => 'destroy', :id => todo }, :confirm => 'Are you sure?', :method => :post %></td> </tr><% end %></table>
<%= link_to 'Previous page', { :page => @todo_pages.current.previous } if @todo_pages.current.previous %><%= link_to 'Next page', { :page => @todo_pages.current.next } if @todo_pages.current.next %> <br />
app/views/todo/list.rhtml
ブラウザのコードと見比べてみよう
<h1>Listing todos</h1><table> <tr> <% for column in Todo.content_columns %> <th><%= column.human_name %></th> <% end %> </tr>
<% for todo in @todos %> <tr> <% for column in Todo.content_columns %> <td><%=h todo.send(column.name) %></td> <% end %> <td><%= link_to 'Show', :action => 'show', :id => todo %></td> <td><%= link_to 'Edit', :action => 'edit', :id => todo %></td> <td><%= link_to 'Destroy', { :action => 'destroy', :id => todo }, :confirm => 'Are you sure?', :method => :post %></td> </tr><% end %></table>
<%= link_to 'Previous page', { :page => @todo_pages.current.previous } if @todo_pages.current.previous %><%= link_to 'Next page', { :page => @todo_pages.current.next } if @todo_pages.current.next %> <br />
app/views/todo/list.rhtml
Todoモデルのカラム一覧を取得
paginateしたデータのループ
前後ページへのリンク
データ表示各ページへのリンク
<h1>Listing todos</h1><table> <tr> <% for column in Todo.content_columns %> <th><%= column.human_name %></th> <% end %> </tr>
<% for todo in @todos %> <tr> <% for column in Todo.content_columns %> <td><%=h todo.send(column.name) %></td> <% end %> <td><%= link_to 'Show', :action => 'show', :id => todo %></td> <td><%= link_to 'Edit', :action => 'edit', :id => todo %></td> <td><%= link_to 'Destroy', { :action => 'destroy', :id => todo }, :confirm => 'Are you sure?', :method => :post %></td> </tr><% end %></table>
<%= link_to 'Previous page', { :page => @todo_pages.current.previous } if @todo_pages.current.previous %><%= link_to 'Next page', { :page => @todo_pages.current.next } if @todo_pages.current.next %> <br />
app/views/todo/list.rhtml
Todoモデルのカラム一覧を取得
paginateしたデータのループ
前後ページへのリンク
データ表示各ページへのリンク
リンクを生成するヘルパー
HTMLをエスケープするヘルパー
<h1>ToDo一覧</h1><table> <tr> <% for column in Todo.content_columns %> <th><%= column.human_name %></th> <% end %> </tr>
<% for todo in @todos %> <tr> <% for column in Todo.content_columns %> <td><%=h todo.send(column.name) %></td> <% end %> <td><%= link_to 'Show', :action => 'show', :id => todo %></td> <td><%= link_to '編集', :action => 'edit', :id => todo %></td> <td><%= link_to '削除', { :action => 'destroy', :id => todo }, :confirm => 'ホントにいいの?', :method => :post %></td> </tr><% end %></table>
<%= link_to ’前のページ', { :page => @todo_pages.current.previous } if @todo_pages.current.previous %><%= link_to '次のページ', { :page => @todo_pages.current.next } if @todo_pages.current.next %> <br />
app/views/todo/list.rhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>Todo: <%= controller.action_name %></title> <%= stylesheet_link_tag 'scaffold' %></head><body>
<p style="color: green"><%= flash[:notice] %></p>
<%= yield %>
</body></html>
app/views/layouts/todo.rhtml
ここにアクションのテンプレが展開される
def edit @todo = Todo.find(params[:id]) end
URLで指定されたidは、params[:id]に入っているのでこれを主キーにして検索し、その結果を@todoに代入@todoはインスタンス変数なので、そのままビューであるapp/views/todo/edit.rhtmlへ渡る
外部からのパラメータ
<h1>Editing todo</h1>
<% form_tag :action => 'update', :id => @todo do %> <%= render :partial => 'form' %> <%= submit_tag 'Edit' %><% end %>
<%= link_to 'Show', :action => 'show', :id => @todo %> |<%= link_to 'Back', :action => 'list' %>
app/views/todo/edit.rhtml
他のテンプレファイルを読み込む:partialで指定された場合は_名前.rhtmlが読み込まれる
<%= error_messages_for 'todo' %>
<!--[form:todo]--><p><label for="todo_description">Description</label><br/><%= text_area 'todo', 'description' %></p><!--[eoform:todo]-->
app/views/todo/_form.rhtml
@todoのエラーを表示
<textarea>を生成して値に@todo.descriptionをセット
def update
@todo = Todo.find(params[:id])
if @todo.update_attributes(params[:todo])
flash[:notice] = 'Todo was successfully updated.'
redirect_to :action => 'show', :id => @todo
else
render :action => 'edit'
end
end
URLのパラメータ
フォームのパラメータをモデルに保存
redirect先で表示するメッセージ
error_messages_forでエラーメッセージ表示
class Todo < ActiveRecord::Base validates_presence_of :descriptionend
app/models/todo.rb
descriptionを必須項目に
validates_acceptance_of「この規約に同意しますか?」などのチェックボックスをチェック。これを指定すると、データベースには保存されない仮想的なカラムが自動生成されます。
例: validates_acceptance_of :kiyakuチェックボックスの値をkiyakuカラムに入れると、チェックされてない場合にはエラーが起こる
validates_confirmation_of確認のために同じ値を入力させた場合の同定をチェック。passwordカラムを指定した場合、データベースには保存されないpassword_confirmationカラムができ、passwordカラムとpassword_confirmationカラムの同一性をチェックする。
例: validates_confirmation_of :emailemailカラムと、email_confimationカラムの値を比較して、不一致の場合にエラーが起こる
validates_inclusion_of指定した値に含まれているかチェックvalidates_exclusion_ofとは逆の挙動
例: validates_inclusion_of :year, :in => 1900..2007yearカラムが1900~2007の間に入っていない場合にはエラーが起こる
例: validates_inclusion_of :sex, :in => ['female', 'male']sexカラムが'famale'でも'male'でもなかった場合には、エラーが起こる
validates_exclusion_of指定した値に含まれて居ないかチェックvalidates_inclusion_ofとは逆の挙動
例: validates_exclusion_of :age, :0..19ageカラムが0~19の間に入っていた場合にエラーが起こる
validates_format_of正規表現で指定した書式でチェック
例: validates_format_of :zip, :with => /^\d{3}-\d{4}$/zipカラムが郵便番号のフォーマットに合っていない場合にエラーが起こる
validates_length_ofvalidates_size_of入力した文字数をチェック。日本語などもバイト数ではなく文字数でチェックされます。
例: validates_length_of :phone, :in => 9..11phoneカラムの桁数が9~11桁にない場合にエラーが起こる
validates_numericality_of入力した文字列が、数字かチェック
例: validates_numericality_of :pricepriceカラムに数字以外の物が入っていた場合にはエラーが起こる
例: validates_numericality_of :num, :only_integer => truenumカラムに整数以外の物が入っていた場合にはエラーが起こる
validates_uniqueness_ofデータベース内で重複していないかチェック
例: validates_uniqueness_of :mailmailカラムの値が、既にデータベースに登録されている場合にはエラーが起こる
> gem install gettext 1. gettext 1.10.0 (ruby) 2. gettext 1.10.0 (mswin32)~ 中略 ~ 6. Cancel installation> 1 ← 最新の(win32)の番号を入力