upinetree's memo

Web系技術の話題や日常について。

NicorepoというRuby gemを公開しました

f:id:upinetree:20140501000122p:plain

ニコニコ動画のニコレポというのがあって、ニコ動版のツイッタータイムラインみたいなやつなんですが、これがまた情報が分類されてなくて読みづらいし、フィルタリングもできない、非常に廃人仕様なわけです。

毎日ニコレポに張り付くわけにも行かないけど、見たい動画は見逃したくない…ので、日々あふれるニコレポを効率よくまとめてチェックできるgemを作りました。

https://rubygems.org/gems/nicorepo

https://github.com/upinetree/nicorepo

といっても今まで自分で便利に使っていたやつを、みんなで使えるように手直ししてgem化しただけです…。Rubyをまだそこまでガッツリ使っていなかったときに書いたやつなので、ザクザクっとリファクタリングしてみました。

でもcliとかカオスすぎるので近々なんとかしたいし、コマンドもなんだか分かりづらい(自分は慣れたパターン)し、汎用性ないし…プルリクお待ちしております!

なお、ニコレポがAPIも提供してないのでかなり力技でぱーすしています。

使い方は大体READMEに書いてあるのですが、下手な英語なので分かりづらかったらお叱りください〜。

では、良いニコ動ライフを!

実行中Rubyプログラムのbinding.pryを全て無効にする

Pry version: 0.9.12.4 on Ruby 2.1.0.

これだけ

pry(main)> disable-pry

どんな機能かというと

pry(main)> help disable-pry
Usage: disable-pry

After this command is run any further calls to pry will immediately return `nil`
without interrupting the flow of your program. This is particularly useful when
you've debugged the problem you were having, and now wish the program to run to
the end.

As alternatives, consider using `exit!` to force the current Ruby process
to quit immediately; or using `edit-method -p` to remove the `binding.pry`
from the code.

ということらしい。

例えばループ中とかshared_examplesとかでbinding.pryしたとき、これを使えば目的の動作を確認した後にぐぬぬってならなくて済みますね。

ただ、binding.prynilを返す動作は変わらないのでそこだけ注意です。

他の方法としては、exit!を使うか、edit-method -pbinding.pryを削除してくれと書いてありますね。

ちなみに、edit-methodすると "DISABLED: Use edit instead." と怒られるので、指示に従ってedit -p method-nameとでもしておきましょう。

CoffeeScriptでインスタンスメソッドを関数バインディングする

忘れないようにメモ。

イベントをバインディングする時、関数をコールバックで渡すことがある。

$('.hoge_field').on('blur', (e) -> updateHoge(e.target))

updateHoge = (hoge_field) ->
  hogehoge

でも、インスタンスメソッドを渡すときは同様にこうしてはいけない。

index: ->
  $('.hoge_field').on('blur', (e) -> @updateHoge(e.target))

updateHoge: (hoge_field) ->
  hogehoge

なぜなら、コールバックとして渡す際、thisの示す先が変わり、updateHogeが未定義となってしまうから。

なのでこう書く。

  $('.hoge_field').on('blur', (e) => @updateHoge(e.target))

ファットアロー => を使うと、thisの示す先を変えずに扱うことができる。

JavaScript苦手意識あったけど、CoffeeScript触るようになってからわりと楽しくやってるかも。

非表示要素はCapybaraのfindで検索対象になるのか

今日はもう一個書く!

Capybara使ってると、display: noneで非表示にしてあるものはCapybaraのfind対象なのか??

という疑問がでてきたわけです。

ここは公式みてみますか。

Module: Capybara::Node::Finders

visible (Boolean) — Only find elements that are visible on the page. Setting this to false finds invisible andvisible elements.

ふむふむ。

でもどっちがデフォルトなのかよくわからん。 ちょっとソースつついてみる。

lib/capybara/query.rb

def visibleありますね。visibleオプション指定がないときは、 Capybara.ignore_hidden_elementsを見て判定しているようです。

こいつはlib/capybara.rbにありました。

[ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: true)

デフォルトはtrueなので、見えないものは探さないってことですね。 Configureで設定可能のようです。

つまり

visible: true #=> display: noneのものは検出しない(デフォルト)
visible: false #=> disiplay: noneでも検出する

ということですね。

実際確かめてみる。

  • visible: trueで検索すると、@resultにdisplay: noneの要素が入らなくて@restに入る。
  • visible: falseで検索すると、@resultに要素が入って@restが空になる。

うん、そのようだ。 スッキリ。

テキストをクリックして入力フォームを出現させる (rails+haml+coffee)

一覧画面とかで、表示されているテキストクリックしたら入力フォームが出現して、 サクッと内容変更できたらカッコ良いじゃないですか。 例えばブログ記事のタイトルとか、クリックしたら編集できるようになるとか。

というわけで毎度のメモです。

haml

#posts
  - @posts.each do |post|
    .title
      .value= post.title
      = text_field :post, :title, class: :field

scss

.title {
  .value {
    display: inline;
  }
  .field {
    display: none;
  }
}

coffee

$('.value').on('click', ->
  $(@).hide()
  $(@).next('.field').show()
                     .val($(@).text())
                     .focus()
)

$('.field').on('blur', ->
   # $.ajax
   #   hogehoge

   $(@).hide()
   $(@).prev('.value').show()

# 直感的にはEnterで確定したいので作ったる
$('.label_field').keypress (e) ->
  if e.which == 13
    e.target.blur()

ちなみに

単純なテキストの切り替えだったらこんな感じ。

haml

#toggle_me
  #showing.toggle_pair Toggle Me!!
  #hidden.toggle_pair Toggled!!

:scss
  #hidden {
    display: none;
  }

coffee

$('#toggle_me').on 'click', ->
  $(@).children('.toggle_pair').toggle()

表示する要素と表示しない要素を用意して同時に表示・非表示を切り替えることで、見かけ上変化させるのがコツですね〜。

FactoryGirlでファクトリ継承時、クラス指定を忘れて困った

困ったのでメモ。

次のようなSTIな感じのモデルがあるとき、ファクトリ側でも継承を使いたいなーと思うわけです。

モデル

class Post < ActiveRecord::Base
end

class PhotoPost < Post
  belongs_to :album
end

Factory

FactoryGirl.define do
  factory :post do
  end

  factory :photo_post, parent: :post do
    album
  end
end

photo_postをparentオプションでpostから継承した。でも、こう書いた場合albumなんて知らんと怒られる。

pry(main)> FactoryGirl.build(:photo_post)
NoMethodError: undefined method `album=' for #<Post:0x007f8e1b52ccd0>

なぜなら、photo_postは継承元(post)のインスタンスとして生成されるため。

albumの記述を削除して確認。

pry(main)> FactoryGirl.create(:photo_post).class
=> Post(id: integer, title: string, body: text, type: string, created_at: datetime, updated_at: datetime)

postにはalbumとの関連はないため、参照しようとして怒られていた。 これを回避するには、ファクトリ定義時にclassオプションを指定する。

  factory :photo_post, class: PhotoPost, parent: :post do
    album
  end

classオプションによりファクトリphoto_postがPhotoPostを生成することを教えられた。 これで、生成されるインスタンスはPhotoPostになる。

pry(main)> FactoryGirl.create(:photo_post).class
=> PhotoPost(id: integer, title: string, body: text, type: string, created_at: datetime, updated_at: datetime)

class指定忘れずにしようねというお話でした。

libv8, therubyracer のインストールが OS X Mavericks で失敗する

はまったのでメモ。

Mavericks上でlibv8, therubyracerのgem installが失敗する現象への対処法です。

なお、最新バージョンのlibv8, therubyracerではもう対応済みのようです。 bundleで特定バージョン入れなきゃいけないんだけどーみたいなときに読んでください。

libv8だけ入れる場合

オプションで、--with-system-v8つけるだけです。

gem install libv8 -- --with-system-v8

bundleでやる場合は、

bundle config build.livb8 --with-system-v8

とかしてからbundle installすれば良いです。

ちなみに、設定したconfigは~/.bundle/configに保存されます。

therubyracerを入れる場合

前提としてlibv8がインストールされるのですが、このとき--with-system-v8オプションがついてるとこけます。 もうオプション付きでlibv8入れちゃっている場合は、一度アンインストールします。

gem uninstall libv8

brew install apple-gcc42
sudo ln -s /usr/local/Cellar/apple-gcc42/4.2.1-5666.3/bin/gcc-4.2 /usr/bin/gcc
sudo ln -s /usr/local/Cellar/apple-gcc42/4.2.1-5666.3/bin/g++-4.2 /usr/bin/g++
sudo ln -s /usr/local/Cellar/apple-gcc42/4.2.1-5666.3/bin/cpp-4.2 /usr/bin/cpp

gem install therubyracer

元から入っていたgccとかはバックアップ取っておくと良いかもしれません。

参考にした Stac Overflow にはexportしてbrew tapする方法ものっています。 試していませんが、こっちでもできるっぽいー。