Programming note」カテゴリーアーカイブ

Rails-tutorialのまとめ10.3(すべてのユーザーを表示する)

その10.2から続きます

10.3 すべてのユーザーを表示する

indexアクションを追加しましょう。このアクションは、すべてのユーザーを一覧表示します。
その際、データベースにサンプルデータを追加する方法や、
将来ユーザー数が膨大になってもindexページを問題なく表示できるようにするためのユーザー出力のページネーション (pagination=ページ分割) の方法を学びます。

10.3.1 ユーザーの一覧ページ

ユーザーの一覧ページを実装するために、まずはセキュリティモデルについて考えてみましょう。
ユーザーのshowページについては、今後も(ログインしているか
どうかに関わらず) サイトを訪れたすべてのユーザーから見えるようにしておきますが
ユーザーのindexページはログインしたユーザーにしか見せないようにし、未登録のユーザーがデフォルトで表示できるページを制限します。

indexアクションのリダイレクトをテストする red
test/controllers/users_controller_test.rb
require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest

  def setup
    @user       = users(:michael)
    @other_user = users(:archer)
  end

  test "should redirect index when not logged in" do
    get users_path
    assert_redirected_to login_url
  end
  .
  .
  .
end

beforeフィルターのlogged_in_userにindexアクションを追加して、
このアクションを保護します

indexアクションにはログインを要求する green
app/controllers/users_controller.rb
class UsersController < ApplicationController
  before_action :logged_in_user, only: [:index, :edit, :update]
  before_action :correct_user,   only: [:edit, :update]

  def index
  end

  def show
    @user = User.find(params[:id])
  end
  .
  .
  .
end

今度はすべてのユーザーを表示するために、全ユーザーが格納された変数を作成し、順々に表示するindexビューを実装します。
User.allを使ってデータベース上の全ユーザーを取得し、
ビューで使えるインスタンス変数@usersに代入させます。

ユーザーのindexアクション

app/controllers/users_controller.rb
class UsersController < ApplicationController
  before_action :logged_in_user, only: [:index, :edit, :update]
  .
  .
  .
  def index
    @users = User.all
  end
  .
  .
  .
end

実際のindexページを作成するには、ユーザーを列挙してユーザーごとにliタグで囲むビューを作成する必要があります。

ここではeachメソッドを使って作成します。
それぞれの行をリストタグulで囲いながら、
各ユーザーのGravatarと名前を表示します。

続きを読む

Rails-tutorialのまとめ10.2(第10章 ユーザーの更新の続き 主に演習)

その10から続く

10.2.1 ユーザーにログインを要求する

ユーザーにログインを要求し、かつ自分以外のユーザー情報を変更できないように制御してみましょう。
(こういったセキュリティ上の制御機構をセキュリティモデルと呼びます)。

許可されていないページに対してアクセスするログイン済みのユーザーがいたら(例えば他人のユーザー編集ページにアクセスしようとしたら)、
ルートURLにリダイレクトさせるようにします。

転送させる仕組みを実装したいときは、Usersコントローラの中でbeforeフィルター
を使います。beforeフィルターは、before_actionメソッドを使って何らかの処理
が実行される直前に特定のメソッドを実行する仕組みです。

今回はユーザーにログインを要求するために、logged_in_userメソッドを
定義してbefore_action :logged_in_userという形式で使います

beforeフィルターにlogged_in_userを追加する red
app/controllers/users_controller.rb
class UsersController < ApplicationController
before_action :logged_in_user, only: [:edit, :update]  .
  .
  .
  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end

    # beforeアクション
    # ログイン済みユーザーかどうか確認
    def logged_in_user
unless logged_in?flash[:danger] = "Please log in."redirect_to login_urlend    end
end
デフォルトでは、beforeフィルターはコントローラ内のすべてのアクションに
適用されるので、ここでは適切な:onlyオプション (ハッシュ) を渡すことで、
:editと:updateアクションだけにこのフィルタが適用されるように制限をかけています
今の段階ではテストは redになります。
rails test
テストユーザーでログインする green
test/integration/users_edit_test.rb

続きを読む

Rails-tutorialのまとめ(第10章 ユーザーの更新 主に演習)

その9から続く

10.1.1 編集フォーム

ユーザーのeditアクションapp/controllers/users_controller.rb
class UsersController < ApplicationController
 #追加
  def edit
   @user = User.find(params[:id])  end    
  end

beforeフィルター (before filter) を使ってこのアクセス制御を実現できます。

1: ユーザーのeditビュー
app/views/users/edit.html.erb

<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>

<div class="row">
<div class="col-md-6 col-md-offset-3">
  <%= form_for(@user) do |f| %>
    <%= render 'shared/error_messages' %>
    <%= f.label :name %>
    <%= f.text_field :name, class: 'form-control' %>
    <%= f.label :email %>
    <%= f.email_field :email, class: 'form-control' %>
    <%= f.label :password %>
    <%= f.password_field :password, class: 'form-control' %>
    <%= f.label :password_confirmation, "Confirmation" %>
    <%= f.password_field :password_confirmation, class: 'form-control' %>
    <%= f.submit "Save changes", class: "btn btn-primary" %>
<% end %>
<div class="gravatar_edit">
  <%= gravatar_for @user %>
   <a href="http://gravatar.com/emails" target="_blank">change</a>
   </div>
  </div>
</div>

gravatarへのリンクでtarget=”_blank”が使われていますが、
これを使うとリンク先を新しいタブ(またはウィンドウ)で開くようになるので、
別のWebサイトへリンクするときなどに便利です。

Railsはどうやって新規のPostと既存のPatchを区別している?
Railsは、form_for(@user)を使ってフォームを構成すると、@user.new_record?がtrueのときにはPOSTを、falseのときにはPATCHを使います。

レイアウトの “Settings” リンクを更新するapp/views/layouts/_header.html.erb
<header class="navbar navbar-fixed-top navbar-inverse">
  <div class="container">
    <%= link_to "sample app", root_path, id: "logo" %>
    <nav>
      <ul class="nav navbar-nav navbar-right">
        <li><%= link_to "Home", root_path %></li>
        <li><%= link_to "Help", help_path %></li>
        <% if logged_in? %>
          <li><%= link_to "Users", '#' %></li>
          <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
              Account <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
              <li><%= link_to "Profile", current_user %></li>
               <li>
                <%= link_to "Settings", edit_user_path(current_user) %></li>
              <li class="divider"></li>
              <li>
                <%= link_to "Log out", logout_path, method: :delete %>
              </li>
            </ul>
          </li>
        <% else %>
          <li><%= link_to "Log in", login_path %></li>
        <% end %>
      </ul>
    </nav>
  </div>
</header>

演習

1:先ほど触れたように、target=”_blank”で新しいページを開くときには、セキュリティ上の小さな問題があります。
それは、リンク先のサイトがHTMLドキュメントのwindowオブジェクトを扱えてしまう、という点です。具体的には、フィッシング (Phising) サイトのような、
悪意のあるコンテンツを導入させられてしまう可能性があります。
Gravatarのようなサイトではこのような事態は起こらないと思いますが、
念のため、このセキュリティ上のリスクも排除しておきましょう。
対処方法は、リンク用のaタグのrel (relationship) 属性に、
“noopener”と設定するだけです。
早速、Gravatarの編集ページへのリンクにこの設定をしてみましょう。

rel= “noopener”を追加するだけ

続きを読む

Rails-tutorial自分用まとめ(第9章 発展的なログイン機構 主に演習)

その8から続く

9.1 Remember me 機能

ユーザーのログイン状態をブラウザを閉じた後でも有効にする [remember me] 機能永続クッキー (permanent cookies) を使ってこの機能を実現していきます

9.1.1 記憶トークンと暗号化

1:記憶トークンにはランダムな文字列を生成して用いる。
2:ブラウザのcookiesにトークンを保存するときには、有効期限を設定する。
3:トークンはハッシュ値に変換してからデータベースに保存する。
4:ブラウザのcookiesに保存するユーザーIDは暗号化しておく。
5:永続ユーザーIDを含むcookiesを受け取ったら、そのIDでデータベースを検索し、
記憶トークンのcookiesがデータベース内のハッシュ値と一致することを確認する。
最初に、必要となるremember_digest属性をUserモデルに追加

rails generate migration add_remember_digest_to_users remember_digest:string
rails db:migrate
トークンとしてRuby標準ライブラリのSecureRandomモジュールに
あるurlsafe_base64メソッドを使う
トークン生成用メソッドを追加するapp/models/user.rb
class User < ApplicationRecord

  # ランダムなトークンを返す。追加
  def User.new_token
SecureRandom.urlsafe_base64
  end
end

実装計画としては、user.rememberメソッドを作成することで、
このメソッドは記憶トークンをユーザーと関連付け、トークンに対応する記憶
ダイジェストをデータベースに保存します。

Userモデルには既にremember_digest属性が追加されていますが
remember_token属性はまだ追加されていません。
このためuser.remember_tokenメソッドを使ってトークンにアクセスできるようにし、トークンをデータベースに保存せずに実装する必要があリます。

仮想のpassword属性はhas_secure_passwordメソッドで自動的に作成されましたが、今回はremember_tokenのコードを自分で書く必要があります。
attr_accessorを使って「仮想の」属性を作成します。

class User < ApplicationRecord
 attr_accessor :remember_token
 .
 .
 .
 def remember
   self.remember_token = ...update_attribute(:remember_digest, ...)
 end
end

selfキーワードを与えると、この代入によってユーザーのremember_token属性が期待どおりに設定されます。

rememberメソッドの2行目では、update_attributeメソッドを使って記憶ダイジェストを更新しています。

ユーザーを記憶するには、記憶トークンを作成して、そのトークンをダイジェストに変換したものをデータベースに保存します。

新しいトークンを作成するためのnew_tokenメソッドを作成

rememberメソッドをUserモデルに追加する green

app/models/user.rb
class User < ApplicationRecord
  
  attr_accessor :remember_token  中略 ↑追加↓
  # 永続セッションのためにユーザーをデータベースに記憶する
  def remember
    self.remember_token = User.new_tokenupdate_attribute(:remember_digest, User.digest(remember_token))  end
  end

続きを読む

Rails-tutorial自分用まとめ(第8章 ログイン機構 主に演習とその回答)

その7から続く

8.1 セッション

HTTPはステートレス (Stateless) なプロトコルです。文字通り「状態 (state)」が「ない (less)」ので、HTTPのリクエスト1つ1つは、それより前のリクエストの情報をまったく利用できない、独立したトランザクションとして扱われます。

ユーザーログインの必要なWebアプリケーションでは、セッション (Session) と呼ばれる半永続的な接続をコンピュータ間 (ユーザーのパソコンのWebブラウザとRailsサーバーなど) に別途設定します。

Railsでセッションを実装する方法として最も一般的なのは、cookiesを使う方法です。cookiesとは、ユーザーのブラウザに保存される小さなテキストデータです。

8.1.1 Sessionsコントローラ

Sessionsコントローラを生成する

rails generate controller Sessions new
リソースを追加して標準的なRESTfulアクションをgetできるようにする red config/routes.rb
Rails.application.routes.draw do
  root   'static_pages#home'
  get    '/help',    to: 'static_pages#help'
  get    '/about',   to: 'static_pages#about'
  get    '/contact', to: 'static_pages#contact'
  get    '/signup',  to: 'users#new'
  get    '/login',   to: 'sessions#new'
  post   '/login',   to: 'sessions#create'
  delete '/logout',  to: 'sessions#destroy'
  resources :users
end
#セッションルールによって提供されるルーティング
HTTPリクエスト URL     名前付きルート アクション名      用途
GET          /login  login_path    new       新しいセッションのページ (ログイン)
POST         /login  login_path    create    新しいセッションの作成 (ログイン)
DELETE       /logout logout_path   destroy   セッションの削除 (ログアウト)

演習

1:GET login_pathとPOST login_pathとの違いを説明できますか?
少し考えてみましょう。

get    '/login',   to: 'sessions#new'
post   '/login',   to: 'sessions#create'

GET login_path: “/login”へアクセスされた際に”sessions#new”アクションを実行

POST login_path: “sessions#create”アクションの情報を”/login”へ送信。

Getは/loginのリクエストが来た際にsessionsコントローラのnewアクションをするという意味でPostはsessionsコントローラのcreateアクションを/loginに送信する

2:ターミナルのパイプ機能を使ってrails routesの実行結果とgrepコマンドを繋ぐことで、Usersリソースに関するルーティングだけを表示させることができます。
同様にして、Sessionsリソースに関する結果だけを表示させてみましょう。
現在、いくつのSessionsリソースがあるでしょうか?

rails routes | grep users#
rails routes | grep sessions# 3つ

form_for(@user)

Railsでは上のように書くだけで、
「フォームのactionは/usersというURLへのPOSTである」と自動的に判定しますが、
セッションの場合はリソースの名前とそれに対応するURLを具体的に指定する必要があります。

form_for(:session, url: login_path)

8.1.2 ログインフォーム

演習

リスト 8.4で定義したフォームで送信すると、Sessionsコントローラのcreateアクションに到達します。Railsはこれをどうやって実現しているでしょうか?
ヒント:表 8.1とリスト 8.5の1行目に注目してください。

action=”/login” method=”post”から/loginにPostする場合
sessionsコントローラのcreateアクションが実行されるため

8.1.3 ユーザーの検索と認証

 ユーザーをデータベースから見つけて検証するapp/controllers/sessions_controller.rb
class SessionsController < ApplicationController

  def new
  end

  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      # ユーザーログイン後にユーザー情報のページにリダイレクトする
    else
      # エラーメッセージを作成する
      render 'new'
    end
  end

  def destroy
  end
end

User                   Password                                                a && b
存在しない        何でもよい (nil && [オブジェクト]) == false
有効なユーザー 誤ったパスワード (true && false) == false
有効なユーザー 正しいパスワード (true && true) == true

演習

続きを読む

Rails-tutorial自分用まとめ(第7章ユーザー登録 主に演習とその回答)

その6から続きます

7.1.1 デバッグとRails環境

サイトのレイアウトにデバッグ情報を追加するapp/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  .
  .
  .
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <%= render 'layouts/footer' %>
      <%= debug(params) if Rails.env.development? %>
    </div>
  </body>
 デバッグ表示を整形するための追加と、Sassのミックスイン.
app/assets/stylesheets/custom.scss
@import "bootstrap-sprockets";
@import "bootstrap";

/* mixins, variables, etc. */

$gray-medium-light: #eaeaea;

@mixin box_sizing {-moz-box-sizing:    border-box;-webkit-box-sizing: border-box;box-sizing:         border-box;}.
.
.
/* miscellaneous */
.debug_dump {clear: both;float: left;width: 100%;margin-top: 45px; -moz-box-sizing:    border-box;
  -webkit-box-sizing: border-box;
  box-sizing:         border-box;
}

演習

1:ブラウザから /about にアクセスし、デバッグ情報が表示されていることを確認してください。

このページを表示するとき、どのコントローラとアクションが使われ
ていたでしょうか? paramsの内容から確認してみましょう。

controller: static_pages
action: about

2:Railsコンソールを開き、データベースから最初のユーザー情報を取得し、変数userに格納してください。

その後、puts user.attributes.to_yamlを実行すると何が表示されますか?
ここで表示された結果と、yメソッドを使ったy user.attributesの実行結果を比較してみましょう。

user = User.first

表示は同じ

HTTP   リクエストURL  アクション 名前付きルート        用途
GET    /users       index   users_path     すべてのユーザーを一覧するページ
GET    /users/1     show    user_path(user) 特定のユーザーを表示するページ
GET    /users/new   new     new_user_path  ユーザーを新規作成するページ (ユーザー登録)
POST   /users       create  users_path     ユーザーを作成するアクション
GET    /users/1/    edit    edit edit_user_path(user) id=1のユーザーを編集するページ
PATCH  /users/1     update  user_path(user) ユーザーを更新するアクション
DELETE /users/1     destroy user_path(user) ユーザーを削除するアクション
Usersリソースが提供するRESTfulなルート

演習

埋め込みRubyを使って、マジックカラム (created_atとupdated_at)
の値をshowページに表示してみましょう埋め込みRubyを使って、
Time.nowの結果をshowページに表示してみましょう。
ページを更新すると、その結果はどう変わっていますか? 確認してみてください。

<%= @user.name %>, <%= @user.email %>,
<%= @user.updated_at %>, <%= @user.created_at %>,
<%= Time.now %>

続きを読む

Rails-tutorial自分用まとめ(第6章 ユーザーモデル作成 主に演習)

その5から続きます

6.1.1 データベースの移行

rails generate controller Users new

Userモデルを生成する

rails generate model User name:string email:string

Userモデルのマイグレーションdb/migrate/[timestamp]_create_users.rb

class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.timestamps
    end
  end
rails db:migrate

演習

1:Railsはdb/ディレクトリの中にあるschema.rbというファイルを使っています。
これはデータベースの構造 (スキーマ (schema) と呼びます) を追跡するために
使われます。さて、環境にあるdb/schema.rbの内容を調べ、その内容と
マイグレーションファイルの内容を比べてみてください。

schema.rb
ActiveRecord::Schema.define(version: 20170203234505) do

  create_table "users", force: :cascade do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
end

 

20200203234505_create_users.rb

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.timestamps
    end
  end
end

2:ほぼすべてのマイグレーションは、元に戻すことが可能です
元に戻すことを「ロールバック (rollback)と呼び、
Railsではdb:rollbackというコマンドで実現できます。
rails db:rollback上のコマンドを実行後、db/schema.rbの内容を調べてみて、
ロールバックが成功したかどうか確認してみてください。

Railsではdb:rollback

コマンドして、ロールバックの成功を確認

3:もう一度rails db:migrateコマンドを実行し、db/schema.rbの内容が元に戻ったことを確認してください。

rails db:migrate

schema.rb

ActiveRecord::Schema.define(version: 0) do

end

User.createでモデルの生成と保存を同時におこなう方法も提供されています。

User.createは、trueかfalseを返す代わりに、ユーザーオブジェクト自身を返す
ことに注目してください。
返されたユーザーオブジェクトは (上の2つ目のコマンドにあるfooのように) 変数に代入することもできます。

続きを読む

Rails-tutorial自分用まとめ(第5章レイアウト 主に演習)

その4から続きます

第5章レイアウトを作成する

5.1.1 ナビゲーション

RailsはデフォルトでHTML5を使います (<!DOCTYPE html>と書いてHTML5であることを宣言します)。ただHTML5は比較的新しく、一部のブラウザ (特に旧式のInternet Explorer) ではHTML5のサポートが不完全である場合があります。そのため、次のようなJavaScriptのコード (通称: HTML5 shim (or shiv))を使ってこの問題を回避します。

<!--[if lt IE 9]>
  <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
  </script>
<![endif]-->
[if lt IE 9] は、Railsの一部ではありません。これは実は、条件付きコメントと呼ばれるもので、今回のような状況のためにInternet Explorerで特別にサポートされています。
リンクを生成するために、Railsヘルパーのlink_toを使います (アンカータグaが最終的に生成されます)。
yieldメソッドはWebサイトのレイアウトにページごとの内容を挿入します。
Railsのロゴ画像をダウンロードする
curl -o app/assets/images/rails.png -OL railstutorial.jp/rails.png

演習

1:Webページと言ったらネコ画像、というぐらいにはWebにはネコ画像が溢れていますよね。コマンドを使って、ネコ画像をダウンロードしてきましょう

curl -OL cdn.learnenough.com/kitten.jpg

2:mvコマンドを使って、ダウンロードしたkitten.jpgファイルを適切なアセットディレクトリに移動してください

mv kitten.jpg ~/environment/sample_app/app/assets/images/

3:image_tagを使って、kitten.jpg画像を表示してみてください

<%= image_tag("kitten.jpg")%>

5.1.2 BootstrapとカスタムCSS

続きを読む

Rails-tutorial自分用まとめ4.8(Ruby 演習)

4.5から続く

4.4 Rubyにおけるクラス

Rubyではあらゆるものがオブジェクト

4.4.1 コンストラクタ

ダブルクォートを使って文字列のインスタンスを作成しましたが、
これは文字列のオブジェクトを暗黙で作成するリテラルコンストラクタ。

>> s = "foobar" # ダブルクォートは実は文字列のコンストラクタ
=> "foobar" >> s.class => String
>> f = 2 => 2 >> f.class => Integer
>> g = 1.1 => 1.1 >> g.class => Float

文字列がclassメソッドに応答しており、
その文字列が所属するクラスを単に返していることがわかります。
なお配列でも、文字列と同様にインスタンスを生成できます。

>> a = Array.new([1, 3, 2])
=> [1, 3, 2]

ハッシュの場合は若干異なります。配列のコンストラクタである
Array.new は配列の初期値を引数に取りますが、
Hash.new はハッシュのデフォルト 値を引数に取ります。
これは、キーが存在しない場合のデフォルト値です。

>> h = Hash.new
=> {}
>> h[:foo] # 存在しないキー (:foo) の値にアクセスしてみる
=> nil
>> h = Hash.new(0) # 存在しないキーのデフォルト値をnilから0にする
=> {}
>> h[:foo]
=> 0

メソッドがクラス自身 (この場合はnew) に対して呼び出されるとき、
このメソッドをクラスメソッドと呼びます。
クラスのnewメソッドを呼び出した結果は、そのクラスのオブジェクトであり、
これはクラスのインスタンスとも呼ばれます。
lengthのように、インスタンスに対して呼び出すメソッドは
インスタンスメソッドと呼ばれます。

演習

1:1から10の範囲オブジェクトを生成するリテラルコンストラクタは何でしたか? (復習です)

a = 1..10
=> 1..10

2:今度はRangeクラスとnewメソッドを使って、1から10の範囲オブジェクト
を作ってみてください。ヒント: newメソッドに2つの引数を渡す必要があります

>> b = Range.new(1,10)
=> 1..10

3:比較演算子==を使って、上記2つの課題で作ったそれぞれのオブジェクトが
同じであることを確認してみてください。

a == b
=> true

superclassメソッドを使ってクラス階層を調べてみるとよくわかります。

>> s = String.new("foobar")
=> "foobar"
>> s.class # 変数sのクラスを調べる
=> String
>> s.class.superclass # Stringクラスの親クラスを調べる
=> Object
>> s.class.superclass.superclass # Ruby 1.9からBasicObjectが導入
=> BasicObject
>> s.class.superclass.superclass.superclass
=> nil

“Rubyではあらゆるものがオブジェクトである” ということの技術的な意味。

Wordクラスを作成し、その中にある単語を前からと後ろからのどちらから読んでも同じ (つまり回文になっている) ならばtrueを返すpalindrome?メソッドを作成してみましょう。

> class Word
>> def palindrome?(string)
>> string == string.reverse
>> end
>> end
=> :palindrome?

このクラスとメソッドは次のように使うことができます。

>> w = Word.new # Wordオブジェクトを作成する
=> #<Word:0x22d0b20>
>> w.palindrome?("foobar")
=> false
>> w.palindrome?("level")
=> true

続きを読む

Rails-tutorial自分用まとめ(4.5 Rubyについて)

その4から続きます

4.3.1 配列と範囲演算子

配列を理解することは、ハッシュやRailsのデータモデルを理解するための重要な基盤
splitメソッドを使うと、文字列を自然に変換した配列を得ることができます。

>> "foo bar baz".split
=> ["foo", "bar", "baz"]
>> "fooxbarxbaz".split('x')
=> ["foo", "bar", "baz"]

多くのコンピュータ言語の慣習と同様、Rubyの配列でもゼロオリジンを
採用しています。これは、配列の最初の要素のインデックスが0から始まり、
2番目は1…と続くことを意味します。添字のこと

a = [42, 8, 17]
>> a[-1] => 17 # 配列の添字はマイナスにもなれる!
>> a.last === a[-1]
=> true

配列の要素にアクセスするには角カッコ[]!
配列の内容を変更したい場合は、
そのメソッドに対応する「破壊的」メソッドを使います。

>> a
=> [42, 8, 17]
>> a.sort!
=> [8, 17, 42]
>> a
=> [8, 17, 42]

pushメソッド (または同等の<<演算子) を使って配列に要素を追加することもできます。

a.push(6)=>[42, 8, 17, 6]
>> a << "foo" << "bar" # 配列に連続して追加する
=> [42, 8, 17, 6, 7, "foo", "bar"]

Rubyでは異なる型が配列の中で共存できる(上の場合は整数と文字列)。
文字列を配列に変換するのにsplitを使いました。
joinメソッドはこれと逆の動作で文字を連結できます。

>> a
=> [8, 17, 42, 6, 7, "foo", "var"]
>> a.join
=> "8174267foovar"
>> a.join(',')
=> "8,17,42,6,7,foo,var"

範囲 (range) は、配列と密接に関係しています。to_aメソッドを使って
配列に変換すると理解しやすいです。

>> 0..9
=> 0..9
>> (0..9).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>> a = %w[foo bar baz quux] # %wを使って文字列の配列に変換
=> ["foo", "bar", "baz", "quux"]
>> a[0..2]
=> ["foo", "bar", "baz"]

インデックスに-1という値を指定できるのは極めて便利。-1を使うと、
配列の長さを知らなくても配列の最後の要素を指定することができ、
これにより配列を特定の開始位置の要素から最後の要素までを一度に
選択することができる。

>> a = (0..9).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>> a[2..(a.length-1)] # 明示的に配列の長さを使って選択
=> [2, 3, 4, 5, 6, 7, 8, 9]
>> a[2..-1] # 添字に-1を使って選択
=> [2, 3, 4, 5, 6, 7, 8, 9]

字列に対しても範囲オブジェクトが使える。

>> ('a'..'e').to_a
=> ["a", "b", "c", "d", "e"]

演習

1:文字列「A man, a plan, a canal, Panama」を “, ” で分割して
配列にし、変数aに代入してみて。

続きを読む