LoginSignup
35
33

More than 5 years have passed since last update.

Ruby on Railsに手を出してみたのでそのメモ

Last updated at Posted at 2015-09-05

最近ちょっと作りたいサービスがあって、サーバサイドとしてRuby on Railsをやってみようと思い立ち、入門してみました。
そもそもRuby自体ほとんど書いたことないので、細かいものをつらつらとメモしていきます。

Railsとは

Railsにはいくつか大事な考え方があるようです。
ひとつは DRY(Don't Repeat Your self)で、同じことを繰り返すな、ということ。なので同じ記述が現れるところはどんどん共通化していく方針のようです。(そのための仕組みが多数用意されています)

そしてもっとも大事なものが「設定より規約」と呼ばれるソフトウェア設計パラダイムです。
端的に言うと、規約に基いてコードを書けば設定はいらない、ということです。

つまり、Rails側で規約を定めていて、その規約に則ってコードを書いている限り、設定を書く必要がなくなります。
なので、ルールに基いてモデルクラスを宣言するだけで基本的な処理(Create, Read, Update, Delete)などは自動的に行われます。

MVCに基づく設計


MVCとRailsの基本構成を学ぼうから引用

後述しますが、モデルやコントローラのひな形を自動生成してくれる便利なコマンドがあります。
基本的な処理はそのコマンドから初めて、必要な箇所だけあとから編集、というのがおおまかな処理の流れになると思います。

Model

app/models に配置されます。

Modelは ActiveRecord::Base クラスを継承したものになります。
基本的な CRUD (Create, Read, Update, Delete) の仕組みはベースクラスで定義されているため、特殊な処理がないモデルの場合は以下のように定義するだけで基本的な機能を使うことができます。

コメントで指摘もらいましたが、あくまでその処理を行うことが定義されている、という意味です。
なので実際にアプリケーションとして実行可能な状態にするにはコントローラなどとの連携が必要になります。

Model
class Product < ActiveRecord::Base
end

インタラクティブな操作

以下のコマンドを使うと、ターミナルからインタラクティブにモデルデータの操作を行うことができます。

$ rails console
Loading development environment (Rails 4.2.3)
2.2.3 :001 >

実行すると上記のようになるので、そこにRubyのコードを書いてモデルの生成を行うと、そのままDBに反映することができます。
(ちなみに quit で抜けることができます)

例)

Product.create(title: "hoge")

Modelを作成する

モデルクラスのひな形とDBのマイグレーションファイルを作成するには以下のコマンドを実行します。

$ rails g model ModelName fieldName1:string fieldName2:integer

ちなみに、デフォルトの型は string のため、string の型の場合は省略することができます。

また、いわゆる has meny な関係を作りたい場合は以下のようにします。

$ rails g model Hoge title fuga:references

ここについては少し勘違いをしていました。
コメントを引用させてもらうと以下の意味のようです。

fuga:references は,Fuga モデルに属すること(belongs_to)を含意しているだけです。Fuga モデルから見てこちらを has_many とは限りません。has_one かもしれない。

上記を実行するとHogeクラスには belogns_to :fuga が自動挿入されます。
ただ、fugaモデルにはその記述が自動挿入されないので、手で追記する必要があります。

class Fuga < ActiveRecord::Base
    has_many :tasks # あるいは has_one
    # ...
end
Modelで使用される型
概要
string 文字列
text 長い文字列
integer 整数
float 浮動小数点数
decimal 精度の高い小数
datetime 日時
timestamp タイムスタンプ
time 時刻
date 日付
binary バイナリ
boolean 真理値
primary_key 主キー

Modelのカラムを更新する

こちらの記事を参考にしました。

Modelのカラムを更新するには、マイグレーションスクリプトを生成し、それを実行する必要があります。

例えば、urlmessage という新しいカラムを追加する場合は以下のようにします。

$ rails g migration AddXXXToYYYY columnName:columnType (columnName:columnType ...)

ここで、XXX は追加するカラム名など任意の文字列です。(複数追加する場合などは明示できないため)
そして YYY は対象のテーブル名をスネークケースで指定します。

仮に any_models というテーブル名だったとしたら、 AddParamsToAnyModels という感じです。

そしてこれを実行するとRails側で適切にマイグレーションスクリプトを生成してくれます。
あとはこれを実行してあげればDBがマイグレーションされます。

$ rake db:migrate

ちなみに db/migrate/2015....rb みたいな形でファイルが生成されますが、これを削除する場合は以下のようにします。

$ rails destroy migration AddParamsToAnyModels

ファイルを直に消しても大丈夫かはやってないので分かりません・・。

Modelに関する規約

Railsのルール(規約)として、モデルは 大文字始まりの単数形 が定められています。

Controller

app/controllers に配置されます。

ユーザからの操作を受け付けて、アプリケーションの動作を決定するコントローラです。

ルーティングを設定する

プロジェクトディレクトリの下に config ディレクトリがあります。
その中の routes.rb ファイルにルートをに関する設定をしてあげると自動的にそのルーティングを行う処理を実行してくれます。

Rails.application.routes.draw do
    resources :projects

    # 以下略
end
rootを設定する

サイトトップにアクセスしたときなどに、どこを表示して欲しいかをコントローラとアクションの単位で指定しておくことができます。

例)

root 'projects#index'

上記のようにすると、トップに来た場合に projectsindex アクションが実行されます。

URLの階層を定義する

以下のようにすることで、あるモデル以下に紐付いた他モデルのデータ(has many的な)を表示、というようなURLのルーティングを実現することができます。
(いわゆるhas manyの関係にあるデータの表示とか)

resources :projects do
    resources :tasks, only: [:create, :destroy]
end

こうすることで、とあるプロジェクトに紐付いたタスク一覧を表示するURLを設定することができます。

特定URLをアクションに結びつける

このURLにアクセスしたらこのアクションを実行したい、という場合は以下のようにすることで設定することができます。

post '/projects/:project_id/tasks/:id/toggle' => 'tasks#toggle'

tasks はコントローラです。そのコントローラの toggle メソッド(アクション)を実行する設定です。

Controllerのルーティングを確認する

ルーティングの設定ができたら rake routes コマンドでルーティングを確認することができます。

$ rake routes
       Prefix Verb   URI Pattern                                      Controller#Action
project_tasks POST   /projects/:project_id/tasks(.:format)            tasks#create
 project_task DELETE /projects/:project_id/tasks/:id(.:format)        tasks#destroy
     projects GET    /projects(.:format)                              projects#index
              POST   /projects(.:format)                              projects#create
  new_project GET    /projects/new(.:format)                          projects#new
 edit_project GET    /projects/:id/edit(.:format)                     projects#edit
      project GET    /projects/:id(.:format)                          projects#show
              PATCH  /projects/:id(.:format)                          projects#update
              PUT    /projects/:id(.:format)                          projects#update
              DELETE /projects/:id(.:format)                          projects#destroy
              POST   /projects/:project_id/tasks/:id/toggle(.:format) tasks#toggle
         root GET    /                                                projects#index

before_action, after_action

モデルの取得など、各アクションの中で共通に処理する部分があるかと思います。
その際に、同じことを書くのはDRYに反するので、before_actionafter_action に処理をまとめることで共通化することができます。
具体的には以下のようにします。

controller
class ProjectsController < ApplicationController
    before_action :anyMethod, only: [:show, :edit]

    private
        def anyMethod
            # do common action
        end
end

ちなみにこの before_action という記述はRubyの機能で、クラス・メソッドなどを指定するとそれがクラス宣言時に実行されるようになります。
※ コメントで指摘をもらったので補足しておきます。before_action というメソッド自体はRails側の機能です。ただ、クラス宣言時に実行される、という点がRubyの機能という意味です。

Controllerに関する規約

モデルを操作するコントローラを作成する場合は同様に、モデル名の複数形で作成する必要があります。上記の例で言えば Projects
さらに、上記のルーティングで示されている Controller#Action の項目が、コントローラにどのメソッドを実装したらどのアクションが実行されるかを表しています。
例えば、index メソッドを実装すれば /projects(.:format) にアクセスされたときにそれが実行されます。

View

app/views に配置されます。

HTMLをレンダリングし表示するビュー。
ちなみに ERB(Embed RuByの略) を利用してHTMLを構築します。

<% if (hoge) %>
    ここにHTML
<% end %>

<%= hoge.name %>

<% ~ %><%= ~ %> という記述方法がある。
前者はRubyを実行するだけで返り値は無視されますが、後者は戻り値がそのままHTMLとして出力される点が異なります。

パーシャルを使う

DRY(Don't repeat your self)の精神で、同じことを記述することを避けるのがRails風です。
ということで、Viewの中で同じ記述が現れる箇所がある場合は、「パーシャル」という機能を使ってまとめておくと便利です。

パーシャルの使い方にもルールがあり、以下のように記述します。

<%= render 'hoge' %>

上記は erb ファイルの一部です。上記のように render メソッドを使ってパーシャルを呼び出します。
パーシャル自体は、Viewsの中に、renderの引数に渡された文字列にアンダースコアを付けたファイル(上記の例では _hoge.erb)を作成し、そこに共通項目を書きます。
あとはRailsが規約に則って該当のパーシャルのその位置に読み込んでくれます。

Viewに関する規約

Viewに関する規約は、コントローラのアクション名と同名のファイル名にする、という点です。
(例えば index アクションなら index.html.erb ファイル)

共通テンプレート

Viewはまた、共通テンプレートを持つことができます。HTML内のhead要素などサイト内で共通にしておきたいものはたくさんあると思います。
それらについては app/views/layouts ディレクトリ内に配置されます。

また、各Viewに記述された内容はテンプレート内の <%= yield %> に展開されるようになっています。

プロジェクトの作成

以下の rails コマンドでさくっと新規プロジェクトが生成できます。

$ rails new hoge

データ(モデル)の作成

モデルの作成には bundle exec rails generate scaffold を使います。

$ rails generate scaffold hoge name:string fuga:string

ちなみに、generateg のみでも実行可能です。

$ rails g scaffold hoge name:string fuga:string

また、DBのマイグレーションファイルも自動生成されるため、以下のようにすることでDBをマイグレーションすることができます。

$ rake db:migrate

作成したアプリケーションの動きをブラウザで確認する

$ rails server

s だけでも起動できます。

$ rails s

bundle exec

いくつかのコマンドで bundle exec というのが使われていますが、これは、プロジェクト内の vendeor/bundle 内に保存されている gem を使うためのコマンドのようです。


Rails 4からの便利機能

http://localhost:3000/rails/info/routes でルートを確認することができます。
POSTやGETの種類、引数としてどんなパラメータが必要かなどが一覧されるので便利。


覚えておきたいメモ

レスポンスを JSON で返します。

controllerで出し分けができるみたい。
具体的には以下。

json
class AnyController < ApplicationController
    def index
        @products = Product.all

        respond_to {|format|
            format.html # => 通常のアクセス
            format.json { render json: @products } # URLが `.json` でのアクセス
        }
    end
end

上記のように、アクション処理の中で respond_to メソッドを使って、フォーマットに応じて処理を分けてやると実現できます。

Rubyについてのメモ別記事に移動しました。

JSONを返すAPIで

スタブ環境みたいなものを作ろうと思って、モデルを2つ用意して、それをネストしてJSONとして返す、みたいなことをやろうとして意外とハマったのでメモ。

以下のようなモデルがあったとして。

class HogeModel < ActiveRecord::Base
    has_one :fuga_model
end
class FugaModel < ActiveRecord::Base
    belongs_to :hoge_model
end

こんな感じでコントローラを書く。

class HogeModelsController < ApplicationController
    def index
        @hoge_models = HogeModel.all
        @fuga_models = FugaModel.all

        render :json => @hoge_models, :methods => :fuga_model
    end
end

まだRubyからして怪しいけど、とりあえずこれで目的のような形になった。

参考記事

35
33
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
33