u16suzuの blog

日々学んだことのメモブログです。

rails console から任意のメソッドのソースコードをRubyMineで開く

設定

.pryrcに以下を追記する。RubyMineのCUIコマンドがない場合は Tools > Create Command-line Launcher... で作っておく。

Pry.config.editor = proc { |file, line| "/usr/local/bin/mine --line #{line} #{file}" }

Pry.commands.alias_command 'mine', 'edit'
Pry.commands.alias_command 'mi', 'edit'

実行例

以下のコマンドを実行すると、RubyMine で User.first.label を定義している部分のコードが開かれる。

pry(main)> mine User.first.label

こちらももちろん呼び出し可能。

pry(main) mine User.first.label=

Rails などの gem のコードも同様に開ける。

pry(main)> mine Rails.cache.read

開かれたコード。dalli_store.rb の 115行目あたり。

      def read(name, options=nil)
        options ||= {}
        name = expanded_key name

        instrument(:read, name, options) do |payload|
          entry = read_entry(name, options)
          payload[:hit] = !!entry if payload
          entry
        end
      end

自分の小さな「箱」から脱出する方法を読んだ

自分の中で一方的に師と仰いでいる元KLab CTO 仙石さんの投稿をきっかけにして、 以前購入し積読してあった本を読んだ。 とても良い本だった。

自分の小さな「箱」から脱出する方法

自分の小さな「箱」から脱出する方法

  • 作者: アービンジャーインスティチュート,金森重樹,冨永星
  • 出版社/メーカー: 大和書房
  • 発売日: 2006/10/19
  • メディア: 単行本(ソフトカバー)
  • 購入: 156人 クリック: 3,495回
  • この商品を含むブログ (418件) を見る

本書の概要

自分が本来相手のためにすべきだと思ったことをしないことを、心理学の世界では「自己欺瞞」という。 これを本書ではシンプルに「箱に入る」とか自分への裏切りと呼ぶ。

一度この自己欺瞞が始まると、そこから...

1. 他人の欠点を大げさにあげつらう
2. 自分の長所を過大に評価する
3. 自己欺瞞を正当化する。ものの価値を過大に評価する
4. 相手に非があると考える

というような流れで悪化していき、物事を見る目が曇ってしまい、しまいには他人との信頼関係が壊れてしまう。 本書では、これを防ぐには自分が箱の中に入っているかどうかを意識して、 なんとか箱の中から脱出することで、解決を目指しましょうということを述べている。 もちろん、つねに箱から出ているのが理想ではあるけれども、 そうもいかないので、たまには箱に入ることもある。 でも、箱に入っている状態を意識するというのは大事だと思う。

正直、過去現在に自分が周りで観測した人間関係のこじれはこの流れに沿っている。 もちろん自分が当事者になった時もあるし、そうじゃない時もある。 本書では、そのような過去の事柄についても、ことあるごとにその時どうすればベストだったか? を振り返って考えることを勧めている。

最後に

最後に本の最終ページに書いてあったリストを引用しておく。

知っておくべきこと

  • 自分への裏切りは、自己欺瞞へ、さらには箱へとつながっていく。
  • 箱の中にいると、業績向上に気持ちを集中することができなくなる。
  • 自分が人にどのような影響を及ぼすか、成功できるかどうかは、全てはこの外に出ているか否かにかかっている。
  • 他の人々に抵抗するのをやめた時、箱の外に出ることができる。

知ったことに即して生きること

  • 完璧であろうと思うな。より良くなろうと思え。
  • すでにそのことを知っている人以外には、箱などの言葉を使うな。自分自身の生活に、この原則を活かせ。
  • 他の人々の箱を見つけようとするのではなく、自分の箱を探せ。
  • 箱の中に入っているといって他人を責めるな。自分自身が箱の外に留まるようにしろ。
  • 自分が箱の中にいることがわかっても、あきらめるな。努力を続けろ。
  • 自分が箱の中にいた場合、箱の中にいたということを否定するな。謝った上で、さらに前へ進め。これから先、もっと他の人の役に立つよう努力しろ。
  • 他の人が間違ったことをしているという点に注目するのではなく、どのような正しいことをすればその人に手を貸せるかを、よく考えろ。
  • 他の人が手を貸してくれるかどうかを気にやむのはやめろ。自分が他の人に手を貸せているかどうかに気をつけろ。

thoughが使われる文章の訳し方について

github で gem の README を読んでいるとよくでてくる英単語の though について調べました.

なんとなく but のように逆説の意味であることは知っていたけれどもいざ実戦で出会うと、though の前の節と後の節が逆のことをいっていて, どちらが文章の真意なのかがよくわからなくなり意味がとれず苦労していました.

ネットで調べたところ though のある節の方を 従属節 と捉えて読めば良いという理解に落ち着きました. 主節がメインの言いたいことであって though 以下の従属節は補足情報であるというイメージです.

以下の例文で説明します.

Jess failed to diet, though he joining Rizap.
(ジェスはライザップに入会したにも関わらずダイエットに失敗した。)

主節

  • メインの情報を示す部分
  • 例文の Jess failed to diet の部分
  • 「ジェスはダイエットに失敗した」という事実(主題)を述べている.

従属節

  • 追加の情報の節
  • 例文の though 以降の部分
  • 「ジェスはダイエットのためにライザップに入会した」という 主題を補足する情報 を述べている.

githubからの例文

  • Unicorn の test/benchmark/README から実際に出会った文章を引っ張り出して翻訳してみます.
== Contributors

This directory is maintained independently in the "benchmark" branch
based against v0.1.0.  Only changes to this directory (test/benchmarks)
are committed to this branch although the master branch may merge this
branch occassionaly.
== コントリビュータ

このディレクトリは v0.1.0 をベースにした benchmark ブランチで独立してメンテナンスされています.
test/benchmarks ディレクトリのみへのコミットはこの benchmark ブランチにコミットされます,
しかしながら, master ブランチは時々このブランチをマージします.

although the master branch may merge this branch occassionaly. の部分が従属節なため, 主題は Only changes to this directory (test/benchmarks) are committed to this branch であると目星をつけて訳してみました.

  • 同じく Capistrano の README にも使われていました.
Capistrano is a framework for building automated deployment scripts. 
Although Capistrano itself is written in Ruby,
it can easily be used to deploy projects of any language or framework, be it Rails, Java, or PHP.
Capistrano は自動デプロイを作るためのフレームワークです。
Capistrano 自身は Rubyで書かれていますが, 
Rails, Java, PHP といったようなどんな言語のフレームワークを使ったプロジェクトにも簡単に使うことができます。

althoughとthoughの比較

  • 最後にalthoughとthoughの簡単な使い分けをまとめておきます.

although

  • 硬い表現
  • 文頭で使用する.

though

  • (although)よりは柔らかい表現
  • 後ろに持ってくることもできる
  • 強意のため even though とすることもある

RubyMineとiTerm2 でRubyのバックトレースからファイルを開く時に RubyMine で開けるようにする

1 RubyMineのコマンドラインランチャーを作成する

RubyMine のツールバー > Tools > Create Command-line Launcher...

2 iTerm2側で設定をする

iTerm2 の Preferences > Profiles >
任意のプロファイルを選択 > Advanced タブ > Semantic History >
Run Command を選択 > `/usr/local/bin/rubymine --line \2 \1` を入れる。

これで、cmd+click でクリックしたときに、 RubyMine 該当のファイルを開いてくれます。

Rubyでデザインパターン ~Stateパターン~

RubyでStateパターンを実装してみるテスト。

Stateのコンクリートクラスにメソッドの実装を生やすことで、Stateを新しく追加するときに追加しやすくしている。

クラスマクロもちょろっと使ってみたり。

でもクラスマクロはコードが短くなるのはいいけど、初見の人には読みづらいと思うんだよなぁ。

class Class
  def subclasses
    subclasses = []
    ObjectSpace.each_object(singleton_class) do |k|
      subclasses << k if k.superclass == self
    end
    subclasses
  end
end
class State
  @_time
  def self.time(time=nil) # 引数がnilの時はgetter, nilでない時はsetterになる
    @_time ||= time
  end
  def time # インスタンスメソッドも一応定義しておく
    self.class.instance_variable_get("@_time")
  end
  def hello
    raise
  end
end
class MorningState < State
  time 0..9
  
  def hello
    puts "Good morning!"
  end
end
class DayState < State
  time 10..15
  
  def hello
    puts "Hello!"
  end
end
class EveningState < State
  time 16..18

  def hello
    puts "Good evening."
  end
end
class NightState < State
  time 19..24
  
  def hello
    puts "Good night."
  end
end
class StateManager
  attr_accessor :state, :time
  def initialize(state=MorningState.new)
    @state = state
  end
  def say_hello
    @state.hello
  end
  def time=(time)
    @time = time
    State::subclasses.each do |k|
      if k.time.include?(@time)
        @state = k.new
        break
      end
    end
  end
end


mgr = StateManager.new
mgr.say_hello
(0..24).to_a.each do |i|
  mgr.time = i
  mgr.say_hello
end

ORDER BY 狙いのキーについて動作確認メモ

こちらのスライドで説明されていることの理解を深めるために動作確認してみました。

www.slideshare.net

# 実験用に bulk insert でデータを入れる

values_1 = (1..9990).to_a.map do |_|
  "(#{rand(80)}, 1)"
end.join(",  ")


values_2 = (1..10).to_a.map do |_|
  "(#{rand(80)}, 0)"
end.join(",  ")

[values_1, values_2].each do |v|
  system "mysql -u root spike -e 'INSERT INTO `users` ( `age`, `gender`) VALUES #{ v };'"
end

puts "success!"
EXPLAIN SELECT *
FROM users
WHERE gender = 1 ORDER BY age LIMIT 5 # 9990件
# WHERE gender = 0 ORDER BY age LIMIT 5 # 10件

# ORDER BY 狙いのインデックス idx_users__age が使われている
# id    select_type table   type    possible_keys   key key_len ref rows    Extra
# 1    SIMPLE  users   INDEX   idx_users__gender   idx_users__age  4  NULL    5  USING WHERE

# WHERE 狙いのインデックス idx_users__gender が使われている
# * id  select_type TABLE   TYPE    possible_keys   KEY key_len ref ROWS    Extra
# 1    SIMPLE  users   ref idx_users__gender   idx_users__gender   1  const   10 USING WHERE; USING filesort
;

Bundlerのエラー設計のメモ

  • Bundlerのエラー設計メモ
module Bundler
  class BundlerError < StandardError
    def self.status_code(code)
      define_method(:status_code) { code }

      if match = BundlerError.all_errors.find {|_k, v| v == code }
        error, _ = match
        raise ArgumentError,
          "Trying to register #{self} for status code #{code} but #{error} is already registered"
      end

      # 全てのエラーcodeリストを BundlerError に保持している. 上の部分で、同じ error code を登録しないためにそうしている。
      BundlerError.all_errors[self] = code
    end

    def self.all_errors
      @all_errors ||= {}
    end
  end

  class GemfileError < BundlerError; status_code(4); end
  class InstallError < BundlerError; status_code(5); end
  # message定義するケース
  class NoSpaceOnDeviceError < PermissionError
    def message
      "There was an error while trying to #{action} `#{@path}`. " \
      "There was insufficient space remaining on the device."
    end

    status_code(31)
  end
end
  • 例外をraiseするところ
raise BundlerError, "Unknown user path requested: #{dir}"
  • 例外ハンドリング周り
rescue GemfileNotFound
  bundle_dir = default_bundle_dir
  raise GemfileNotFound, "Could not locate Gemfile or .bundle/ directory" unless bundle_dir
  Pathname.new(File.expand_path("..", bundle_dir))
end