キーワード引数を使ってみる

キーワード引数とは

メソッドの引数に名前(キーワード)を付けることができる機能です。
名前を付けることで、引数の意味がわかりやすくなったり、引数の順番を意識しなくても良くなります。

キーワード引数を使ってメソッドを定義してみる

今回はself_introductionという自己紹介を出力してくれる、メソッドを定義します。

def self_introduction(name:, age:, sex:)
  puts "私の名前は#{name}です"
  puts "#{age}歳の#{sex}です"
end

self_introductionメソッドを呼び出してみます。

self_introduction(name: '太郎', age: 20, sex: '')
=>私の名前は太郎です
  20歳の男です

f:id:maru877:20170706090829p:plain

次に引数の順番を変えて、self_introductionメソッドを呼び出してみます。

self_introduction(sex: '', age: 20, name: '太郎')
=>私の名前は太郎です
  20歳の男です

f:id:maru877:20170706091306p:plain
順番を変更しても、処理結果は変わりません。

メソッド定義の段階でキーワードにデフォルト値を設定することもできます。

# キーワードにデフォルト値を設定する
def self_introduction(name: '名無し', age: 'n', sex: '?')
  puts "私の名前は#{name}です"
  puts "#{age}歳の#{sex}です"
end

# 引数を渡さずに、呼び出す
self_introduction
=>私の名前は名無しです
  n歳の?で

f:id:maru877:20170706092646p:plain

ちなみにデフォルト値を設定せずに、引数を渡さない場合は、
ArgumentErrorが発生するのでご注意を。
f:id:maru877:20170706093035p:plain

このようにキーワード引数を使うことによって、 引数の数が多くなってもコードの可読性を保つことができます。

enumを使ってみる

enumとは

ActiveRecordが提供する機能の一種で、列挙型のクラスのことです。

土台となるアプリケーションを作成する

$ rails new enum_test
$ rails g scaffold User name:string role:integer

マイグレーションファイルを修正する

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name
      t.integer :role, default: 0, null: false

      t.timestamps
    end
  end
end

$ bin/rails g migrate

modelにenumを定義する

class User < ApplicationRecord
  enum role: { normal: 0, staff: 1 }
end

今回はユーザーにnormalとstaffという2つの権限を設定できるようにします。

ユーザを登録する

$ bin/rails cでコンソールを立ち上げ、
enum定義したnormalとstaff権限を持つユーザーを1データずつ作成します。

$ User.create(name: 'ノーマルユーザーさん', role: 0)
$ User.create(name: 'スタッフユーザーさん', role: 1)
f:id:maru877:20170705202005p:plain
$ User.allでデータの中身を確認してみる f:id:maru877:20170705202709p:plain

enumのメソッドを使ってみる

先ほど作成したノーマルスタッフさんを取り出して、enumのメソッドを検証していきます。

# usersテーブルからノーマルユーザーさんを取り出します
user = User.find(1)

# ユーザーのロールを確認します。(1ではなく、定義したキー値が返却されます)
user.role
=> "normal"

# userがnormalであるかどうかを、真偽値で返却します。
user.normal?
=> true

# userがstaffであるかどうかを、真偽値で返却します。
user.staff?
=> false

# userをnormalからstaffへ変更します。
user.staff!
=> UPDATE "users" SET "role" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["role", 1], ["updated_at", "2017-07-05 11:32:34.172870"], ["id", 1]

# userがstaffに変更されているか確認します。
user.role
=> "staff"

f:id:maru877:20170705203315p:plain

このようにenumを使うことでデータ数を固定できたり、
コードの可読性を向上させることができます。

[Try Gem] CarrierWaveを使ってみる

CarrierWaveとは?

画像のアップロード機能を簡単に実装できるGemです。

土台となるアプリケーションを作成する

$ rails new carrierwave_test
$ rails g scaffold Blog title:string content:text image:string
$ bin/rails db:migrate
$ brew install imagemagick

画像情報を格納しておくimage:stringをあらかじめ用意しておきます。 また、今回は画像を扱うのでImageMagickという、画像操作に必要なソフトウェアをインストールしておきます。

CarrierWaveをインストー

gem 'carrierwave'
gem 'rmagick'

$ bundle install
rmagickはアップロードした画像のリサイズに必要なので、
carrierwaveとセットでインストールしておきます。

アップローダーを作成

$ rails g uploader image
app/uploaders/image_uploader.rbアップローダーが作成されます。

モデルにアップローダーを配置

class Blog < ApplicationRecord
  mount_uploader :image, ImageUploader
end

先ほど作成したアップローダーをBlogモデルに配置します。

入力フォームを修正

<%= form_for(blog) do |f| %>
  <% if blog.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(blog.errors.count, "error") %> prohibited this blog from being saved:</h2>

      <ul>
      <% blog.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div>

  <div class="field">
    <%= f.label :content %>
    <%= f.text_area :content %>
  </div>

  <div class="field">
    <%= f.label :image %>
    <%= f.file_field :image %>
    <%= f.hidden_field :image_cache %>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

<%= f.hidden_field :image_cache %>を追記しておくことで、
バリデーションエラー等でrenderされた場合でも、画像をキャッシュしておくことができます。

ビューを修正

<p id="notice"><%= notice %></p>

<p>
  <strong>Title:</strong>
  <%= @blog.title %>
</p>

<p>
  <strong>Content:</strong>
  <%= @blog.content %>
</p>

<p>
  <%= image_tag @blog.image %>
</p>

<%= link_to 'Edit', edit_blog_path(@blog) %> |
<%= link_to 'Back', blogs_path %>

ブラウザで確認

f:id:maru877:20170704124554p:plain

このようにCarrierWaveを使うことで、簡単に画像をアップロードすることができます。

CSV.generateを使って、配列の中身をCSV形式でダウンロードする

CSV.generateとは?

対象データを自動的にCSV形式に変換してくれるCSVライブラリの一種です。

テストデータの作成

今回は辞書のような配列を用意し、csvファイル作成します。

dictionary = [['', 'dog'], ['', 'cat'], ['', 'pig'], ['', 'monkey']]

CSV.generateを使って、配列をCSV形式に変換

csv = CSV.generate(force_quotes: true) { |generate_data|
  dictionary.each do |data|
    set_data = [data[0], data[1]]
    generate_data << set_data
  end
}
send_data csv, type: :csv, filename: "dictionary.csv"

変数(generate_data)に格納したデータ(set_data)は自動的にcsv形式に変換され、
force_quotes: trueとすることで対象のデータを"“で囲うことができます。
実際のダウンロード処理はsend_dataを使い、指定したデータをダウンロードさせ、
file_nameには自由にファイル名を指定することができます。

ここまでの処理が成功すると、このようにcsvファイルが出来上がります。 f:id:maru877:20170703223258p:plain

補足 文字コード変換について

CSV.generateはencodingオプションを与えることで、ファイルの書式を文字コードを変換することができます。

# Encoding::SJISはShift_JISを表しています
CSV.generate(force_quotes: true, encoding:Encoding::SJIS) 
# Encoding::CP65001はutf-8を表しています
CSV.generate(force_quotes: true, encoding:Encoding::CP65001) 

それぞれの文字コードエイリアスは以下のコマンド取得できます。
$ Encoding.aliases.each {|e|p e}
f:id:maru877:20170703224659p:plain

Active Support を使ってみる

Active Supportとは?

以下、RailsGuidesより。

Active SupportはRuby on Railsコンポーネントであり、Ruby言語の拡張、ユーティリティ、その他横断的な作業を担っています。 Active Supportは言語レベルで基本部分を底上げして豊かなものにし、Railsアプリケーションの開発とRuby on Railsそれ自体の開発に役立てるべく作られています。

簡単にいうと、Active Supportを読み込むこで、Rubyには存在しない便利メソッド(文字列や数字、日付などの操作)が使えるようになるということです。

irb上でActive Supportを使ってみる

まずはActive Supportを読み込まず.blank?を使ってみます。 f:id:maru877:20170702154427p:plain
NoMethodErrorが出ましたね。普段当たり前のように使ってるblank?はruby標準搭載ではなく、 Active Supportが提供しているメソッドと言うことです。

では、コンソール上でActive Supportを読み込みます。

require 'active_support/all'

f:id:maru877:20170702155129p:plain
こうすることで、Active Supportをすべて利用することができます。

先ほど失敗した$ hoge.blank?を再度実行してみます。
f:id:maru877:20170702155610p:plain

今度は、成功しましたね。
Railsアプリケーションはデフォルトで全てのActive Supportが読み込まれているため、
意識せずともblank?等のメソッドが使えていたわけです。

fakerを使ってみる

fakerとは?

seedデータを作る際、それっぽいデータを作成することができるGemです。
それっぽいデータとは、名前であれば'john'とか'Michel'、'ken'など本物と似たようなデータのことです。

土台となるアプリケーションを作成する

$ rails new faker_test
$ rails g scaffold User name:string email:string favoreite_pokemon:string
$ bin/rails db:migrate

fakerをインストー

gem 'faker'

$ bundle install

fakerを使ってテストデータを作ってみる

100.times do |n|
  name = Faker::Name.name
  email = Faker::Internet.email
  pokemon = Faker::Pokemon.name
  User.create(name: name, email: email, favoreite_pokemon: pokemon)
end

$ bin/rails db:seed

作成されたデータを確認する

f:id:maru877:20170702150523p:plain

$ User.count
f:id:maru877:20170702150720p:plain

ちゃんと100件作れてますね。 それっぽいデータ一覧はこちらから見れます。

ピカチュウはいなかった。。。 f:id:maru877:20170702151246p:plain

kaminariを使ってみる

kaminariとは?

ページング機能を簡単に実装できるGemです。
早速実装していきます。

土台となるアプリケーションを作成する。

$ rails new kaminari_test
$ rails g scaffold Blog title:string content:text
$ bin/rails db:migrate

テストデータを10件くらい作っておきます。

f:id:maru877:20170702132923p:plain

kaminariをインストー

gem 'kaminari'

$ bundle install

indexアクションを修正

  # GET /blogs
  # GET /blogs.json
  def index
    @blogs = Blog.all.page(params[:page]).per(3)
  end

perにはページングしたい数字を渡してあげることができます。

ビューを修正

<p id="notice"><%= notice %></p>

<h1>Blogs</h1>

<!-- ページング情報を表示 -->
<%= page_entries_info @blogs %>

<table>
  <thead>
    <tr>
      <th>Title</th>
      <th>Content</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @blogs.each do |blog| %>
      <tr>
        <td><%= blog.title %></td>
        <td><%= blog.content %></td>
        <td><%= link_to 'Show', blog %></td>
        <td><%= link_to 'Edit', edit_blog_path(blog) %></td>
        <td><%= link_to 'Destroy', blog, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<!-- ページングボタンを表示 -->
<%= paginate @blogs %>

<%= link_to 'New Blog', new_blog_path %>

ブラウザ上で表示確認

f:id:maru877:20170702214920p:plain

このようにkaminariを使うことで簡単にページング機能を実装することができます。