Ruby

こんにちは。

Rubyで事前に準備したテンプレートのプレースホルダーに沿って文字列を展開することもあるかと思います。
そのようなときにRubyの Kernel.%メソッドを使用するといい感じに展開出来ます。
C言語のsprintfのように展開できて便利です。

例えば以下のようにするとプレースホルダーを入れたところに文字列が展開されます。

s = '%s World!'
s % 'Hello'
# => "Hello World!"

複数のプレースホルダーを入力した場合は後ろに配列を置くことで順番にプレースホルダーに入り展開されます。

s = '%s and %s are %f yen'
s % ['apple', 'grape', 500]
# => "apple and grape are 500.000000 yen"

値にハッシュを渡すことでプレースホルダーに名前をつけておくことが出来るようになります。
その場合はプレースホルダーを%<>で囲うか%{}で囲えます。
%<> の場合は後ろにフォーマットを指定します。

s = 'Your name is %&lt;first_name&gt;s %&lt;last_name&gt;s, %&lt;year&gt;d years-old'
s % { first_name: 'Taro', last_name: 'Tanaka', year: 20 }
# =&gt; &quot;Your name is Taro Tanaka, 20 years-old&quot;

%{}の場合はフォーマットを指定する必要はありません。そのかわりRubyのフォーマットがそのまま出力値に影響を与えます。

s = 'Your name is %{first_name} %{last_name}, %{year} years-old'
s % { first_name: 'Taro', last_name: 'Tanaka', year: 20 }
# => "Your name is Taro Tanaka, 20 years-old"

結構便利なメソッドなので覚えておいて損はないなと思いました!
フォーマットなどはsprintfのメソッドに沿うので必要であればドキュメントを見てください。

Read more

ここ最近Railsを触っていて一番の衝撃といってもいいかもしれない。 知識のアップデートを怠ってはいけない。悲しい。

ブログ記事や色々なところで add_column にオプションとして index: true を貼っているものを見るのですが、あれ実はindexが効いていないそうなのです(衝撃)

add_column ignores index: true

こちらのプルリクで無効なオプションが渡されたらWARNINGエラーが出るように修正されたものがmasterブランチにmergeされているので次バージョンにのるのか近いうちにリリースされそうですね。

Continue reading Rails migrationでadd_columnのオプションにindex: trueをしても効かないから気をつけよう

Read more

こんにちは! 毎週Ruby,Railsもくもく会というものを開催していて毎週のようにRubyやRailsの初心者の方とお会いするのですが、意外と知らない方も多いのでこちらで紹介させてください。

Pryって何?

PryはRubyに標準でついているIRB(Interactive Ruby)をより便利なものにしたものです。対話的にプログラミングが出来るREPLを実現するものになります。
具体的にはプログラムが動いている途中で希望の場所で止められるようになります。例えば以下のRubyプログラムがを実行した場合、
binding.pry の部分でプログラムを止めて変数の中身などを確認出来るようになります。

class Sample
  def hello_pry
    hello = "Hello"
    binding.pry
    hello
  end
end

p Sample.new.hello_pry

Githubのページはこちら↓
https://github.com/pry/pry

Pryを使うための準備

PryはGemの形式で配布されているため、gemをインストールする必要があります。

Rubyで使用したい場合

まずはGemをインストールしましょう。

$ gem install pry

インストール終了後、Pryを使いたいコード内に require 'pry' を書く必要があります。必要に応じて記述しましょう。

Railsで使用したい場合

Railsで使いたい場合は Gemfile に以下の行を追加しましょう。

group :development, :test do
  gem 'pry'
end

追加したあとは bundle install を忘れずに実行しましょう。
あとはRails起動時に自動でPryを読み込んでくれます。

実際にPryを使ってみよう

Pryの使い方はとても簡単で、止めたいコードの部分で binding.pry と書いてアクセスするとターミナル上で止まってデバッグすることが出来ます。

例えばRubyで以下のファイルをターミナルで実行するとターミナル上で止まります。

require 'pry'

class Sample
  def hello_pry
    hello = "Hello"
    binding.pry
    hello
  end
end

p Sample.new.hello_pry
binding.pry 実行時

上記のように止まるので変数の中身を確認することが出来ます。

終了させたい場合は exit を実行します。

[2] pry(#&lt;Sample&gt;)&amp;gt; exit

覚えておくと便利な使い方

メソッド一覧を表示する「ls」

特定のオブジェクトがどのメソッドを実行することができるのか一覧で確認したいときがあります。(特にRailsを使用時)
このようなときに「ls」コマンドを使用出来ます。例えば上記の hello 変数がどのようなメソッドを持っているか確認したい場合は

[2] pry(#&lt;Sample&gt;)&gt; ls hello
Comparable#methods: &lt;  &lt;=  &gt;  &gt;=  between?  clamp
Comparable#methods: &lt;  &lt;=  &gt;  &gt;=  between?  clamp
JSON::Ext::Generator::GeneratorMethods::String#methods: to_json  to_json_raw  to_json_raw_object
String#methods:
  %            chars           each_codepoint         length        scan         to_c
  *            chomp           each_grapheme_cluster  lines         scrub        to_f
  +            chomp!          each_line              ljust         scrub!       to_i
  +@           chop            empty?                 lstrip        setbyte      to_r
  -@           chop!           encode                 lstrip!       shellescape  to_s
  &lt;&lt;           chr             encode!                match         shellsplit   to_str
  &lt;=&gt;          clear           encoding               match?        size         to_sym
  ==           codepoints      end_with?              next          slice        tr
  ===          concat          eql?                   next!         slice!       tr!
  =~           count           force_encoding         oct           split        tr_s
  []           crypt           freeze                 ord           squeeze      tr_s!
  []=          delete          getbyte                partition     squeeze!     undump
  ascii_only?  delete!         grapheme_clusters      prepend       start_with?  unicode_normalize
  b            delete_prefix   gsub                   pretty_print  strip        unicode_normalize!
  bytes        delete_prefix!  gsub!                  replace       strip!       unicode_normalized?
  bytesize     delete_suffix   hash                   reverse       sub          unpack
  byteslice    delete_suffix!  hex                    reverse!      sub!         unpack1
  capitalize   downcase        include?               rindex        succ         upcase
  capitalize!  downcase!       index                  rjust         succ!        upcase!
  casecmp      dump            insert                 rpartition    sum          upto
  casecmp?     each_byte       inspect                rstrip        swapcase     valid_encoding?
...(省略)

上記を見てみるとどのクラスに属しているメソッドなのかがわかります。

メソッドを検索する「find-method」

「ls」だと一覧が出てくるのですが特定の名前のメソッドだけ検索することが出来る「find-method」も使うことが出来ます。

[3] pry(#&lt;Sample&gt;)&gt; find-method instance hello
BasicObject
BasicObject#instance_eval
BasicObject#instance_exec
Kernel
Kernel#instance_variable_set
Kernel#instance_variable_defined?
Kernel#remove_instance_variable
Kernel#instance_of?
Kernel#instance_variable_get
Kernel#instance_variables
Module
Module#instance_methods
Module#public_instance_methods
Module#protected_instance_methods
Module#private_instance_methods
Module#instance_method
Module#public_instance_method
PP::ObjectMixin
PP::ObjectMixin#pretty_print_instance_variables

Rails等で使用する場合はたくさんのクラスを継承していることが多いので使いたいメソッドの目星がついているのであればこちらのほうがよいかと思います。

トラブルシューティング

Railsサーバーが立ち上がらなくなってしまった

たまにpryを正常に終わらせることが出来ず、Railsサーバーを立ち上げようとしても立ち上がらない場合があります。その場合はプロセスが残っている可能性があるのでプロセスを削除しましょう。

現在動いてるサーバーを確認するには以下のコマンドを実行すればよいです。

$ ps aux | grep ruby
Read more

こんばんわ! このブログは大都会岡山 Advent Calendar 2016の17日目の記事です。昨日の記事はpuhitakuさんの住んでてわかる岡山県、離れてわかる岡山県。 – Zopfcodeでした。岡山のいいところがうまくまとまっていて、またコミュニティもまとまっていたのでまたじっくり読もうかと思います。 Continue reading RailsGirlsOkayama 2ndを2月25日26日に開催する予定です!

Read more

5230673897_1a356a89b0

みなさんこんにちは! 今日はRails4.2+capistrano3でデプロイしようとしたら Application has been already initialized. (RuntimeError) が出て泣きそうになりながら数時間費やしたあげく一瞬で解決したのでご報告がてらミニブログを書いてみようと思います!

Continue reading Rails4.2 + nginx + capistrano3でデプロイしようとしたら Application has been already initialized. (RuntimeError)

Read more

みなさんこんにちは! Railsで僕がよく使うimpressionistというRailsのGemがあるのですが、それを用いてランキング機能を作りたい!と思ったので共有します。 一参考になればいいなぁと思います。

ランキングのコード

ひとまずコードです。

# return [ #
, #
, ....] def daily_article_ranking ids = Impression.where("created_at >= ?", Time.now.yesterday).where("created_at ids).order("field(id, #{ids.join(',')})") end

設定としてはArticle modelが存在していて、そのPVを取得している、という状況を考えています。 また、現在から考えて1日の間のrankingなのでもし◯日のランキングを作る、とかそういう場合は適宜変えていただければ、と。 これを適切なhelperに入れてもらえれば便利かと思います。

以下解説です。 まずはimpressionテーブルから必要なデータを抜き出し、グループ化してカウントし、Article idを10件ほど取得します。 そのときに参考にさせていただいた記事は以下になります。 Rails で group by して count を取りたい時のイディオム

そしてそのidsを元にidsの配列に入っているid順にArticle modelからデータを引っ張ってきます。 そのときに参考にさせていただいたのは以下の記事(英語) Finding an array of ids while keeping the order with Rails 今回例としてあげたコードはMySQLをデータベースとして考えているのですが、こちらの記事内でMySQL以外のデータベースの場合、という風にコードが示してあるのでそれを参考に書き換えていただければ動くのではないかと思います。

こんな感じでランキングをイメージしたデータを返すことが出来るようになりました! これをもとにviewを調整していただければランキングの完成です!!

最後に

Impressionist Gem便利ですね。

Read more

467702445_b8676f60fb_n

みなさんこんにちは! 今回はRails4でTwitterのタイムライン上で実装されている◯秒前とか◯分前とか表示されるやつを実装してみたいと思います!

Rails4ではDateHelperに実装されているtime_ago_in_wordsというメソッドを使えばTwitterにある◯秒前というのを実装することが出来ます!簡単!!

ただしこのメソッドを使って日本語で表示しようと思った場合はi18n対応してあげないといけません。

具体的にはまずconfig/application.rb内にある以下のコードをjaに設定しましょう

config.i18n.default_locale = :ja

そしてこちらのファイルをコピペしてconfig/locale/ja.ymlとして保存しましょう。

ja.ymlの内容は以下の通りです

ja:
  date:
    abbr_day_names:
    - 日
    - 月
    - 火
    - 水
    - 木
    - 金
    - 土
    abbr_month_names:
    - 
    - 1月
    - 2月
    - 3月
    - 4月
    - 5月
    - 6月
    - 7月
    - 8月
    - 9月
    - 10月
    - 11月
    - 12月
    day_names:
    - 日曜日
    - 月曜日
    - 火曜日
    - 水曜日
    - 木曜日
    - 金曜日
    - 土曜日
    formats:
      default: "%Y/%m/%d"
      long: "%Y年%m月%d日(%a)"
      short: "%m/%d"
    month_names:
    - 
    - 1月
    - 2月
    - 3月
    - 4月
    - 5月
    - 6月
    - 7月
    - 8月
    - 9月
    - 10月
    - 11月
    - 12月
    order:
    - :year
    - :month
    - :day
  datetime:
    distance_in_words:
      about_x_hours:
        one: 約1時間
        other: 約%{count}時間
      about_x_months:
        one: 約1ヶ月
        other: 約%{count}ヶ月
      about_x_years:
        one: 約1年
        other: 約%{count}年
      almost_x_years:
        one: 1年弱
        other: "%{count}年弱"
      half_a_minute: 30秒前後
      less_than_x_minutes:
        one: 1分以内
        other: "%{count}分未満"
      less_than_x_seconds:
        one: 1秒以内
        other: "%{count}秒未満"
      over_x_years:
        one: 1年以上
        other: "%{count}年以上"
      x_days:
        one: 1日
        other: "%{count}日"
      x_minutes:
        one: 1分
        other: "%{count}分"
      x_months:
        one: 1ヶ月
        other: "%{count}ヶ月"
      x_seconds:
        one: 1秒
        other: "%{count}秒"
    prompts:
      day: 日
      hour: 時
      minute: 分
      month: 月
      second: 秒
      year: 年
  errors:
    format: "%{attribute}%{message}"
    messages:
      accepted: を受諾してください
      blank: を入力してください
      present: は入力しないでください
      confirmation: と%{attribute}の入力が一致しません
      empty: を入力してください
      equal_to: は%{count}にしてください
      even: は偶数にしてください
      exclusion: は予約されています
      greater_than: は%{count}より大きい値にしてください
      greater_than_or_equal_to: は%{count}以上の値にしてください
      inclusion: は一覧にありません
      invalid: は不正な値です
      less_than: は%{count}より小さい値にしてください
      less_than_or_equal_to: は%{count}以下の値にしてください
      not_a_number: は数値で入力してください
      not_an_integer: は整数で入力してください
      odd: は奇数にしてください
      record_invalid: バリデーションに失敗しました %{errors}
      restrict_dependent_destroy: "%{record}が存在しているので削除できません"
      taken: はすでに存在します
      too_long: は%{count}文字以内で入力してください
      too_short: は%{count}文字以上で入力してください
      wrong_length: は%{count}文字で入力してください
      other_than: は%{count}以外の値にしてください
    template:
      body: 次の項目を確認してください
      header:
        one: "%{model}にエラーが発生しました"
        other: "%{model}に%{count}個のエラーが発生しました"
  helpers:
    select:
      prompt: 選択してください
    submit:
      create: 登録する
      submit: 保存する
      update: 更新する
  number:
    currency:
      format:
        delimiter: ","
        format: "%n%u"
        precision: 0
        separator: "."
        significant: false
        strip_insignificant_zeros: false
        unit: 円
    format:
      delimiter: ","
      precision: 3
      separator: "."
      significant: false
      strip_insignificant_zeros: false
    human:
      decimal_units:
        format: "%n %u"
        units:
          billion: 十億
          million: 百万
          quadrillion: 千兆
          thousand: 千
          trillion: 兆
          unit: ''
      format:
        delimiter: ''
        precision: 3
        significant: true
        strip_insignificant_zeros: true
      storage_units:
        format: "%n%u"
        units:
          byte: バイト
          gb: ギガバイト
          kb: キロバイト
          mb: メガバイト
          tb: テラバイト
    percentage:
      format:
        delimiter: ''
        format: "%n%"
    precision:
      format:
        delimiter: ''
  support:
    array:
      last_word_connector: と
      two_words_connector: と
      words_connector: と
  time:
    am: 午前
    formats:
      default: "%Y/%m/%d %H:%M:%S"
      long: "%Y年%m月%d日(%a) %H時%M分%S秒 %z"
      short: "%y/%m/%d %H:%M"
    pm: 午後

これで日本語化することが出来ました! 簡単に実装出来てRailsは楽しいですね!

Read more