react-railsとreact_on_railsについてのメモ
個人用の調べたことや思ったことメモ。
RailsでReactを利用するのに使われる2大Gem。 どちらもSSRに対応している。
webpackerでreactやるんではダメなん?
webpacker:install:reactのこと。 やれなくはないと思う。
しかし、今回はSPAではなく一部分に導入(ボタン等)したかったので、react_componentのようなヘルパーメソッドがほしかった(部分適用が楽)
下記のようにやる必要があるので、部分適用で箇所が多くなるとツライと思う。。
document.addEventListener("DOMContentLoaded", e => { ReactDOM.render(<Hello name="React" />, document.getElementById("ターゲットのid")) })
react-rails
https://github.com/reactjs/react-rails
- react登場の初期の頃からある認識
- execjs依存
- 単体利用だとコンポーネントをグローバルに紐付ける
- webpackerをサポートしたので、webpackerを利用していればグローバルではなくなる
- CSRFトークンをpropで渡す必要がある
- デフォルトはsprockets利用
- レールに乗ったままいける
- 確か内部でreact.jsを持っている(バージョンがちょっと古い)
- reactのaddonsの利用をサポートしているから?
- すぐにnpm使いたくなる
- 今はwebpackerと組み合わせる方法がある
- 他はbrowserify-rails使う方法かRailsAssets.orgかな?
react_on_rails
https://github.com/shakacode/react_on_rails
- execjs依存
- Railsと疎結合でReactを利用できる
- Rails側で使いやすいようにヘルパーやnpmのライブラリを提供している
- CSRFはnpmでライブラリが用意されている
- ReactOnRailsで取得可能
- 非SPAだと重厚すぎないか?
csrfToken = ReactOnRails.authenticityToken(); // compose Rails specific request header as following { X-CSRF-Token: csrfToken, X-Requested-With: XMLHttpRequest } header = ReactOnRails.authenticityHeaders(otherHeader);
- 利用例はr7kamuraさんのamakanが秀逸
http://r7kamura.hatenablog.com/entry/2016/10/10/173610
その他
- Hypernova
ExecJSとは
Rubyからjavascriptを実行できるようにするためのもの。
各javascriptランタイムを抽象化して同じインターフェースで利用できるようにする。
ランタイム
- therubyracer
- Gemfileでデフォルトで入っていたやつ
- メモリ使用量が多いのが難点
- インストールも苦労するのだが
- 最近はmini_racer推奨
- Node.js
- いわずとしれたサーバサイドでも使えるjavascript
- mini_racer
- therubyracerよりも高速、安定、省メモリ
- therubyracerが抱えていた古いV8エンジンの問題も解決
Railsのwebpackerでbin/webpack-dev-serverをした時にinvalid host headerになってしまう
Railsのwebpackerでbin/webpack-dev-serverをしてブラウザからアクセスするとinvalid host header
とJSのエラーになってしまった。
(Virtualboxに開発環境を作ってホストOSのブラウザからアクセスしている)
とりあえず、下記の設定を入れてエラーを回避しているが、どうやるのが正しいのだろう。
[config/webpack/development.js] module.exports = merge(sharedConfig, { ・・・ devServer: { disableHostCheck: true, ・・・ }
HerokuのRailsでnpm installをできるようにする
1. 下記の手順に従ってrubyとnodejsのビルドパックを追加する
$ heroku buildpacks:add --index 1 heroku/nodejs Buildpack added. Next release on アプリ名 will use: 1. heroku/nodejs 2. heroku/ruby Run git push heroku master to create a new release using these buildpacks.
2. assets:precompileの前にnpm installを行うRakeタスクを作成する
[lib/tasks/before_precompile.rake] task :npm_install do sh "npm install" end Rake::Task["assets:precompile"].enhance(%i(npm_install))
手順2. は要らなさそう。Herokuがyarnをサポートしているようなのでyarn.lockファイルがあるとyarn installが自動で走るみたい。
herokuのDBをローカルのDB(Docker)にリストアする
1. herokuのDBのバックアップを取得する
下記のコマンドを実行。
heroku pg:backups capture --app アプリ名
2. herokuのDBのコンソール画面でバックアップしたファイルをダウンロード
コマンドからでもできるみたいだけど、今回は画面から。
herokuのダッシュボードから行くか、https://data.heroku.com/へアクセスした対象のDBへ行ってダウンロードボタンを押す。
3. Dockerのpostgresqlへインポート
下記のコマンドを実行。
cat ダウンロードしたバックアップファイル | docker exec -i [container_id or name] pg_restore --verbose --clean --no-acl --no-owner -U ユーザ名 -d DB名
以上。
administrateでacts-as-taggable-onと連携できるようにする
最近、管理画面をadministrateで作ってみたが、 acts-as-taggable-onが設定されたモデルをうまく表示する方法が分からなかった。。
試行錯誤の結果、一応できるようになったのでメモとして残す。
やったこと
- app/dashboards/xxx_dashboard.rbにtagsをField::HasManyで定義
- acts_as_taggable_onのtagとtaggingのdashboardを生成
- 生成したdashboard/controllerを移動・修正
- config/routes.rbの設定
app/dashboards/xxx_dashboard.rbにtagsをField::HasManyで定義
acts_as_taggableを定義しているモデルのxxx_dashboard.rbにtagsを定義する。
(例えば、bookモデルにacts_as_taggableを定義している場合はbook_dashboard.rb)
ATTRIBUTE_TYPES = { # ... tags: Field::HasMany.with_options(class_name: "::ActsAsTaggableOn::Tag"), } COLLECTION_ATTRIBUTES = { # ... :tags, } SHOW_PAGE_ATTRIBUTES = { # ... :tags, } FORM_ATTRIBUTES = { # ... :tags, }
administrateのField::HasManyができると編集画面などで便利なので、Field::HasManyでできるようにするのが目標だった。
acts_as_taggable_onのtagとtaggingのdashboardを生成
administrateのgenarateコマンドを実行する。
$ bundle exec rails generate administrate:dashboard ActsAsTaggableOn::Tag $ bundle exec rails generate administrate:dashboard ActsAsTaggableOn::Tagging
生成したdashboardを移動・修正
$ mkdir app/dashboards/acts_as_taggable_on $ mkdir app/controllers/admin/acts_as_taggable_on $ mv app/dashboards/tag_dashboard.rb app/dashboards/acts_as_taggable_on/ $ mv app/controllers/admin/tags_controller.rb app/controllers/admin/acts_as_taggable_on/ $ mv app/dashboards/tagging_dashboard.rb app/dashboards/acts_as_taggable_on/ $ mv app/controllers/admin/taggings_controller.rb app/controllers/admin/acts_as_taggable_on/
生成したままのclass ActsAsTaggableOn::TagDashboard
などのままでもいいが、私は下記のようにmoduleでネームスペースを切るようにした。
module ActsAsTaggableOn class TagDashboard < Administrate::BaseDashboard #... # Overwrite this method to customize how tags are displayed # across all pages of the admin dashboard. # def display_resource(tag) ←コメントアウトされているのを解除。ここが新規/編集時のtagsに表示される項目名になる tag.name end end end
module ActsAsTaggableOn class TaggingDashboard < Administrate::BaseDashboard #... end end
module Admin module ActsAsTaggableOn class TagsController < Admin::ApplicationController # ... end end end
module Admin module ActsAsTaggableOn class TaggingsController < Admin::ApplicationController # ... end end end
config/routes.rbの設定
各画面でacts-as-taggable-on関連のパスも生成しようとするのでroutes.rbの設定をしておく。
namespace :admin do #... namespace :acts_as_taggable_on do resources :tags resources :taggings end end
これで、acts-as-taggable-onを利用しているモデルのdashboardでもCRUDがhas_manyと同様でできるようになる。
ただ、tagやtaggingは表示のみで新規/編集/削除が画面からできないのでできるようにしたいところ(まだ、直近で必要無いので今は保留)
ネームスペースで区切られたモデルはまだサポートされてなさそう。 下記のpull requestが取り込まれると解決するか?
2017/06/27 追記
最新のmasterブランチだと上記のpull requestも取り込まれていて、HasOneもサポートされています!
一応、Qiitaの方にも投稿しておいた。 qiita.com