ハトネコエ Web がくしゅうちょう

プログラミングやサーバー・Web制作、チームマネジメントなど得た技術のまとめ

Rails の Mountable Engine 側の _path や _url をメインアプリから呼び出す

1. 前提

まず config/routes.rb

# config/routes.rb
Rails.application.routes.draw do
  mount Admin::Engine, at: "/admin"
end

は書かれていることと思う。

今回はその Admin::Engine の配下にある /admin/users を呼び出したいとする。
つまり、 admin/config/routes.rb には以下が定義済みとする。

# admin/config/routes.rb
Admin::Engine.routes.draw do
  resources :users
end

2. controller から呼び出すぶんにはカンタン

/adminadmin_path で呼び出せるし、
/admin/usersadmin.users_path で呼び出せる。

_url 側は後述する設定をおこなわないとまだダメかもしれない。

3. as 設定を入れておく

この設定は必要ではないのだけれど、
Admin app からメインアプリを呼び出すときの routing が
main_app.mypage_path のようなものなので、そこと対称性を持つためと、
あとで文字列でのファイル検索がしやすいように、 admin_app と名付ける。

# config/routes.rb
Rails.application.routes.draw do
  mount Admin::Engine, at: "/admin", as: :admin_app
end

この変更により、

  • admin_pathadmin_app_path
  • admin_urladmin_app_url
  • admin.users_pathadmin_app.users_path

が正しい path になるので、 as 設定を入れる場合は、現在の記載を変更するようお忘れなく。

4. admin_app.xxx_url を使えるようにする

admin_app.users_path は使えるが、
admin_app.users_url を使おうとすると以下のようにエラーが出るはず。

ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
from /bundle/ruby/2.7.0/gems/actionpack-6.0.3.4/lib/action_dispatch/http/url.rb:63:in `full_url_for'

というわけで、警告通り、

admin_app.users_url(host: "localhost:3000") のようにオプション付きで呼び出すか、
default_url_options の設定をする必要がある。

今回は、メインアプリ側の config/environments で環境ごとの
default_url_options を指定してあるので、それを呼び出すものとする。

# config/environments/development.rb 内の記載
Rails.application.routes.default_url_options[:host] = "localhost:3000"

# config/environments/production.rb 内の記載
Rails.application.routes.default_url_options[:host] = "prod.example.com"

上のような設定が各ファイルに書かれているとして、
以下のように admin/config/routes.rb には書いてあげて Rails.application.routes.default_url_options[:host] を再利用する。

# admin/config/routes.rb
Admin::Engine.routes.draw do
  default_url_options host: Rails.application.routes.default_url_options[:host]

  resources :users
end

これで admin_app.users_url のような呼び出しも可能になったはずだ。

5. Job から Mountable Engine 側の path や url を呼び出す

Controller はカンタンだけど、では Job や Model から呼ぶにはどうするか。
特に Slack 通知なんかで管理画面側の URL 表記をしたい場合があるだろう。
また、 Rails console から routing を確認したいときもあるだろう。

メインアプリ側であれば include Rails.application.routes.url_helpers の記載があれば
mypage_path などを呼び出せた。
Engine 側はこれだけでは呼び出せない。

NameError: undefined local variable or method `admin_app' for main:Object
Did you mean?  admin_app_url

などと言われてしまうことだろう。

どうするか。 include Rails.application.routes.mounted_helpers を呼び出せばいい。

というわけで、Job は例えばこうなる。

class MountedEngineTestSlackNotificationJob
  include Rails.application.routes.url_helpers
  include Rails.application.routes.mounted_helpers
  include Sidekiq::Worker
  sidekiq_options queue: :slack, retry: 3

  def perform
    blocks = []
    blocks.push({
      type: :section,
      text: {
        type: :mrkdwn,
        text: "リンク → <#{admin_app.users_url}|ユーザー一覧管理画面>",
      },
    })
    notifier = Slack::Notifier.new("https://hooks.slack.com/services/ABCDEF/GHIJKL/MNOPQRSTUVWXYZ")
    notifier.post(attachments: { blocks: blocks, color: "#2eb886" })
  end
end

gem入れてること前提のコードなので、上のはあくまで参考程度に。

Mountable Engine 周りの話はネットに情報少なめなので、情報探すの苦労しました。
最終的には Rails 本体のテスト周りのコードを読むことで解決しました。

やはり https://github.com/rails/rails は神……。

顔画像認識周りのメモ

手っ取り早いのは Haar-like

OpenCV に分類器が同梱されていてすぐに使えるので、試してみるのはとっても簡単です。
これらの記事が詳しいです。

上の記事ではそれぞれの分類器ファイルの説明が書いてあってとてもありがたいのですが、
『haarcascade_profileface.xml : 顔(証明写真)』のとこだけ、
Profile face は「横顔」の意味が正解ですので、そこだけ注意です。

実際に試してみるとこんな感じ。

f:id:nekonenene:20210219082512j:plainf:id:nekonenene:20210219082518j:plainf:id:nekonenene:20210219082522j:plain
Haar-like で試してみた顔認識結果

処理が1秒未満で終わるのは良いのですが、(2841 x 2200 px の画像で 0.74s 程度)
やはりこの手法は画像の白黒パターンの一致から判定しているだけなので、
顔が傾いているとダメだったり、必要以上の場所を認識してしまって、なかなか実用は難しそうです。

英語ですが、「テンプレートマッチング」と「畳み込みニューラルネットワーク」の違いの説明記事は
以下がいい感じでした。

What’s the Difference Between Haar-Feature Classifiers and Convolutional Neural Networks?

CNN(畳み込みニューラルネットワーク)か~

というわけで、実用可能な方向を考えると、
CNN(Convolutional Neural Networks=畳み込みニューラルネットワーク)か~。
なんですけど、ここはまだあれこれ試してないので、メモ程度にリンクをまとめときます。

使えそうなライブラリやアプリケーション

実装してみた記事に関しては、このあたりがわかりやすそうでした。

まだ試せていませんが、実装してみるときはここらへんの記事を読みながらやってみようと思います。

IBMの学習済みモデルを使ったAPIが簡単に作れる Model Asset Exchange なんかも便利だなーと思って読んでましたが、
IBMは2020/06に顔画像認識は肌の色の偏見に基づく可能性があるため撤退しているようで、
現在は Facial recognization は一覧にありませんでした。

【2019/4月更新】学習済みの様々なディープラーニング・モデルをメチャ簡単に利用できる! Model Asset Exchange(MAX)をご紹介します - Qiita

畳み込みニューラルネットワークがなんなのか、どうやって処理しているのかとか、
勉強しないといけないことが多いですが、時間あるときに調べていきたいと思います。

画像処理の基礎:フィルタリング,パターン認識から撮像過程モデルまで | Udemy

この Udemy の講座も、せっかく買ったのにまだほぼ見られてないので、
早く学びたいです。

prezto の rm や mv で確認プロンプトを出さないようにする

prezto を使っているんですが、
デフォルト設定だと rmmv はそれぞれ rm -imv -i になっていて、
安全なのですがやや面倒に感じることもあります。

この機能をオフにするには、

vi ~/.zpreztorc

G でファイル末尾に移動したのち、

zstyle ':prezto:module:utility' safe-ops 'no'

の1行を足してあげて、以下のようにします。

# Enabled safe options. This aliases cp, ln, mv and rm so that they prompt
# before deleting or overwriting files. Set to 'no' to disable this safer
# behavior.
# zstyle ':prezto:module:utility' safe-ops 'yes'
zstyle ':prezto:module:utility' safe-ops 'no'

これだけです。

何が起きているかと言うと、
~/.zprezto/modules/utility/init.zsh に以下のような記述があり、
safe-ops 'yes' (デフォルト)の場合には、
rmrm -iエイリアスとなるなどの設定がおこなわれています。

# Safe ops. Ask the user before doing anything destructive.
alias rmi="${aliases[rm]:-rm} -i"
alias mvi="${aliases[mv]:-mv} -i"
alias cpi="${aliases[cp]:-cp} -i"
alias lni="${aliases[ln]:-ln} -i"
if zstyle -T ':prezto:module:utility' safe-ops; then
  alias rm="${aliases[rm]:-rm} -i"
  alias mv="${aliases[mv]:-mv} -i"
  alias cp="${aliases[cp]:-cp} -i"
  alias ln="${aliases[ln]:-ln} -i"
fi

逆に no にすることで、ここのエイリアス設定をスキップすることが出来るわけですね。