ウェブエンジニア珍道中

日々の技術的に関する経験を書いていきます。脱線もしますが助けになれば幸いです。

Docker for MacでRubyの検証用環境をサクッと作る

はじめに

Rubyの勉強を家でしている時に「これ実際に動かさないとわからんな」ということが度々あります。

Macだと homebrewrbenvを使って環境構築をする場合が多いですが、今回はMacに直接インストールしたくないと思いDocker for Macで作りました。 敷居は高そうでしたがやってみると大分楽でローカルの環境も汚れなかったのでまとめます。

Docker for Macのインストー

Docker For Mac | Docker

ここからダウンロードして、インストールします。

Ruby環境が入ったimageファイルを落とす

インストールしたらターミナルを開いて。

docker pull ruby:latest

と打つと最新のRubyが入ったイメージファイルが落とせます。

latestの箇所をバージョンに変えると任意のバージョンで取ってこれます。

例:

docker pull ruby:2.3.4

落として来ることができるバージョン一覧はこちら。 Tag Nameを入力するとOKです。

https://hub.docker.com/r/library/ruby/tags/

動かす

docker run -it ruby:latest /bin/bash

でOKです。別バージョンの場合は latestの箇所を変えて下さい。

これでRuby環境の入ったLinuxに入ることができました。あとは

irb

これで簡単なrubyの検証ならできますね。

詰まらなければDockerのインストール込みで10分でできました。なんというお手軽さ。

おまけ

https://hub.docker.com/

Docker Hubの検索で出てくるものなら同じ要領で環境が作れるので、 perlでも pythonでも nginxでもちょっとした勉強用の環境ならすぐできますね。便利便利。

RubyでURLをaタグに書き換える処理を書いた

DBから取ってきた文字列を表示する際に、URLが混ざっていた場合aタグに置き換えて表示する必要があったためその処理を書きました。

コードはこんな感じです。

require 'uri'

def convert_url_into_a_tag(text)
  text.gsub(URI.regexp(['http', 'https'])) do |text|
    "<a href='#{text}'>#{text}</a>"
  end
end


# 検証用の文字列作成
text = <<EOS
私のブログのURLは
http://www.te-nu.com/です!
もう一度いいます
http://www.te-nu.com/です!
EOS

# 実行した結果を表示
puts convert_url_into_a_tag(text)

実行結果

私のブログのURLは
<a href='http://www.te-nu.com/'>http://www.te-nu.com/</a>です!
もう一度いいます
<a href='http://www.te-nu.com/'>http://www.te-nu.com/</a>です!

ざっくり解説

String#gsubURI.regexpを組み合わせました。 URI.regexpでURLを抜き出すための正規表現を取得することができるので、あとは gsubメソッドで置換を行うことで上手くaタグに変換することができました。

Railsの場合は app/helpers/application_helper.rbあたりに定義して必要な場合に使ったりするといいんじゃないかなーと思います。

今更ながらirbからpryにして色を付けた話

経緯

僕はRailsを使って開発をしているのですが、「なんで rails consoleでは綺麗に色分けされて表示されるのに、 irbではずっと白黒なんだろう」と思ってました。

よくよく見るとうちのプロジェクトで rails console時に動いているのって pry-railsってgemで、 irbではなくて pryなんですね、ありがとうございました。

導入

とりあえずpryを導入します。

gem install pry pry-doc

これでOKですね。 pryコマンドで実行しましょう。

f:id:te-nu:20170317205104p:plain

ちゃんと色分けされてます!綺麗!

pry特有の便利な機能もあるらしいので、また機会があればまとめます。

Rubyのセッターメソッドとレシーバとselfの話

Rubyでクラスを作って色々処理を書いていると、セッターメソッド周りで意図しない挙動をしたりRubocop(静的コード解析ツール)に「冗長なselfけんじゃねーよ」と怒られたりしたのでまとめます。

問題

問題のコードはこちらです、ギターをクラス化してみました。僕の趣味です。

class Guitar
  attr_accessor :color

  def initialize
    color = ''
  end

  def say_color
    "このギターは #{color} やで!"
  end
end

では色を表示してみましょう。

guitar = Guitar.new
puts guitar.color
puts guitar.say_color

実行結果

このギターは  やで!

うまく表示されません、つらい。

原因

原因はcolor = 'red'colorがローカル変数扱いされているからです。
Guitar#color=が呼び出されているのではなく、新しく変数を作っています。で、使わずにソッコー捨ててます。
で、インスタンス変数の@colornilのままです。

解決策

selfを付ければこのインスタンスのメソッドであることを明示できます。当てはめてみるとこんなコードになりますね。

class Guitar
  attr_accessor :color

  def initialize
    self.color = ''
  end

  def say_color
    "このギターは #{self.color} やで!"
  end
end

では再度色を表示してみましょう。

guitar = Guitar.new
puts guitar.color
puts guitar.say_color

実行結果

赤
このギターは 赤 やで!

ちゃんと表示されましたね。うまくインスタンス変数に値が入っています。

冗長だと怒られる問題

ではRubocopに通してみたいと思います。

self.rb:9:15: C: Redundant self detected.
    "このギターは #{self.color} やで!"

selfいらねーよ!」(意訳)と怒られてしまいました。ここはなくても大丈夫みたいですね。どこにいるのかいらないのかわからなくなってきました。

selfがいるところいらないところ

Rubyは変数の代入とセッターメソッドの違いをselfを使うことで区別するようです。
要はセッターメソッドの時にのみselfを付ければ良いわけですね。

def initialize
  #ここはRubyにとってはローカル変数かインスタンス変数かわからないのでローカル変数として扱う
  color = "" 
end

というわけでうまく動いて無駄なselfもないコードがこちらになります。

class Guitar
  attr_accessor :color

  def initialize
    self.color = ''
  end

  def say_color
    "このギターは #{color} やで!"
  end
end

いい感じですね。しっかり使い分けることができました。
クラスを定義する上で扱う変数には気を配らないと訳がわからなくなるので、こういったところから気をつけようと思います。

Effective Ruby

Effective Ruby

Rubyでプライベートクラスメソッドを定義する方法

Rubyでクラスの外から呼べないプライベートなクラスメソッドを書く時にちょっとクセがあったのでご紹介します。

方法

こんな感じに書くと宣言できます。パブリックメソッドの hogeから プライベートメソッドの fugaを呼び出してます。

class Hoge
  def self.hoge
    fuga
  end

  def self.fuga
    puts "fuga method is called."
  end

  private_class_method :fuga
end

実行結果

実行結果はこんな感じ

Hoge.hoge
=> fuga method is called.

Hoge.fuga
=> NoMethodError: private method `fuga' called for Hoge:Class

外側からの使用を防げていますね。

解説

private_class_methodというメソッドがあるので、これでクラスメソッドをプライベート化します。「 privateでいいじゃないか」と思われる方もいるかもしれませんが、 privateメソッドはインスタンスメソッドに対してのみ効果があるのでこの後ろにクラスメソッドを定義しても効果はありません。

class Hoge
  private

  def self.hoge
    puts "hoge method is called."
  end
end
Hoge.hoge # 呼べる
=> hoge method is called.

注意点

private_class_methodの位置には注意して下さい。メソッド定義の前に入れるとエラーとなってしまいます。

class Hoge
  private_class_method :hoge

  def self.hoge
    puts "hoge method is called"
  end
end
NameError: undefined method `hoge' for class `Class'  # 怒られる

複数選択もできるので、クラス定義の最後にまとめていれるといいと思います。

class Hoge

  # ...メソッドをいくつか定義

  private_class_method :hoge, :fuga, :foo
end

少しクセがあるように感じますが、方法自体は簡単なのでカプセル化の助けになれば幸いです。 では今回はこのへんで。