Madogiwa Blog

主に技術系の学習メモに使っていきます。

Ruby:ppモジュールで実行結果を良い感じに確認する

はじめに

Rubyでデバック実行する時に、よくpメソッドを使うと思いますが、Rubyには標準でppモジュールというものがあります。

ppモジュールを使うとpよりも良い感じで実行結果を確認出来ます!

使い方

導入はとても簡単で、ソースコードrequire 'pp'と記載するだけです!

ソースコード

require 'pp'

users = [
  {name: "太郎", age: 20},
  {name: "花子", age: 20},
  {name: "聡美", age: 20},
  {name: "庄司", age: 20}
]

p users
pp users

実行結果

# pの結果
[{:name=>"太郎", :age=>20}, {:name=>"花子", :age=>20}, {:name=>"聡美", :age=>20}, {:name=>"庄司", :age=>20}]

# ppの結果
[{:name=>"太郎", :age=>20},
 {:name=>"花子", :age=>20},
 {:name=>"聡美", :age=>20},
 {:name=>"庄司", :age=>20}]

ppの方が良い感じに改行が入って見やすいですね!:D APIから取得したjsonを確認する時とか、色々と役に立ちそう。

参考

docs.ruby-lang.org

DockerでRubyonRailsの環境を構築してみた

f:id:madogiwa0124:20180114153719p:plain

はじめに

Dockerの勉強会に参加して少し、Dockerについて勉強しました。

tec.connpass.com

せっかく勉強したので、Raisの開発環境をDockerで構築してみました(._.)

まだまだわからないことだらけですが、とりあえず開発環境をDockerコンテナ上に構築・実行確認とherokuへのデプロイまで確認出来たので、手順をメモしてみますφ(._.)

※ちなみに下記ページを大変参考にさせて頂きました・・・!

qiita.com

DockerFile等を含んだ形でgithubサンプルソースをpushしているので、ソースだけ見たい方はこちらへ。

github.com

環境

私の環境

ちなみに私のローカル環境は、こんな感じです!

構成 内容
ローカル Mac OSX Yosemite
Docker 17.12.0-ce-mac47

Docker

Dockerとは

DockerとはRubyやPosgresといったミドルウェアをDocker上にコンテナとして構築出来るものです。

似たような技術として仮想環境がありますが、下記のようなメリットがあり、最近注目されている技術です。

  • 環境をテキストベースのファイルとして配布出来る。環境の再現性。
  • スクラップ&ビルドが容易
  • DockerがOSレイヤーをラップして、各OSの差分を吸収してくれるためOS環境を気にしなくても良い。

上記説明ではわからない部分が多いと思うので、下記のような記事で確認頂ければと思います。

employment.en-japan.com

Dockerのインストール

MACだったらDockerのインストールはとても簡単です!

下記のインストールページにアクセスし、Get Dockerを押すと安定版のインストーラーが入手出来るので、あとは手順に従えばOKです。 https://store.docker.com/editions/community/docker-ce-desktop-mac

f:id:madogiwa0124:20180114152439p:plain

最後にターミナルからインストールを確認して下記のようになれば、OKです。

$ docker --version
Docker version 17.12.0-ce, build c97c6d6

Dockerを使ってRails開発環境を構築する

目指す環境構成

今回目指す環境はこんな感じで、ベーシックなRailsの環境を目指して行きます!

構成 内容
Ruby 2.4.0
Rails 5.1.4
DB PostgreSQL 10.1
本番環境 Heroku

Docker上にRailsが動作するコンテナとPosgreSQLが動作するコンテナの立てて、ローカルで動作確認を行いHerokuへデプロイしてみたいと思います。

イメージはこんな感じです。 f:id:madogiwa0124:20180114152357p:plain

手順

Railsプロジェクトの作成

まずは、普通にローカルでRailsプロジェクトを作成します。

rails new docker_sample_app

Docker関連ファイルの配置

その後、DockerFile及びdocker-compose.ymlをrootディレクトリ配下に配置します。

DockerFileはコンテナの定義ファイルで、docker-conpose.ymlは、DockerFileの関連を定義したファイルです。

DockerFileでWeb用のコンテナを既存のrubyのimageをベースに定義しています。DB用のコンテナはdocker-compose.ymlで公式のpostgresのイメージを使ってそのまま構築しています。

DockerFile

# ベースイメージの設定
FROM ruby:2.4.0
# 環境変数の設定
ENV APP_ROOT /docker_sample_app
# コンテナ上で関連パッケージのインストール
RUN apt-get update -qq && apt-get install -y nodejs build-essential libpq-dev postgresql-client
# コンテナ上でフォルダを作成
RUN mkdir $APP_ROOT
# 作業ディレクトの設定
WORKDIR $APP_ROOT
# Gemfileをコンテナ上にコピー
ADD Gemfile ${APP_ROOT}/Gemfile
ADD Gemfile.lock ${APP_ROOT}/Gemfile.lock
# コンテナ上でbundle install
RUN bundle install
# rootフォルダ配下をコンテナ上にコピー
ADD . $APP_ROOT

docker-compose.yml

version: '2'
services:
  # DB用のコンテナ
  db:
    image: postgres
    ports:
      - "5432"
    # データをホスト側で保持し、関連付けることで永続化
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
  # Web用のコンテナ
  web:
    # DockerFileの配置フォルダ
    build: .
    # コンテナ起動時に実行されるコマンド
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    ports:
      - "3000:3000"
    # dbとwebを関連付け
    links:
      - db
    # ローカルのルートディレクトリをコンテナ上の作業ディレクトリと関連付け
    volumes:
      - ./:/docker_sample_app
    # 環境変数
    environment:
      DATABASE_USER: postgres
      DATABASE_PASSWORD:
      DATABASE_PORT: 5432
      DATABASE_HOST: db

DB関連ファイルの修正

DBをPosgreSQLに変更

これは、過去の記事にまとめているので参照して頂ければと思います。

madogiwa0124.hatenablog.com

DB設定をDB用のコンテナに合わせて変更

DockerコンテナでDBを構築するにあたって、DBの参照の仕方等を少し工夫する必要があるためにdatabase.ymlファイルを編集します。

default: &default
  adapter: postgresql
  encoding: unicode
  timeout: 5000
  # docker-composeで指定した環境変数の読み込み
  port: <%= ENV.fetch('DATABASE_PORT') { 5432 } %>
  host: <%= ENV.fetch('DATABASE_HOST') { 'localhost' } %>
  username: <%= ENV.fetch('DATABASE_USER') { 'root' } %>
  password: <%= ENV.fetch('DATABASE_PASSWORD') { 'password' } %>
  pool: <%= ENV.fetch('RAILS_MAX_THREADS') { 5 } %>

development:
  <<: *default
  database: docker_sample_app_development

test:
  <<: *default
  database: docker_sample_app_test

production:
  <<: *default
  database: docker_sample_app_production
  username: docker_sample_app
  password: <%= ENV['appname_DATABASE_PASSWORD'] %>

Dockerコンテナの起動

では実際にDocker上に環境を構築していきます。 流れとしては、下記のような形になります。 1. Web用のコンテナとDB用のコンテナを構築 2. DBを作成 3. マイグレーションの実行 4. Dockerコンテナの起動

# Dockerイメージの取得等の初期化処理
$ docker-compose build
# DBの作成とマイグレーションの実行
$ docker-compose run web rake db:create
$ docker-compose run web rake db:migrate
# Web、DB用のコンテナの起動
$ docker-compose up

localhost:3000にブラウザから接続するとRailsのスタートページが見えました!

f:id:madogiwa0124:20180114152508p:plain

Herokuにデプロイ

最後にHerokuにデプロイしてみようと思います。 HerokuへのデプロイはDockerを使わない環境と特に変わりません。

今回は、scaffoldUserモデルを作成後、Herokuへデプロイしてみました。

$ rails generate scaffold user name:string age:integer
$ git add -A
$ git commit -m "scaffold user model"
$ git push heroku master
$ heroku run db:migrate
$ heroku open

無事にherokuにデプロイできました!
https://rails-docker-sample-app.herokuapp.com/users

f:id:madogiwa0124:20180114152524p:plain

おわりに

まだまだDockerのことは理解出来ていない部分が多いですが、なんとかネットの情報を元に環境と立ててデプロイすることが出来ましたφ(..)
Dockerだと失敗しても潰して、もう一回ということが簡単に出来るので、仮想環境の構築よりもストレスは大分少ないんじゃないかなぁと思います…!

Dockerは色々書籍も出ているので、色々と勉強してみようと思いました。 オススメの書籍等あれば、教えてくださいφ(..)

参考

tech.recruit-mp.co.jp

qiita.com

Ruby on Rails:過去日・未来日を判定する

Railsで過去日・未来日判定を行う際に下記のような実装をしていたのですが、便利なメソッドがRailsに用意されていたので、φ(..)メモメモ
Rubyでは使用出来ないので、注意してください(._.)

# 生年月日に未来日は設定不可
def birthday_cannot_be_in_the_future
  if birthday.present? && birthday > Date.today
    errors.add(:birthday, "can not specify your future date as your birth date.")
  end
end

# スケジュールに過去日は設定不可
def schedule_cannot_be_in_the_past
  if schedule.present? && schedule < Date.today
    errors.add(:schedule, "can not specify your past date as your schedule.")
  end
end

Railsには過去日の判定を行うDate.past?、未来日の判定を行うDate.future?があるので、><を使用するよりも綺麗に実装出来ます。

# 生年月日に未来日は設定不可
def birthday_cannot_be_in_the_future
  if birthday.present? && birthday.future?
    errors.add(:birthday, "can not specify your future date as your birth date.")
  end
end

# スケジュールに過去日は設定不可
def schedule_cannot_be_in_the_past
  if schedule.present? && schedule.past?
    errors.add(:schedule, "can not specify your past date as your schedule.")
  end
end

ちなみにDateTimeでも同様にfuture?past?が使えます(..)アリガタヤ

past? (DateTime) - APIdock

future? (DateTime) - APIdock

以上です。

感想:ストレングス・ファインダーで自分の才能に目覚めてみた

最近、転職活動を始めて、色々と自分のキャリアを考える機会が多いのですが、そもそも、、、

自分に向いていることはなんなのか
自分に出来るのことはなんなのか

適切に自己評価が出来なくなっている気がしたので、下記書籍を購入してみました。

この書籍にはストレングス・ファインダーというWebテストの意義と結果を解説したものになります。
ストレングスファインダーは下記の通り、自分の才能を知れるWebテストで、企業にも導入されている実績のあるもののようです。

ストレングスファインダー®とは、米国ギャラップ社の開発したオンライン「才能診断」ツールです。Webサイト上で177個の質問に答えることで、自分の才能(=強みの元)が導き出されます。
出典:ストレングスファインダー®とは | ストレングスファインダーで強みを活かす 株式会社ハート・ラボ・ジャパン

書籍にはWebテストのアクセスコードが付いているため、本を買えばWebテストの受けて、自分の才能Top5を検査することが出来ます。 ちなみにストレングス・ファインダーの公式ページでもアクセスコードコードを購入することが出来ますが、$19.99なので書籍を購入した方がお得だと思いました。。。

私の才能

受験してみたので、私の結果を書いてみましたφ(..)

1.未来志向

未来志向という資質を持つ人は、未来がどのようなものかについて考え、そこからアイデアを得ます。未来についてのビジョンを語ることで、人々を高揚させます。

確かに新しいモノ・価値について、考えたり話したりするのは好きだな、と感じました!そういうことを日々行いたいものですね(._.)

2.戦略性

戦略性という資質を持つ人は、目的に向かうための選択肢を想定することができます。いかなる想定に直面しようとも、適切なパターンと問題点を直ちに予測することができます。

目標を達成するために、どのような手段が合って、どれを選ぶべきか考えるのは確かに結構好きな気がします・・・! また、今の仕事で保守や不具合対応を行うことが多かったので、事象に関して原因や対応策を考えるといったことが鍛えられたのかも知れないですね。

3.着想

着想という資質を持つ人は、新しいアイデアを考えるのが大好きです。全く異なる現象に見えるものの間に、関連性を見出すことができます。

新しいアイデアを考えるのは、とでも好きですね!アイデア思考とか、いつかきちんと学んでみたいです。ちなみに過去に下記のようなWebサービスを作ったりもしました・・・!

キーワードミキサー

github.com

4.個別化

個別化という資質を持つ人は、一人一人が持つユニークな個性に興味をひかれます。異なるタイプの人たちの集団をまとめ、生産性の高いチームを作ることに長けています。

あまり人の好き嫌いは無くて、個人個人で価値観が違うのが当たり前で、魅力的だと感じることが多い気がします。

5.親密性

親密性という資質を持つ人は、他人との緊密な関係を楽しみます。目標達成のために友人と努力することから、大きな満足感を得ます。

広く浅くよりも、狭く深くの人間関係の方が、価値を感じる方だと思いますね!(..)

おわりに

自分の才能に目覚められたかどうかは正直わかりませんが、結果を元に自分のキャリアや自己評価を見直すのにはいいきっかけになったと思います。
これからのキャリアの中で今回私の才能として挙げられたものを大事にしていきたいと感じました。

  1. 未来志向
  2. 戦略性
  3. 着想
  4. 個別化
  5. 親密性

以上です。

Ruby on Rails:自作アプリをTwitterカードに対応させる

Railsで作ったアプリケーションをTwitterカード対応させる手順をメモしておきますφ(..)

Twitterカードとは下記のようなものです:D

twitter.com

単純にURLリンクを貼る貼るよりも、より多くの情報を伝えることが出来ますね!

手順

前提

今回は、詳細ページでは各ページに対応したTwitterカードを、その他ではサービスを紹介するTwitterカードを表示させるような対応を想定していますφ(..)

詳細ページ moook.herokuapp.com

サービス紹介 moook.herokuapp.com

実装メモ

概要

Twitterカードに対応させるには、ページのhead内にmetaタグを埋め込む必要があります。各metaタグの意味については、下記のサイトが参考になりました!

saruwakakun.com

実装手順

metaタグを各ページに埋め込む

Twitterカードに対応するのは、各ページにTwitterカード用のmetaタグを埋め込む必要があるため、今回はapplication.html.erbに埋め込むことにしました。

<!DOCTYPE html>
<html>
  <head>
    <!-- 省略 -->
    <% twitter_card = get_twitter_card_info(@page ? @page : nil) %>
    <meta name="twitter:card" content=<%=twitter_card[:card]%> />
    <meta name="twitter:site" content=<%=twitter_card[:site]%> /> 
    <meta property="og:url" content=<%=twitter_card[:url]%> />
    <meta property="og:title" content=<%=twitter_card[:title]%> />
    <meta property="og:description" content=<%=twitter_card[:description]%> />
    <meta property="og:image" content=<%=twitter_card[:image]%> />
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
  <!-- 省略 -->

metaタグに設定する情報を取得するメソッド

metaタグに埋め込む値はapplication.html.erbに直接記述しても良いのですが、今回はページ詳細とその他でmetaタグに設定する値を変更するので、application_helper.rbで設定値を取得するようにしてみました。

ページ詳細画面(pageに値が設定されていれば)であれば、pageに値が設定され、それ以外ではnilとなるようにapplication.html.erbので実装しているため、Twitterカードの出し分けが出来るようになっていますφ(..)

  def get_twitter_card_info(page)
    twitter_card = {}
    if page
      twitter_card[:url] = page.url
      twitter_card[:title] = 'Moookからオススメページのお知らせ'
      twitter_card[:description] = "タイトル:#{page.name}、タグ:#{page.tag_list.join(',')}"
      twitter_card[:image] = set_page_img(page.image_src)
    else
      twitter_card[:url] = 'https://moook.herokuapp.com/pages'
      twitter_card[:title] = 'Webページ更新管理ツール「Moook」'
      twitter_card[:description] = 'いつもの更新いつもの更新確認、Moookを使えばお気に入りのページの更新を見逃しません。'
      twitter_card[:image] = 'https://raw.githubusercontent.com/Madogiwa0124/Moook/master/app/assets/images/favicon.png'
    end
    twitter_card[:card] = 'summary'
    twitter_card[:site] = '@Madogiwa_Boy'
    twitter_card
  end 

以上ですφ(..)

Ruby on Rails:Rails5でtwitter-bootstrap-railsで導入したBootstrapをちゃんと使えるようにする

自分の作っているサービスで、ずっとbootstrapが上手く反映されてくれずハマっていたけど、解消できたのでメモφ(..)

github.com

前提

事象

発生していた事象は下記の通りです。

  • ナビバーのドロップダウンリストが開かない
  • スマホでアクセスしてもナビバーがハンバーガーメニューにならない

環境

私のサービスの環境情報を下記に記載しておきます。

gem version
rails 5.1.2
twitter-bootstrap-rails 4.0.0

手順

jQueryを導入する

Bootstrap3はjQueryに依存していますが、Rails5からjQueryが依存から除外されたので、明示的にGemfileに記述する必要があります。
下記をGemfileに追記し、bundle installを実行します。

gem 'jquery-rails'

application.jsの修正

jQueryの導入が出来たらapplication.jsに追記し、Asset管理対象に追加します。
twitter/bootstrapが記載されていない場合は、合わせて追記します。

//= require jquery
//= require twitter/bootstrap

この時点で、ナビバーのドロップダウンリストが開かないは解消するはずです!

viewportの設定

application.html.erbに下記を追記します。

<meta name="viewport" content="width=device-width, initial-scale=1">

これで、スマホでアクセスしてもナビバーがハンバーガーメニューにならないが解消されるはずです!

※viewportについては下記が参考になると思います。

qiita.com

おわりに

Rails5では、jQueryの依存がなくなってフロントエンド界隈が盛り上がっていますが、Rails4以前でBootstrapを使っているサービスは数多くあると思うので、Railsのバージョンアップの際に参考になればと思いますφ(..)
大きなバージョンアップの際には依存するライブラリへの影響も気をつける必要がありますね・・・!

参考

www.bountysource.com

Ruby on Rails:複数のForm項目の値を配列形式でコントローラーに渡す

Viewの項目の値を配列形式でparamsに設定し、Controllerで使用する方法をメモしておきますφ(..)

手順

前提

今回は、下記のように複数のレコードに設定したCheckBoxの値を配列形式で設定し、Controller側で処理するケースを想定してます。
さらに具体的にいうと、スケジュールが設定されたレコードが複数あって、それに対してそれぞれCheckBoxで承認していく仕様を実装していきます。

f:id:madogiwa0124:20171231212613p:plain

手順

まず、複数のフォーム項目を配列形式でparamsに設定するには下記の形式でView側に記載します。ポイントは、要素名を要素名[]のように設定することです。

<%= tag_name 'hoge[]' %>

今回はForm内にある複数のCheckBoxの値を配列で渡すので、Viewの実装は下記のようになります。

<%= form_tag approve_interviews_path, { method: :put } do %>
<table border='1'style="border-collapse:collapse">
  <thead>
    <tr>
      <% if params[:action] = 'select' %>
        <th>Approve</th>
      <% end %>
      <th>Title</th>
      <th>Schedule</th>
      <th>User</th>
    </tr>
  </thead>
  <tbody>
    <% @interviews.each do |interview| %>
      <tr>
        <% # 配列 approved にinterview.idを追加 %>
        <td><%= check_box_tag('approved[]', interview.id)%></td>
        <td><%= interview.title %></td>
        <td><%= format_datetime_string interview.schedule %></td>
        <td><%= interview.user.user_name %></td>
      </tr>
    <% end %>
  </tbody>
</table>
<%= submit_tag :approved %>
<% end %>

Contollerで下記のように配列形式で受け取ることが出来ます。

  def approve
    @interviews = Interview.where("id in (?)", params[:approved])
    @interviews.each do |interview|
      interview.status = Interview::statuses[:approved]
      interview.save
    end
    redirect_to interviews_path
  end

参考

check_box - リファレンス - - Railsドキュメント

Rails のフォームで配列形式のデータを扱う方法 - WebOS Goodies