Rails7 慣例に沿ったプログラミング

今回はRailsの慣例に沿った形でWordbookを作り直します。

Convention Over Configuration

Railsには「Convention Over Configuration」(設定より規約が優先)という哲学があります。 「規約」とは「プログラミングの約束事」ですが、「プログラミングの慣例」あるいは「習慣」と言う方が合っているかもしれません。 というのは、この「規約」というのは「絶対に守らなければいけないルール」ではなく、「Railsが勧めるより良いプログラミングの方法」のことなのです。

そのひとつに、コントローラのアクションは7つにまとめることができる、というのがあります。

  • index: 最初の画面。モデル全体のリストを表示させることが多い
  • show: ひとつのモデルのデータを表示。クライアントはindexから項目をクリックしてshowに遷移することが多い
  • new: モデルの新規作成の画面
  • create: new画面から送られたデータにより、モデルを新規作成するアクション
  • edit: 既存のモデルのデータを変更するための画面。クライアントはshowからアクセスすることが多い
  • update: edit画面から送られたデータにより、モデルを更新するアクション
  • destroy: 既存のモデルを消去するアクション。クライアントはshowから遷移することが多い

Railsでは、「RESTful」(レストフル)なウェブアクセスでは、アクションをこの7つにまとめることができる、としています。 RESTfulは形容詞で「RESTな」ということです。 では、RESTとは何かというと、それは「Representational State Transfer」を短くしたもので、ウェブ・インターフェースのアーキテクチャスタイルです。 これでは説明にならないと思うので、具体的に説明すると次の4つを持つスタイルです

  • ステートレス(「状態」を持たない)。 例えば、ログインするようなサイトは「ログイン状態」という状態を持っているので、ステートレスではありません。 ログイン無しのサイトは、ほぼ「ステートレス」と考えて良いと思います
  • 上手く定義された操作のセット。 例えばHTTPプロトコルでは、GET、POST、PATCH、PUT、DELETEなどのメソッドがあり、これを使って上手く通信ができます
  • リソースの一意的識別。 これはHTTPではURIで識別しています
  • 文書の情報に状態遷移を含めることができる。 言葉は難しいですが、要するに「リンクを貼ることができる」ということです

これから、RESTfulというのは私達がブラウザでウェブにアクセスしているスタイルのことを概念的にまとめたものだと分かると思います。 ウィキペディアに情報がありますので、参考にしてください。

RailsではRESTfulなアクセスは上記の7つのアクションにまとめることができるから

  • プログラマーは、このパターンを主に使うようにすると良い
  • Railsは「このパターンによるプログラミング」が楽になるような様々な工夫をしている

ということなのです。

上記の7つのアクションの構成は、前回作ったwordbookの構成に似ていますが、名前が違っていました。

Railsの慣例によるアクション名 前回wordbookのアクション名
new append
edit change
destroy exec_delete
  delete
  search

deleteとsearchが前のwordbookにありましたが、これはRailsの慣例アクション名にはありません。

今回はこの慣例に合うようにWordbookを作り直します。 ただ、次の点は慣例と異なります。

  • indexですべての単語のリストを表示することはしない(登録単語が多くなるとリストが長くなりすぎるため)。 そこでは使い方の説明を表示することにする
  • searchアクションを作り、正規表現での検索をサポートする

モデル

それでは、WordBookの新版を作りましょう。 ディレクトリ名を「word_book_rails_resources」とします。 ディレクトリ、コントローラ、モデルを作り、データベースのマイグレーションをします。

$ rails new word_book_rails_resources -c bootstrap
... ... ...
$ cd word_book_rails_resources
$ ./bin/rails generate controller Words index show new create edit update delete search
... ... ...
$ ./bin/rails generate model Word en:string jp:string note:text
... ... ...
$ ./bin/rails db:migrate
... ... ...

モデルのフィールドには「英単語」「日本語訳」に加えて「備考」(note)を作りました。 フィールドタイプのstringは短い文字列(通常一行)で、textは複数行に渡るような文字列です。 備考には例文や解説を書くことを想定しています。

モデルのバリデーションは英単語と日本語訳に設定します。 備考については空欄でも構わないとします。

class Word < ApplicationRecord
  validates :en, presence: true, format: {with: /[a-zA-Z]+/}, uniqueness: true
  validates :jp, presence: true
end

ルーティング

/config/routes.rbを編集します。

Rails.application.routes.draw do
  root "words#index"
  get "words/search"
  resources :words
end

rootとsearchは個別のルーティングを書いておきます。 Railsの7つのアクションは「resources」メソッドでルーティングを定義します。 これはRailsが用意した「便利な工夫」のひとつで、これだけで7つのルーティングが記述できます。 このとき、それぞれのルーティングがどうなっているかは、./bin/rails routesコマンドで確認できます。

$ ./bin/rails routes
      Prefix Verb   URI Pattern                  Controller#Action
        root GET    /                            words#index
words_search GET    /words/search(.:format)      words#search
       words GET    /words(.:format)             words#index
             POST   /words(.:format)             words#create
    new_word GET    /words/new(.:format)         words#new
   edit_word GET    /words/:id/edit(.:format)    words#edit
        word GET    /words/:id(.:format)         words#show
             PATCH  /words/:id(.:format)         words#update
             PUT    /words/:id(.:format)         words#update
             DELETE /words/:id(.:format)         words#destroy
... ... ...

左の列「Prefix」に、「_path」をつけるとパスを返すメソッドが得られます。

root_path #=> /
words_search_path #=> /words/search
words_path #=> /words

このような形で他アクションへのメソッドも得られます。 createアクションはアドレスがindexアクションと同じなのでwords_pathでPOSTメソッドを使えばアクセスできます。 同様にupdateアクションはword_pathをPATCHまたはPUTメソッドで、destroyアクションはword_pathをDELETEメソッドでアクセスすることによりアクセスできます。

7つのルーティングがresourcesメソッド1つで書けるところが、負担軽減になっています。 このようなルーティングを「リソースフル・ルーティング」と呼んでいます。

なお、「リソース」というのはウェブサーバで扱っているデータのことで、例えばWordインスタンスの表すデータはリソースです。

レイアウト、ナビゲーションバー、フラッシュ

レイアウト

レイアウト/app/views/layouts/application.html.erbは前回のWordbookと同様ですが、画面幅は少し広めにしました。

<!DOCTYPE html>
<html>
  <head>
    <title>WordBookRailsResources</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
  </head>

  <body>
    <div class="container">
      <div class="col-lg-10 col-xl-8 mx-auto">
        <%= render "navbar" %>
        <%= render "flash" %>
        <%= yield %>
      </div>
    </div>
  </body>
</html>

ナビゲーションバー

ナビゲーションバー/app/views/words/_navbar.html.erbも前回とほぼ同様ですが次の2点が異なります。

  • 「変更」と「削除」はshowアクションからの画面でのみ有効にし、他のアクションからの画面では無効(disable)にする
  • 「検索」の窓もナビゲーションバーに付ける
<nav class="navbar navbar-expand-lg navbar-light" style="background-color: #e3f2fd;">
  <div class="container-fluid">
    <a class="navbar-brand" href="/">Wordbook</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <%= link_to "追加", new_word_path, style: "text-decoration: none;", class: "nav-link" %>
        </li>
        <li class="nav-item">
          <% if action_name == "show" && @word %>
            <%= link_to "変更", edit_word_path(@word), style: "text-decoration: none;", class: "nav-link" %>
          <% else %>
            <a class="nav-link disabled" href="#">変更</a>
          <% end %>
        </li>
        <li class="nav-item">
          <% if action_name == "show" && @word %>
            <%= link_to "削除", @word, style: "text-decoration: none;", class: "nav-link", data: {turbo_method: :delete, turbo_confirm: "Are you sure?"} %>
          <% else %>
            <a class="nav-link disabled" href="#">削除</a>
          <% end %>
        </li>
      </ul>
      <%= form_with  url: words_search_path, method: :get, class: "d-flex" do |form| %>
        <%= form.search_field :search, placeholder: "検索", class: "form-control me-2" %>
        <%= form.submit "検索", class: "btn btn-outline-success text-nowrap" %>
      <% end %>
    </div>
  </div>
</nav>

13、20行目に<% if action_name == "show" %>があります。 action_nameはRailsのメソッドで、そのときのアクション名を文字列で返します。 したがって、if節はアクションがshowのときだけ実行され、それ以外はelse節(リンクdisable)になります。

また、削除リンクはdata: {turbo_method: :delete, turbo_confirm: "Are you sure?"}により、HTTPメソッドがdeleteになり、「Are you sure?」の確認ダイアログが表示されます。 前回のwordbookではフォームの送信ボタンが削除のきっかけになっていましたが、今回はナビゲーションバーの「削除」メニューがきっかけになっています。 また、リンク先が@wordとなっています。 リソースフル・ルーティングでは@wordword_path(@word)は同じパスを指します。

下から7〜4行目が検索部分で、form_withによるフォーム送信が埋め込まれています。 「検索」ボタンを押すとsearchアクションに飛ぶようにリンク先がwords_search_pathメソッドで与えられています。

フラッシュ

フラッシュは前回と同じです。

<% flash.each do |name, msg| %>
  <% if name == "success" %>
    <%= content_tag :div, msg, class: "text-success" %>
  <% elsif name == "alert" %>
    <%= content_tag :div, msg, class: "text-danger" %>
  <% end %>
<% end %>

indexアクション

indexアクションは初期画面です。 Wordbookの使い方を表示します。

コントローラでは特にやることはありません。

def index
end

ビューapp/views/words/index.html.erbは次のようになります。

<h1 class="text-center">単語帳</h1>
<h5 class="my-2">単語帳の使い方</h5>
<ul class="list-group my-2">
  <li class="list-group-item">Wordbook: 初期画面に戻ります</li>
  <li class="list-group-item">追加: 単語を追加します</li>
  <li class="list-group-item">検索: 単語を検索しマッチした単語を表示します</li>
</ul>
<p>
検索にRubyの正規表現を使うことができます。
各単語に対して「英単語」「日本語訳」「備考」を書き、保存することができます。
「備考」は複数行のテキストが可能なので、例文や解説などを書くのに適しています。
</p>
<p>
単語の表示、変更、削除は次のようにしてください。
なお「単語の表示」または「表示画面」とは、ひとつの単語についてその日本語訳と備考を表示すること、またはその画面です。
検索結果の画面では備考は表示されません。
</p>
<ul class="list-group my-2">
  <li class="list-group-item">表示: 検索後の一覧において、各項目の左にあるボタンをクリック</li>
  <li class="list-group-item">変更: 表示画面から変更メニューをクリック</li>
  <li class="list-group-item">削除: 表示画面から削除メニューをクリック</li>
</ul>

searchアクション

ナビゲーションバーの入力枠に正規表現を入れ、検索ボタンをクリックすることにより、/words/searchにgetメソッドでアクセスします。 これはsearchアクションにルーティングされます。

def search
  @search_word = params[:search]
  if @search_word == ""
    flash.now[:alert] = "検索ワードは入力必須です"
    render html: "", status: :unprocessable_entity
  end
  begin
    pattern = Regexp.compile(@search_word)
  rescue RegexpError
    flash.now[:alert] = "正規表現に構文エラーがあります"
    render :index, status: :unprocessable_entity
  else
    @words = Word.all.select{|word| word[:en] =~ pattern}.sort{|w1,w2| w1[:en] <=> w2[:en]}
  end
end

検索ワードはsearchという名前で送られるので、params[:search]で取り出すことができます。 searchアクションの内容は、前回のWordbookのlistアクションとほぼ同じです。

ビュー/app/views/words/search.html.erbは次のようになります。

<h1 class="my-2">単語検索結果</h1>
<p>検索ワード: <%= @search_word %></p>
<% if @words %>
  <table class="table table-bordered">
    <thead>
      <tr>
        <th scope="col">英語</th>
        <th scope="col">日本語</th>
      </tr>
    </thead>
    <tbody>
    <% @words.each do |word| %>
      <tr>
        <td><%= link_to word[:en], word %></td>
        <td><%= word[:jp] %></td>
      </tr>
    <% end %>
    </tbody>
  </table>
<% end %>

ここでは、英語と日本語訳のみを表にして表示します。 英単語はshowアクションへのリンクになっています。 wordがshowアクションへのリンクです。 このリンクには該当の単語のid(データベースの通し番号)が挿入されます。

showアクション

showアクションはid番号を用いてデータベースからWordモデルを取り出します。

def show
  begin
    @word = Word.find(params[:id])
  rescue ActiveRecord::RecordNotFound
    @word = nil
    flash.now[:alert] = "データベースにはid=#{params[:id]}のデータは登録されていません"
  end
end    

search画面のリンクからshowアクションに遷移した場合はエラーになることはありません。 クライアント側が適当なid番号で「words/id番号」をgetでアクセスした場合にはエラーの発生する可能性があります。 そのためrescueを使ったエラー処理を入れておきました。

ビュー/app/views/words/show.html.erbは次のようになります。

<% if @word %>
  <ul class="list-group my-2">
    <li class="list-group-item"><%= @word.en %></li>
    <li class="list-group-item"><%= @word.jp %></li>
    <li class="list-group-item"><%= @word.note %></li>
  </ul>
<% end %>

showでは英単語、日本語訳に加え備考(@word.note)も表示します。

newとcreateアクション

newアクション

ナビゲーションバーの「追加」をクリックすると/words/newにgetメソッドでアクセスします。 そして、newアクションにルーティングされます。

newコントローラはWordモデルを生成して@wordに代入します。

def new
  @word = Word.new
  @submit = "作成"
end

ビュー/app/views/words/new.html.erbは次のようになります。

<h1 class="my-2">単語登録</h1>
<%= render "form" %>

formパーシャル

画面の組み立てはformパーシャルが行います。

<%= form_with model: @word do |form| %>
  <div>
    <%= form.label :en, "英単語", class: "form-label" %>
    <%= form.text_field :en, value: @word.en, class: "form-control" %>
    <% @word.errors.full_messages_for(:en).each do |message| %>
      <div class="text-danger"><%= "DB: 英単語は空欄にできません" if message == "En can't be blank" %></div>
      <div class="text-danger"><%= "DB: 英文字を入力してください" if message == "En is invalid" %></div>
      <div class="text-danger"><%= "DB: すでに同名の単語が登録されています" if message == "En has already been taken" %></div>
    <% end %>
  </div>

  <div>
    <%= form.label :jp, "日本語訳", class: "form-label" %>
    <%= form.text_field :jp, value: @word.jp, class: "form-control" %>
    <% @word.errors.full_messages_for(:jp).each do |message| %>
      <div class="text-danger"><%= "DB: 日本語訳は空欄にできません" if message == "Jp can't be blank" %></div>
    <% end %>
  </div>

  <div>
    <%= form.label :note, "備考", class: "form-label" %>
    <%= form.text_area :note, value: @word.note, class: "form-control" %>
    <% @word.errors.full_messages_for(:jp).each do |message| %>
      <div class="text-danger"><%= message %></div>
    <% end %>
  </div>

  <div class="my-2">
    <%= form.submit @submit,  class: "btn btn-primary" %>
  </div>
<% end %>

ルーティングがリソースフルである場合は、form_withにモデルを設定すればurlは省略できます。 送信ボタンを押すとcreateアクションにアクセスします。 「備考」の入力枠はform.text_areaで作ります。 複数行のテキストを想定した入力フォームです。

createアクション

createアクションはコントローラのみでビューはありません。

def create
  @word = Word.new(word_params)
  if @word.save
    flash[:success] = "単語を保存しました"
    redirect_to @word, status: :see_other
  else
    flash.now[:alert] = "単語を保存できませんでした"
    render :new, status: :unprocessable_entity
  end
end

private

def word_params
  params.require(:word).permit(:en, :jp, :note)
end

プライベートメソッドword_paramsはクライアントからのデータを調べ、必要なものだけを取り出します。 この仕組みはparamsrequirepermitの3つのメソッドで構成されています。

  • params: ActionController::Parametersオブジェクトを返す。 このオブジェクトはクライアントから送られてきたデータを、キーと値の形式(ハッシュに似た形式)で保持している
  • require: パラメータにキーが与えられたとき、その値があればその値を持つActionController::Parametersオブジェクトを返す。 そうでなければエラーになる。
  • permit: パラメータにはキーのリストをとる。 与えられたキー以外のデータは捨てられ、指定されたキーと値のみのActionController::Parametersオブジェクトを返す

この仕組みはストロング・パラメータと呼ばれ、仮に不正なデータが送られたとしてもそれを除去することができます。 createメソッドでWord.new(word_params)としても安全です。 これを使わず`Word.new(params)とするとサーバ側で予期していないデータを保存しようとする可能性があり、エラーになったり、何らかの問題を引き起こす可能性があります。

Wordbookではストロングパラメータを使わなくてもほとんど危険はありませんが、ユーザ登録の仕組みを持つサーバでは脆弱性が発生することがあります。 例えば、ユーザモデルUserが3つのフィールドname、email、adminを持っていて、最後のadminは管理者権限を表し、true=adminnil|false=not adminだとします。 newアクションのビューではnameとemailのみをデータ送信するようになっているとします。 通常なら@user=User.new(params)でnameとemailのみ代入され、admin=nilとなるのですが、 悪意のあるユーザがPOSTデータを改ざんしname、emailに加えadmin=trueを送ってきたとすると、新規ユーザは管理者になってしまいます。 ストロングパラメータがパラメータをnameとemailに限定すれば、このような危険は無くなるというわけです。

createアクションでは、単語登録できればshowにリダイレクト、失敗したら再度newの画面を表示します。

editとupdateアクション

editアクション

editアクションはshowアクションから遷移される前提です。 showアクションの画面ではナビゲーションバーの「変更」リンクが有効になります。 /words/:id/editにアクセスがあるとeditアクションにルーティングされ、:idのところの数字がパラメータとしてparams[:id]にセットされます。

def edit
  begin
    @word = Word.find(params[:id])
  rescue ActiveRecord::RecordNotFound
    @word = nil
    flash[:alert] = "データベースにはid=#{params[:id]}のデータは登録されていません"
    redirect_to words_path, status: :see_other
  end
  @submit = "変更"
end

show画面から遷移すればWord.find(params[:id])がエラーになることはありませんが、ユーザがURLを作ってアクセスすると、そうとも限りません。 そこで、rescueを使ったエラーの捕捉をしています。

ビューは次のようになります。

<h1 class="my-2">単語の変更</h1>
<%= render "form" %>

newと共有しているformパーシャルを使います。 editの場合は送られてきたデータによってフォーム入力枠に値が入った状態から編集することができます。 編集が終わるとupdateアクションに遷移します。 newではcreateアクションへの遷移でした。 どこでcreateとupdateを区別しているかと言うと、@wordのidフィールドがnilか数字かの違いです。 この判断はform_withメソッドがしてくれるので、プログラマーが気にする必要はありません。

updateアクション

updateアクションはコントローラのみでビューはありません。

def update
  @word = Word.find(params[:id])
  if @word.update(word_params)
    redirect_to @word, status: :see_other
  else
    flash.now[:alert] = "単語「#{@word.en}」は変更できませんでした"
    render :edit, status: :unprocessable_entity
  end
end

アップデートができたらshowにリダイレクト、失敗したらedit画面を再表示します。 @wordだけで/words/:idにリダイレクトできます。 word_path(@word)よりも短い@wordだけで同じリンク先を生成してくれるは、リソースフル・ルーティングのさらなる恩恵です。

destroyアクション

show画面ではナビゲーションバーの「削除」リンクが使えるようになります。 それをクリックするとdestroyアクションに遷移します。 destroyアクションはコントローラだけでビューはありません。

def destroy
  @word = Word.find(params[:id])
  if @word == nil
    flash[:alert] = "単語#{@en}は未登録のため削除できません"
  else
    begin
      @word.destroy
    rescue
      flash[:alert] = "単語#{@en}を削除できませんでした"
    else
      flash[:success] = "単語を削除しました"
    end
    redirect_to words_path, status: :see_other
  end
end

削除ができてもできなくてもINDEX画面にリダイレクトします。 クライアント側はフラッシュ・メッセージによって削除できたかどうかを知ることができます。

起動

コマンドラインから起動します。

$ ./bin/rails server

ブラウザを起動しhttp://localhost:3000にアクセスするとWordbookの初期画面が現れます。

railsを終了するには、コマンドラインからCTRL-Cを入力します。

まとめ

前回のWordbookと比べ、大きな差はないものの、リソースフル・ルーティングを使ったおかげで楽をした部分がありました。 また、Railsの慣例に従っているので、メンテナが変わっても分かりやすいはずです。 そのような保守管理の意味でも慣例を守るのは重要なことです。

Wordbookはシンプルで分かりやすいと思います。 実際のウェブの開発はもっと複雑でデータベース・テーブルも複数になり、それらが関係しあっていることもあります。 そのようなテーブル間の関係をRailsはサポートしているのですが、今回はそこまでは踏み込みませんでした。 詳しいことは「Rails Guide」を参照してください。

また、ソースコードはGitHub_example/word_book_rails_resourcesにありますので、 必要な方はダウンロードまたはクローンしてお使いください。

2023

単項マイナスと構文解析

1 minute read

単項マイナスとは 単項マイナスと括弧 括弧なし単項マイナスを許容する場合のBNF calcの場合

Raccライブラリと構文解析

3 minute read

パーサ・ジェネレータとは 少し複雑な文法 四則(加減乗除)計算のBNF Racc で実装 クラス定義、BNFの記述部分 ヘッダー、インナー、フッター コンパイルと実行 演算子の優先順位と結合における左右の優先順位 まとめ

StrScanライブラリと字句解析

less than 1 minute read

StrScanライブラリのドキュメント 字句解析とは StrScanライブラリ StrScanライブラリを使った字句解析 実例

Gem

1 minute read

lbtというgemを作って公開してみた lbtはどんなgemか ファイルの配置 lbt.gemspec Rakefile gemのビルド RubyGems.orgへのアップロード 補足・・rake/gempackagetaskサブライブラリについて

Encoding

1 minute read

文字列のエンコーディングに頭を悩ませることはほとんどなくなりました。 なぜなら、どのアプリ、システムもUTF-8を使うようになったからです。 Rubyでもエンコーディングの問題が起こることはまず無いでしょう。 ですが、今回はエンコーディングの考え方を整理してみたいと思います。

Thread

less than 1 minute read

Fiberを書いたときから、次はスレッドを書こうと思っていましたが、時間がかかってしまいました。 その理由は、期待したとおりのスレッドの効果がなかったためです。 今回はそのことを書きますが、これはRubyのスレッドの抱えている問題なのか、自分のやり方が悪いのかははっきりしていません。

Fiber

1 minute read

Fiberは「ノンプリエンプティブな軽量スレッド」とRubyのマニュアルに記載されています。

RDoc

less than 1 minute read

今回はRubyプログラムから自動的にドキュメントを作成するRDocについて書きたいと思います。 私はこのことについて、エキスパートではありません。 この記事も、初心者の体験談だと考えてください。

Back to Top ↑

2022

Ruby/GTK4

5 minute read

Ruby/Gtkの記事を先日書いたときに、「これはかなり使える」という手応えを感じたので、WordBook(Railsで作った単語帳プログラム)のGTK 4版を作りました。 プログラムは「徒然なるままにRuby」のGitHubレポジトリに置いてあります。 レポジトリをダウンロードし、ディレクトリ_example/...

Shoes – Rubyとグラフィック

5 minute read

Rubyはグラフィックについて弱い印象があります。 しかし、グラフィックはデバイスに関することなので、言語そのものには直接の関係はないはずで、あるとすればライブラリです。 今後グラフィック関係のgemが開発されることに期待しましょう。

Rails7 テスト

5 minute read

前回作ったWordbook(リソースフル)のテストを書いてみます。 RailsのテストはminitestをRails用に拡張したものです。

Rails7 モデルとデータベース

5 minute read

今回はRailsにおけるデータの作成と保存、そして変更について説明します。 そのベースになるモデルとデータベースの話から始め、appendとchangeの動作について詳しく説明します。

Rails7とBootstrap

3 minute read

一般に、HTMLは文書の構造を表し、CSSはその体裁(見栄え)を表します。 Railsは最終的にCSSを含むHTML文書を出力するので、この2つについての理解が必須です。 この記事ではとくにCSSの人気ライブラリであるBootstrapを紹介します。 BootstrapはJavascriptも含んでいます。

Rails7のインストール

2 minute read

Rubyの最も人気のあるアプリケーションであるRuby on Railsを取り上げようと思い、書き始めました。 予想してはいましたが、相当な分量になってしまいました。 そのため、何回かに分けて記事にすることにします。 また、対象となる読者のレベルをどうしようかと考えましたが、「徒然Ruby」が基礎的な内容から始ま...

GemとBundler

1 minute read

Rubyのライブラリ管理システムのRubygemsとコマンドgemおよびbundlerについて説明します。

minitest(3)モックの詳細

1 minute read

minitestについて連続して2回書いてきました。 「minitestはドキュメントが少ない」という人がいますが、私も同感です。 例えば、モックとスタブの説明も少ないです。 そこで、今回はmock.rbのソースコードを参考に、モックの私的ドキュメントを書いてみました。 あくまで私個人の考えであり、minites...

minitest(1)テストとは

2 minute read

アプリ作成の記事でminitestを使いました。 今回はminitestについて、また一般にテストについて、私の考えを書こうと思います。

public、private、protected

2 minute read

今回はメソッドの呼び出し制限ついて説明します。 呼び出し制限にはpublic、private、protectedの3つがあります。

アプリ制作、インストール、テスト

1 minute read

2023/10/29 追記:この記事は新しく書き直しました。 古い記事で使っていたGitHubのCalcが大幅にアップデートされたためです。 そこで、この記事に合うようなプログラムsimple_calcを新たに作りました。 このプログラムは本レポジトリの_example/simple_calcにあります。

case文

2 minute read

if〜elsif〜・・・〜else〜endは皆さん良く使うでしょうか? これは場合分けで良く使われる方法です。 これと同様の制御構造にcase文があります。 Cのswitch文に似ていますが、より強力な機能を持っています。 if-else-endよりも高い能力があるといえます。

Lambda

2 minute read

Procオブジェクトを生成するメソッドlambdaについて説明します。

Proc オブジェクト

2 minute read

今回はブロックを一般化したオブジェクトProcを説明します。

モジュール

1 minute read

モジュールには名前空間とミックスイン(Mix-in)の2つの機能があります。 ここではミックスインについて説明します。

Kernelモジュール

less than 1 minute read

Kernelモジュールのメソッドはどこでも使うことができます。 そのメソッドの中には便利で有用なものが多いです。

便利なメソッド

1 minute read

ここでは私が便利だと思ったメソッドを紹介します。

文字列と正規表現

3 minute read

文字列は最も使うオブジェクトのひとつです。 特にウェブ・アプリケーションでは、コンテンツだけでなくHTMLのタグやCSSを含めすべてが文字列です。 Rubyは文字列オブジェクトのメソッドが充実しており、またパターンマッチのための正規表現も充実しています。

配列

2 minute read

配列は、どのプログラミング言語にもあると思います。 複数の要素を一括して扱うことができるのが配列です。 Rubyの配列はメソッドが充実しているので、プログラムを効率的、機能的に書くのに役立ちます。

トップレベルのメソッド

1 minute read

今回はメソッド定義です。 メソッド定義はRubyの核心ですが、今回はトップレベルに限って説明します。 この限定によって、内容はかなり易しくなっています。

ブロックとイテレータ

less than 1 minute read

ブロックはRubyの特長です。 ブロックのおかげで記述が非常にすっきりと分かりやすくなります。 今回はブロックをイテレータの本体として使う方法を説明します。

整数

less than 1 minute read

ここではRubyの最も基本的なオブジェクトである整数について説明します。

Hello world

less than 1 minute read

「徒然なるままに」をネットで調べてみると、「することもなく、手持無沙汰なのにまかせてという意味」とありました。 まさに、自分の現状を言い当てた言葉。 しかも、ブログに書くネタもなかなか思いつかない日々。

Back to Top ↑