blog.waterlow.work

Ruby, Rails, js, etc...

webpackerのサンプルをparcelでつかったらautoloadが効かなかった

はじめに

parcelを使っていて動かすコードとしてwebpackerのreactのサンプルを使っていました。

その中で、parcelにはdefaultでautoloadの機能が備わっているのにloadされないという状態が起こりました。

ここでは原因とその対処法について書いていきます。

問題のコード

https://github.com/rails/webpacker/blob/05062bd72a6e759d34ed3f4e05639dbd0f3b4ce4/lib/install/examples/react/hello_react.jsx

import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'

const Hello = props => (
  <div>Hello {props.name}!</div>
)

Hello.defaultProps = {
  name: 'David'
}

Hello.propTypes = {
  name: PropTypes.string
}

document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <Hello name="React" />,
    document.body.appendChild(document.createElement('div')),
  )
})

原因

以下のコードが問題でした。

document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <Hello name="React" />,
    document.body.appendChild(document.createElement('div')),
  )
})

autoloadはjsが再実行されるだけなので、addEventListenerで再度イベント登録しても、domがrenderされることはありません。

対処

まず、addEventListenerを使わずReactDOM.renderを即時実行するようにします。そうするとautoloadするたびにappendChildされるので、getElementByIdにして何個もdomが作られないようにします。html側にid要素をもつdivを一個作っておきました。

const mountNode = document.getElementById("app");
ReactDOM.render(<Hello name="React" />, mountNode);

jsのscriptタグがheadに書いてあったので、bodyの一番最後に変更してdivがある状態で読み込まれるようにもしました。

背景

Railsは基本scriptタグはheadに置くので、haedにおいても大丈夫なようにaddEventListenerを使った書き方になっているのだと思います。

まとめ

まだまだjsについては無知だなと感じました。

モチベーションを上げたい2〜猪子寿之の話に学ぶ〜

f:id:waterlow2013:20181109010843j:plain

猪子寿之の話

https://ja.wikipedia.org/wiki/%E7%8C%AA%E5%AD%90%E5%AF%BF%E4%B9%8B

かなり前の話になるのだが、テレビで以下のような話をしていた。

  • 仕事で海外に1人出張することが多く、いろいろとつらい
  • 海外で自分の食べたいものを食べられないのがとくにつらい
  • なので、どこでも食べられる目玉焼きを好きになることにした
  • 本当に好きになってたまに目玉焼きを家でも作る

モチベーションアップに置き換える

  • モチベーションの上がらない仕事を好きになる
  • 何かモチベーションアップにつながるルーティンを持っておく

まとめ

結局のところ自己暗示の話なのだが、好きなものを変えるというのはなかなかぶっ飛んでいて面白いと思った。

「Presentational and Container Components」を読んだメモ

はじめに

さいきんちょこちょこReactやReduxをやっているのですが、いつも読んだドキュメントのことを忘れてしまうのでちょこちょこまとめて行こうと思います。
今回はReduxの作者でもある@dan_abramov氏の書いた、Presentational and Container Componentsです。

Presentational and Container Components

  • コンポーネントをPresentationalとContainerに分けると、再利用がやりやすくなる。

presentational コンポーネントの特徴

  • 見た目に関すること
  • presentational/container コンポーネントのどちらも含む。
  • DOM markupを含む。
  • this.props.childrenによる封じ込めを許可する(?)
  • アプリケーションの他の機能に依存がない
  • データの扱いや操作は書かない
  • propsを通じてデータやcallback関数を受け取る
  • まれに自身のstateを含む(?)
  • stateへのアクセスや、lifecycle hook、パフォーマンスの問題がない限り(?)はfunctionalにかく
  • ex) Page, Sidebar, Story, UserInfo, List.

container コンポーネントの特徴

  • どう動くかに関すること
  • presentational/container コンポーネントのどちらも含む。
  • ラップするためのdivを除いて、DOM markupを含まない
  • dataや振る舞いを他のpresentational/containerコンポーネントに提供する。
  • Flux actionを呼んでpresentationalコンポーネントにcallback関数として提供する(?)
  • ステートフルで、データソースとして機能することが多い。
  • 手で書かない。React Reduxのconnect()を使う。
  • ex) UserPage, FollowersSidebar, StoryContainer, FollowedUserList.

このアプローチの利点

  • アプリケーションとUIをよく理解できる
  • 再利用性が上がる
  • デザインだけの微調整ができる
  • layout componentsだけを外出することができる。(?)

どちらのコンポーネントもemit DOM(?)を含まないこと

presentationalコンポーネントだけでアプリケーションを作ろうとするとpropsを渡す煩雑さに気づく。(?) propsを渡して歩くよりcontainerを使う方が良い場合がある。(?)

2つのコンポーネントの差はtechnical(?)なものではなく目的である。

宗教的に2つのコンポーネントを書き分けようとしないこと。 presentationかcontainerかわからなければ、あえて決めなくても良い。

捗る!Ruby on Railsでscaffold駆動開発

最近Ruby on Railsの開発をするときに、色々参考にするためにscaffoldを叩くようにしています。 scaffoldのコードからどういうところが学べるのかを書いていきます。

scaffoldは誰もが通る道

きっとRailsを始める人は、Railsチュートリアルなり本なりで勉強することが多いはずです。scaffoldはそれらの中でRailsを始める第一歩として取り上げられることが多く、よってかなりの人がscaffoldのコードを目にしているはずです。

scaffoldから学べるポイント

コントローラで例外処理を書かない

scaffoldで作られるコントローラには、例外処理が一切ありません。しかし、ActiveRecord::RecordNotFoundになったら404が返るし、NoMethodErrorは500が返るわけです。これによりコントローラでの関心事を少なくすることができます。多くのアプリケーションでは404や500のエラーページを専用のものを用意しますが、以下のようなプラクティスで、例外処理を共通化することができます。

Railsの404,500エラーページをカスタマイズ - Qiita

update系の成功失敗は戻り値で判断

jnchitoさんが以下の記事に書いてくださっています。 qiita.com save, update, destroyはバリデーションエラーが発生する可能性があり、その場合はエラーページではなく正常なページでバリデーションで引っかかった箇所をユーザに通知するのが望ましいです。エラーをraiseして500エラーページを出してはいけません。

ルーティングはRESTに

特に必要がなれけばconfig/routes.rbにはresourcesでルーティングを定義するのが良いです。これにより全体のAPIインタフェースを合わせることができます。

namespaceありの場合の挙動

例えば以下のようなコマンドを打ったとしましょう

rails g scaffold foo/bar

すると、以下のようなモジュールが追加されます

module Foo
  def self.table_name_prefix
    'foo_'
  end
end

これにより、モジュール下のモデルにtable nameをいちいち書く必要がなくなります。 また、ルーティングもどのようにして書かなければならないかいつも覚えられないのですが、動作できるように追加してくれます。

だめなところもある

コントローラでbefore_action でついてくるset_xxxは実はもやもやしています。 scaffoldで書いてあるのくらいであればいいのですが、だんだん増えてコントローラのconcernで共通化やり出す発想になるのは避けたいところです。

www.slideshare.net

まとめ

scaffoldをを叩いたときに学べるポイントをメインに書いていきました。 もっとみんなscaffoldを使ってほしい!!!!

Rails アンチパターン - スケールへの壁(Scaling Roadblocks)

引き続きRails AntiPatternsという本を読んでいます。

https://www.amazon.co.jp/dp/B004C04QE0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前回は5 Servicesの2つめ「Sluggish Services」についてまとめました。

waterlow2013.hatenablog.com

今回は8 Scaling and Deployingの1つめ「 Scaling Roadblocks」についてまとめます。

Scaling Roadblocks

Railsアプリケーションを運用するのに、本番サーバ1台でなんとかなるのにわざわざクラスタ化などのコストの高い対応を初めからする必要はない。 ただ、コストが低いもの、もしくは後で対応するとコストが高くなるものは初めに対応しておいてもよさそう。

Solution: Build to Scale from the Start

例えばimageの配信はローカルのファイルではなくS3においておくというのはそこまでコストはかからない。 gemも存在している。carieerwaveやpaperclip、shrineなど。

まとめ

最近はRailsアプリはコンテナ化しておくのが割と普通になっている感じがしていて、時代が変わったなと思いました。 asset-syncやcdnなども、やっておいてもよさそうだなと思いました。

Rails アンチパターン - 怠けものサービス(Sluggish Services)

引き続きRails AntiPatternsという本を読んでいます。

https://www.amazon.co.jp/dp/B004C04QE0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前回は7 Testingの2つめ「Lost in Isolation」についてまとめました。

waterlow2013.hatenablog.com

今回は5 Servicesの2つめ「Sluggish Services」についてまとめます。

Sluggish Services

リモートサービス(外部APIなど)によっては、パフォーマンスやたまにエラーになる、メンテナンスになるなど、自分のアプリケーションに大きな影響を及ぼす。

Solution: Set Your Timeouts

失敗時にリトライするか、失敗しても問題ないようなサービスの場合はタイムアウトを設定することでパフォーマンスを改善することができる。
net/httpやfaradayなどの一般的なhttpクライアントはタイムアウトを設定してその時間だけ待ったら特定のエラーをあげてくれる。

Solution: Move the Task to the Background

リモートサービスのレスポンスがおそすぎる場合や、リトライを精密に行う必要がある場合には、ユーザにフィードバックを即時で返さなくていい場合に限り、処理を非同期にするという方法がある。
2017年現在だと非同期処理のgemはdelayed_job, resqueue, sidekiq, shoryukenなどがある。

まとめ

今回は特に言うことなく、外部サービスとのやりとりはタイムアウトを設けて非同期ジョブにするというのはよくある話です。
外部とのやり取り含め、バックグラウンドに持っていくことでパフォーマンス改善できるところは結構ありそう。 複雑化とのトレードオフではありますが。

Rails アンチパターン - モックにより失われた物(Lost in Isolation)

引き続きRails AntiPatternsという本を読んでいます。

https://www.amazon.co.jp/dp/B004C04QE0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前回は4 Controllersの5つめ「Controller of Many Faces」についてまとめました。

waterlow2013.hatenablog.com

今回は7 Testingの2つめ「Lost in Isolation」についてまとめます。

Lost in Isolation

モックを使ってテストを書いていると、unit testとしてテストできるようになるがつなぎの部分はテストされない。 メソッド名が変わったり引数が変わったりという変更に対して追従することができない。

Solution: Watch Your Integration Points

integration testをやろう。Rails5.1のSystem Tests、feature spec やturnip等がある。 開発の順序としては以下のようになる。

  1. まずintegration testを書き、それをパスするだけの実装をする
  2. 次にfunctional testを書き、それをパスするだけの実装をする
  3. 最後にunit testを書き、それをパスするだけの実装をする

まとめ

自分は何が何でもintegration testは書くべきという派です。 feature specはテストが遅くなるため導入の是非はあるのですが、そもそもfeature specを導入できないくらいの規模になってしまっているRailsアプリケーションは大きすぎるのかなという感じです。個人的な意見です。

あと「テスト戦略」については難しいと思っていて、functional testは書かない人も多いみたいです。 なんかテスト戦略関連のことがのっている本を読みたいなと思いました。