日常

ケ・セラ・セラ

rails new skip-いろいろ して react_on_rails を使おうとた場合に遭遇したあれこれ

これは整理して書いておこうと思ってもう2ヶ月経ってしまったものなので、この際ちらかったままに公開だけしておこうというメモです。

意気込んで、

rails new app --skip-action-cable --skip-action-mailer --skip-bundle --skip-javascript --skip-listen --skip-puma --skip-spring --skip-test --skip-turbolinks

などどして react_on_rails を使い始めようとした際に得た知見です。 react_on_rails をまっとうに使っている記事はもう色々あるので、 こういうの公開しておく意味はありそうかなと思ったのでした。

gist.github.com

RailsでRuby2.4のHash#compactを使うp-rがある

読みました。短くまとめます。

これがマージされると、Ruby 2.4 で加わる Hash#compact / Hash#compact! を Rails でも使うようになる。

Hash#compact が無い環境では、従来どおり activesupport 版を使うような変更ですね。

# activesupport/lib/active_support/core_ext/hash/compact.rb

+  unless Hash.instance_methods(false).include?(:compact)
+    # Returns a hash with non +nil+ values.
+    #
+    #   hash = { a: true, b: false, c: nil }
+    #   hash.compact        # => { a: true, b: false }
+    #   hash                # => { a: true, b: false, c: nil }
+    #   { c: nil }.compact  # => {}
+    #   { c: true }.compact # => { c: true }
+    def compact
+      select { |_, value| !value.nil? }
+    end

Ruby 2.4 の Hash#compact #compact! は C 実装です。ActiveSupport 版に比べて速くなるでしょう。

yaml_checker という Gem を作りました

github.com

https://rubygems.org/gems/yaml_checker

ファイル名かディレクトリを指定すると、.yml / .yaml 拡張子のファイルのみ YAML.load_file して回って、例外を起こしたものをまとめて標準出力する。というやつです。

$ yaml_checker path/to/directory
$ yaml_checker path/to/directory/foo.yml
$ yaml_checker path/to/directory/bar.yaml

invalid なファイルを含む時の様子です。

$ yaml_checker examples/
(/path/to/examples/dir1/dir2/invalid.yml): did not find expected key while parsing a block mapping at line 1 column 3
(/path/to/examples/dir1/invalid.yml): did not find expected key while parsing a block mapping at line 1 column 3
(/path/to/examples/invalid.yml): did not find expected key while parsing a block mapping at line 1 column 3
(/path/to/examples/dir1/dir2/invalid.yaml): did not find expected key while parsing a block mapping at line 1 column 3
(/path/to/examples/dir1/invalid.yaml): did not find expected key while parsing a block mapping at line 1 column 3
(/path/to/examples/invalid.yaml): did not find expected key while parsing a block mapping at line 1 column 3

もう少し機能的に色々考えていて書き始めたのですが、とりあえずこれだけあればいいかという気持ちになってきて公開しました。必要が生じたらまたという気持ちです。

capybara, poltergeist, phantomjs で js: true なテストをする

save_and_open_page や save_screenshot する場合には、 html の charset が設定されていないと日本語が文字化けてしまいました。 そういう場合には書きましょう。

<meta charset="UTF-8" />

まず install phantomjs (Ubuntu での例です)

$ wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
$ sudo cp -ip phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/bin/
$ phantomjs --version
2.1.1

Gemfile

group :test do
  gem "capybara"
  gem "launchy" # save_and_open_page するなら
  gem "poltergeist"
end

rails_helper.rb

require "capybara/poltergeist"
Capybara.javascript_driver = :poltergeist

sample feature spec

# sample_spec.rb
require "rails_helper"
RSpec.describe "Sample", :type => :feature do
  before do
    visit foo_path
  end

  feature "bar" do
    senario "baz", js: true do
      click_link "baz"

      # target: "_blank" な場合は別 window になる
      within_window(switch_to_window(windows.last)) do
        expect(current_path).to eq("/foo/bar/baz")
        expect(page).to have_content "some content"

        # save_page("save.html")
        # save_and_open_page
        save_screenshot "screenshot-#{DateTime.now}.png"
        # 全画面とりたい場合は full: true で
        save_screenshot("screenshot-#{DateTime.now}.png", full: true)
      end
    end
  end
end

save_and_open_page で js, css も反映されたい場合、 assets が localhost で完結している場合には別途 rails s しておいて、 rails_helper.rb などに以下の様に設定しておくというのが簡単かなあと思いました。

Capybara.asset_host = "http://localhost:3000"

trelloのカードの並び順みたいなのをどう実装しているか

trello clone 的なやつを作っているんですが、

drag & drop でカードの並び替えとかした時の並び順をどう管理しようかと考えていた。

そこで trello の動きをちょっと見てみたらこんな感じだった。

たとえばこんな風に、あるリストに 3つのカードが登録されていたとする。

  • list
    • card1
    • card2
    • card3

まずこうしてみたところ、card3 を PUT してる内容を見ると、 pos という項目に 57344 という値が見られた。うむ、position ぽい。

  • list
    • card1
    • card3
    • card2

ふたたびこうしてみる。card2 の PUT では pos: 53248

  • list
    • card1
    • card2
    • card3

また繰り返すと、pos 値は 51200, 50176 と変化した。変化量を追うと、 -4096, -2048, -1024 ... ということのようだ。

では以下のように card4 を追加してみる。pos: 116736 だった。

  • list
    • card1
    • card2
    • card3
    • card4

さらに card5 を追加すると、pos: 182272。card6 は 247808。

この値は、最後のカードの pos + 65536 のようだ。

リロードして、card7 を追加してみると、同様に 313344 だった。

216 空けておけば妥当なのかな。16回繰り返したらどうなるんだろうと思ってやってみたら、

215040, 198656, 190464, 186368, 184320, 183296, 182784, 182528, 182400, 182336, 182304, 182288, 182280, 182276, 182274, 182273, 182272.5, 182272.25

なるほど、小数になるわけだ。

というわけでこういう実装をすることに決めた。