ȥå   Խ ʬ Хåå ź ʣ ̾ѹ   ñ측 ǽ   إ   ǽRSS

Ruby/Ruby on Rails/step by step

Last-modified: 2010-09-21 () 15:35:14 (2557d)
Top / Ruby / Ruby on Rails / step by step

Ruby/Ruby on Rails

Ruby on RailsǷ֤ƳФstepȤޤ

step01 InstantRailsεưirb

C:\InstantRails\InstantRails.exe֥륯åƵưޤ

step01_InstantRails.gif


DOSץץȲ̤򳫤irbƤߤޤ
[IΥ] - [Rails Applications] - [Open Ruby Console Window]

step01_irb.gif

ƥޥɤΰ̣

ޥư
cmd /f:octrl+fǤΥե̾䴰ͭȤޤ
ruby -vrubyΥСɽޤ
irb -ribr/completion䴰ǽͭirbưޤ
pu[tab]tab򲡤䴰ޤ
puts "Hello World!"rubyʸǤĤȤ˼¹Ԥޤ
exitirbλޤ

褯Ȥrails_appsľΥХåեˤޤ

Хåե̾
setenv.batcmd /f:o
irb.batC:\InstantRails\ruby\bin\irb -rirb/completion

step02 ץȤο

  1. InstantRailsDOSץץȤ򳫤
    ȥեC:\InstantRails\rails_appsȤʤޤ
  2. rails ץ̾פǥץȤ򿷵
  3. cd ץ̾פǥץȥե˰ư
    ʹߤϥץȥեǹԤޤ

step03 Mongrel webФεư

  1. ץȥեruby script\server¹ԤMongrel webФư
    ctrl+cǤǤޤ
  2. http://127.0.0.1:3000/֥饦dzȡץȤWebڡޤ

step04 Aptana Studio RadRails

UTF-8˽

  1. Aptana Studioư
  2. ʸɤUTF-8˽
    [Window] - [Preferences] - [General] - [Workspace] - [Text file encoding]UTF-8ꤷޤ
    step04_RadRailsUTF8.gif

RailsץȤΥݡ

  1. [File] - [Import] - [Other] - [Import As New Project] - [Next]
    step04_RadRailsImport01.gif
  2. ץȥե
    step04_RadRailsImport02.gif
  3. ΤޤFinish
    step04_RadRailsImport03.gif

step05 ǡ١

config\database.yml򳫤ơɬפʾ

development:
  adapter: mysql
  database: ץ̾_development
  username: root
  password:
  host: localhost

test:
  adapter: mysql
  database: ץ̾_test
  username: root
  password:
  host: localhost

production:
  adapter: mysql
  database: ץ̾_production
  username: root
  password: 
  host: localhost

MySQLδʸɤUTF-8

  1. [Instant Rails] - [I] - [Configure] - [MySql]my.ini򳫤
  2. ˼ΣԤɲ
    default-character-set=utf8
    skip-character-set-client-handshake

step06 ǡ١

sqlޥɤǺˡ

  1. phpMyAdminư [Instant Rails] - [I] - [Configure] - [Database(via PhpMyAdmin)]
    url֥饦dzƤOKǤ
    http://127.0.0.1/mysql/
  2. SQL򥯥å
  3. create database ץ̾_development default charset utf8;
  4. ȤphpMyAdmin
  5. ĶѤDBȤϡޥɤǼ???ʬtestproductionѹ
    create database ץ̾_??? default charset utf8;

rakeǺˡ

  1. lib\tasks\setup_db.rakeե
    env = ENV['RAILS_ENV'] || 'development'
    database = "ץ̾_#{env}"
    
    task :connect_db => [:environment] do
      ActiveRecord::Base.establish_connection(
        :adapter => 'mysql',
        :host => 'localhost',
        :username => 'root',
        :database => 'mysql'
       )
    end
    
    task :setup_db => [:connect_db] do
      ActiveRecord::Schema.define do
        create_database database
      end
    end
    
    task :destroy_db => [:connect_db] do
      ActiveRecord::Schema.define do
        drop_database database
      end
    end
  2. ץȥեǡrake setup_db
  3. Ȥϡrake destroy_db
  4. ĶѤDBȤϡrake RAILS_ENV=test setup_dbפޤϡrake RAILS_ENV=production setup_db

step07 migrationˤơ֥

  1. ruby script\generate migration create_memos_table
  2. db\migrate\001_create_memos_table.rbԽʿѤ礬ޤ
    class CreateTable < ActiveRecord::Migration
      def self.up
        create_table :memos do |t|
          t.column :created_at, :datetime
          t.column :text, :string, :limit => 256
          t.column :location, :string, :limit => 64
        end
      end
    
      def self.down
        drop_table :memos
      end
    end
  3. rake db:migrateפǥޥ졼Ȥ¹
  4. migrationˤꡢ㤨ʸѹ
    ruby script\generate migration expand_location
  5. db\migrate\002_expand_location.rbԽʿѤ礬ޤ
    class ExpandLocation < ActiveRecord::Migration
      def self.up
      change_column :memos, :location, :string, :limit => 256
      end
    
      def self.down
      change_column :memos, :location, :string, :limit => 64
      end
    end
  6. rake db:migrateפǥޥ졼Ȥ¹
  7. С󣱤᤹Ȥϡ
    rake db:migrate VERSION=1

step08 scaffoldˤǥ뤪ӥǥ˥­Υڡ

ץȥ롼ȤǼΥޥɤ

ruby script\generate scaffold ǥ̾
ǥ̾ϥåѡñǤ

㤨Сruby script\generate scaffold MemoפȤ硢Υڡޤ

ȥ顼memoslist, new, show, edit, destroyȤʤޤ

Υե뤬ޤ

  • app\models\memo.rb ... ǥ
  • app\controllers\memos_controller.rb ... ȥ顼
  • app\views\layouts\memos.rhtml ... WebץΤΥӥ塼
  • app\views\memos\edit.rhtml ... editΥӥ塼ԽΥӥ塼
  • ...

step09 ǥؤθڽɲ

ǥ˸ڥ᥽åɤɲäޤ
app\models\memo.rb

class Memo < ActiveRecord::Base
  validates_presence_of :text, :location
  validates_length_of :location, :maximum => 256
  validates_length_of :ե̾, :within 6..12
end

Ǹ6ʸʾ12ʸʲǤ
ɥåȤ򣳤äĤȤȡ̤פȤʤޤ

step10 ΥեѸ줫ѹ

app\views\memos\_form.rhtml

...
<%= datetime_select 'memo', 'created_at', :use_month_numbers => true %></p>
...

_form.rhtmlcreated_atפɽݤȺȡưŪ˥ǡꤵޤ

step11 󥹥ȡ뤵줿gemAPIɥȻ

  1. DOSץץȤgem_server
  2. ֥饦Ǽurl򳫤
    http://127.0.0.1:8808/
    㤨иڤѤ᥽åɤϼAPI򻲾Ȥޤ
    [activerecord rdoc] - [ActiveRecord::Validations::ClassMethods]

step12 Ruby-GetTextΥ󥹥ȡ

  1. gettext-1.10.0-mswin32.gem٤
  2. Instant RailsưDOSץץȤ򳫤
  3. ޥɤϤƥ󥹥ȡ
    gem install C:\tmp\gettext-1.10.0-mswin32.gem
    ͡
    • gem install gettextפϤơ饤˥塼򤹤륤󥹥ȡˡ⤢뤽ǤʤGemNotFoundExceptionפȤʤꥤ󥹥ȡǤޤǤ
    • 꿷СRuby-GetTextRails 2.0ΤбǤ
    • 󥹥ȡ衧C:\InstantRails\ruby\lib\ruby\gems\1.8\gems\gettext-1.10.0-mswin32
  4. GNU GetText򥤥󥹥ȡ
    ruby-gnome2-0.16.0-1-i386-mswin32.exe٤ꤷƥ󥹥ȡ뤷ޤ
    󥹥ȡ衧C:\InstantRails\ruby\Ruby-GNOME2
  5. Instant RailsƵư

step13 Ruby-GetTextѤ褦ץȤ

  1. gettext.rake٤lib\tasks˥ԡ
  2. script\serverޥɤ¹ΤȤctrl+c
    configեΥեѹȤϺƵưɬפʤǤ
  3. ץȥեǡrake init_gettextפ¹
    ᤹Ȥϡrake void_gettextפ¹
  4. ruby script\serverWebкƵư

step14 Ruby-GetTextѤܸ첽

  1. ӥ塼ν񤭴
    app\views\memos\_form.rhtml򼡤Τ褦˽񤭴
    <label for="memo_created_at">Create at</label>
            
    <label for="memo_created_at"><%=h _('Create at')%></label>
    app\controllers\memos_controller.rb򼡤Τ褦˽񤭴
          flash[:notice] = 'Memo was successfully created.'
            
          flash[:notice] = _('Memo was successfully created.')
  2. pot/poե
    rake update_po
  3. poեɽʸ
    po\ja\memopad.po񤭴
    #: app/views/memos/_form.rhtml:4
    msgid "Create at"
    msgstr ""
    ...
    #: app/controllers/memos_controller.rb:26
    msgid "Memo was successfully created."
    msgstr "κޤ"
  4. moե
    rake make_mo

step15 ƥȶưȯ(TDD, Test Driven Development)ν

  1. ƥDB
    Τɤ餫Ǻޤ
    • phpMyAdmin SQLޥϤ
      create database ץ̾_test default charset utf8;
    • DOSץץ ץȥեǤΥޥϤ
      rake RAILS_ENV=test setup_db
  2. ƥȤ¹
    ץȥեǡrake
  3. ŪƥȥǡѰ
    test\fixtures\memos.yml
    one:
      id: 1
      text: ƥȥǡ#1
      location: 
    two:
      id: 2
      text: ƥȥǡ#2
      location: ϩ
    ƥȥǡ ץ
    today: <%= Date.today.to_s %>
    created_at: <%= Time.now.to_formatted_s :db %>
  4. ưŪƥȥǡѰ
    test\functional\memos_controller_test.rb
      ...
      def setup
        @controller = MemosController.new
        @request    = ActionController::TestRequest.new
        @response   = ActionController::TestResponse.new
    
        @first_id = memos(:one).id Τ褦firstone˽񤭴
      end
      ...
      def test_create
        num_memos = Memo.count
    
    ### post :create, :memo => {}
    ###     Τ褦˥ƥȥǡ
        post :create, :memo => {:text => 'ƥȥǡ#3', :location => 'ƥ'}
    
        assert_response :redirect
        assert_redirected_to :action => 'list'
    
        assert_equal num_memos + 1, Memo.count
      end
      ...
  5. ƤӡrakeפǥƥȤ¹Ԥfailures, errorsȤʤ뤳Ȥǧ

step16 ˥åȥƥȡʾά

10ǤܤRuby on Rails148ڡ򤴻Ȥ

step17 ե󥯥ʥƥȡʾά

10ǤܤRuby on Rails164ڡ򤴻Ȥ

step18 ӥ塼񤭴㡧ϤƤ'http://'ǻϤޤȤ˥󥯤Ȥyyyy-mm-dd hh:mmѹ

app\views\memos\list.rhtml

<h1><%=h _('Listing memos') %></h1>

<table border="1">
  <tr>
  <% for column in Memo.content_columns %>
    <th><%= column.human_name %></th>
  <% end %>
  </tr>
  
<% for memo in @memos %>
  <tr>
  <% for column in Memo.content_columns %>
    <% if column.name == 'location' && memo.location.index('http://') == 0 %> ... Τ褦˽񤭴
      <td><%= link_to h(memo.location), memo.location %></td> ... 󥯤νǤ
                                                                  ɽƤh()ǥפޤ
    <% else %>
      <td><%=h memo.send(column.name) %></td> ... send()Ѥȥե̾᤺˥롼׽Ǥޤ
                                                  㤨column.name'text'ΤȤmemo.send(column.name)
                                                  memo.textȤʤޤ
    <% end %>
  <% end %>
    <td><%= link_to _('Show'), :action => 'show', :id => memo %></td>
    <td><%= link_to _('Edit'), :action => 'edit', :id => memo %></td>
    <td><%= link_to _('Destroy'), { :action => 'destroy', :id => memo }, :confirm => _('Are you sure?'),  :method => :post %></td>
  </tr>
 <% end  %>
</table >

<%= link_to _('Previous page'), { :page => @memo_pages.current.previous } if @memo_pages.current.previous  %>
<%= link_to _('Next page'), { :page => @memo_pages.current.next } if @memo_pages.current.next %>

<br />

<%= link_to _('New memo'), :action => 'new' %>



˥åʬإѡ᥽åɤ˳Фդ񤭴 app\views\memos\list.rhtml

  ...
  <% for column in Memo.content_columns %>
    <td><%= format_column_value memo, column.name %></td>
  <% end %>
  ...

app\helpers\memos_helper.rb

module MemosHelper
  # ⥪֥ȤλꥫɽѤ
  def format_column_value(memo, colname)
    if colname == 'location' && memo.location.index('http://') == 0
      link_to h(memo.location), memo.location
    elsif colname == 'created_at'
      memo.created_at.strftime '%Y-%m-%d %H:%M' if memo.created_at # դ⤳Τ褦
    else
      h memo.send(colname)
    end
  end
end

step19 ǥɲ: źեեɽAttachmentǥɲäޤ

  1. ǥ
    C:\InstantRails\rails_apps\memopad>ruby script\generate model Attachment
          exists  app/models/
          exists  test/unit/
          exists  test/fixtures/
          create  app/models/attachment.rb
          create  test/unit/attachment_test.rb
          create  test/fixtures/attachments.yml
          exists  db/migrate
          create  db/migrate/003_create_attachments.rb ... ǥ˺ȡΤ褦˥ơ֥
                                                           migrationեҤʷޤ
  2. եɤ
    db\migrate\003_create_attachments.rb
    class CreateAttachments < ActiveRecord::Migration
      def self.up
        create_table :attachments do |t|
          t.column :memo_id, :integer                   # Τ褦ɲäޤ
          t.column :name, :string, :limit => 64
          t.column :size, :integer
          t.column :content_type, :string, :limit => 64
          t.column :content, :mediumblob
        end
      end
    
      def self.down
        drop_table :attachments                         # ˥ǥȡΤ褦˥ơ֥
                                                        # ⼫ưäǤ
      end
    end
  3. migration¹
    rake db:migrate
  4. ¦Attachmentǥ˸ڡbelongs_to᥽åɡ᥿ǡ᥽åɤɲ
    app\models\attachment.rb
    class Attachment < ActiveRecord::Base
      # ڽ
      validates_presence_of :name, :size, :content_type, :content
    
      # memo֥Ȥ˽°뤳Ȥ
      # ˤäƤΥ饹Memo°ѤǤޤ
      # memoñʤΤñǤ
      belongs_to :memo
    
      # ᥿ǡ̾
      #   źեե뼫Ȱʳʤ̤Υ̾Ǥ
      METADATA_COLUMNS = 'id, memo_id, name, size, content_type'
    
      # Memo֥Ȥꤷơźʪ᥿ǡμΥ᥽å
      # @param ƤMemo֥
      # @return źʪ᥿ǡ
      # 㡧arMeta = Attachment.metadatas memos(objMemo)
      #     puts arMeta.size
      #     if (arMeta.size > 0)
      #       puts arMeta[0].memo_id
      #     end
      def self.metadatas(memo)
        find :all, :select => METADATA_COLUMNS,
            :conditions => ['memo_id = ?', memo.id]
      end
    
      # źʪid᥿ǡΥ᥽å
      # @param źʪid
      # @return idźʪ᥿ǡ
      def self.metadata(id)
        find id, :select => METADATA_COLUMNS
      end
    end
    
  5. ¦Memoǥhas_many᥽åɤɲ
    class Memo < ActiveRecord::Base
      validates_presence_of :text, :location
      validates_length_of :location, :maximum => 256
    
      # attachments֥Ȥʣ:selectǻꤷ˥Ǥ뤳Ȥ
      # attachmentsʣʤΤʣǤ
      # 裲ˤ:orderʤfind᥽åɤƱǤޤ
      has_many :attachments, :select => Attachment::METADATA_COLUMNS
    
      def self.bookmarks
        find :all, :conditions => "location like 'http://%'", :order => "created_at DESC"
      end
    end
    

step20 źեեΥåץ

ӥ塼񤭴

app\views\memos\new.rhtml

<h1><%=h _('New memo')%></h1>

<% form_tag ({:action => 'create'}, :multipart => true) do %> ... multipart
  <%= render :partial => 'form' %> ... ϸ餢륽ǡ_form.rhtmlɤ߹ߤޤ
  <p>
    <label for="file"><%=h _('Attachment') %><label><br />    ... ٥
    <%= file_field_tag 'file' %>                              ... ե̾ϤȻȥܥ
  </p>
  <%= submit_tag _("Create") %>
<% end %>

<%= link_to _('Back'), :action => 'list' %>

źեեǥǥ

app\controllers\memos_controller.rb

  ...
  def create
    @memo = Memo.new(params[:memo])
    if params[:file] && params[:file].respond_to?(:original_filename)
      # createfileѥ᡼äƤȤν
      @memo.attachments.create :name => params[:file].original_filename,
        :size => params[:file].length,
        :content_type => params[:file].content_type,
        :content => params[:file].read
    end
    
    if @memo.save
      flash[:notice] = _('Memo was successfully created.')
      redirect_to :action => 'list'
    else
      render :action => 'new'
    end
  end
  ...

step21 źեեɽʬɲ

롼ƥ󥰤

config\routes.rb
ƬԤɲ

 map.connect ':controller/:action/:id/:filename.:fileext'
 map.connect ':controller/:action/:id/:filename'
 map.connect ':controller/:action/:id.:format'
 map.connect ':controller/:action/:id'

ɽźեեꥹɽ

app\views\memos\show.rhtml

...
<% if !@memo.attachments.empty? %>
  <b><%=h _('Attachments') %>:</b>
  <table border="1">
    <tr>
      <% for column in @memo.attachments.content_columns %>
        <th><%= column.human_name %></th>
      <% end %>
    </tr>
    <% for attachment in @memo.attachments %>
      <tr>
        <% for column in @memo.attachments.content_columns %>
          <td><%= format_column_value attachment, column.name %></td>
        <% end %>
      </tr>
    <% end %>
  </table>
<% end %>
...

åʬϥإѡ˵

app\helpers\memos_helper.rb

module MemosHelper
  # ֥ȤλꥫɽѤ
  def format_column_value(ar, colname)
    if Memo === ar
      format_memo_column_value ar, colname
    elsif Attachment === ar
      format_attachment_column_value ar, colname
    end
  end

  # ⥪֥ȤλꥫɽѤ
  def format_memo_column_value(memo, colname)
    ...
  end

  # źե֥ȤλꥫɽѤ
  def format_attachment_column_value(atch, colname)
    if colname == 'content'
      if atch.content_type =~ /image\/(x-|p)?(jpe?g|png|gif)/
        image_tag url_for(:action => 'file', :id => atch.id, :filename => atch.name), :alt => h(atch.name)
      else
        link_to h(atch.name), {:action => 'file', :id => atch.id, :filename => atch.name}
      end
    else
      h atch.send(colname)
    end
  end
  ...
end

fileɲ

app\controllers\memos_controller.rb

  ...
  def file
    attachment = Attachment.find params[:id]
#    return if forbidden?(attachment.memo)
    filename = (params[:fileext]) ? "#{params[:filename]}.#{params[:fileext]}" : params[:filename]
    if filename != attachment.name
      render :file => File.join(RAILS_ROOT, 'public', '404.html'), :status => 404, :layout => true
    else
      disposition = 'inline'
      send_data attachment.content, :filename => attachment.name, :type => attachment.content_type, :disposition => disposition
#      cache_page if attachment.memo.public_memo
    end
  end
  ...