Heroku SeachBox ElasticsearchがRails Searchkickのデフォルト設定で動かない
実運用しているアプリが2020/2/13あたりからインデックスの新規作成が上手くいかず調査しました。
エラー
class Post < ApplicationRecord searchkick end
reindexでエラーが出ます。
irb(main):001:0> Post.reindex Traceback (most recent call last): 1: from (irb):1 Elasticsearch::Transport::Transport::Errors::BadRequest ([400] {"error":{"root_cause":[{"type":"remote_transport_exception","reason":"[oin-1][10.0.24.93:9300][indices:admin/create]"}],"type":"illegal_argument_exception","reason":"The difference between max_gram and min_gram in NGram Tokenizer must be less than or equal to: [1] but was [49]. This limit can be set by changing the [index.max_ngram_diff] index level setting."},"status":400})
create_indexでエラーが出ている模様
対応
searchkick
のインデックス設定を変更
max_shingle_size
を4にするmin_gram
,max_gram
の差を1にする
※値は各自の環境、必要要件に合わせてください
class Post < ApplicationRecord MIN_GRAM = 1.freeze searchkick settings: { analysis: { filter: { searchkick_suggest_shingle: { max_shingle_size: 4 }, searchkick_ngram: { min_gram: MIN_GRAM, max_gram: MIN_GRAM + 1 } } } } end
調査過程
index.max_ngram_diff
を1に設定
The difference between max_gram and min_gram in NGram Tokenizer must be less than or equal to: [1] but was [49]. This limit can be set by changing the [index.max_ngram_diff] index level setting.
index.max_ngram_diff
は1にしないといけないということで設定する
class Post < ApplicationRecord searchkick settings: { index: { max_ngram_diff: 1 } } end
結果
エラー変わらず
irb(main):001:0> Post.reindex Traceback (most recent call last): 1: from (irb):1 Elasticsearch::Transport::Transport::Errors::BadRequest ([400] {"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"The difference between max_gram and min_gram in NGram Tokenizer must be less than or equal to: [1] but was [49]. This limit can be set by changing the [index.max_ngram_diff] index level setting."}],"type":"illegal_argument_exception","reason":"The difference between max_gram and min_gram in NGram Tokenizer must be less than or equal to: [1] but was [49]. This limit can be set by changing the [index.max_ngram_diff] index level setting."},"status":400})
indexの設定を確認する
irb(main):001:0> Post.searchkick_index.index_options {:settings=> {:analysis=> {:analyzer=>{}, :filter=> {:searchkick_index_shingle=>{:type=>"shingle", :token_separator=>""}, :searchkick_search_shingle=> {:type=>"shingle", :token_separator=>"", :output_unigrams=>false, :output_unigrams_if_no_shingles=>true}, :searchkick_suggest_shingle=>{:type=>"shingle", :max_shingle_size=>5}, :searchkick_edge_ngram=> {:type=>"edge_ngram", :min_gram=>1, :max_gram=>50}, :searchkick_ngram=>{:type=>"ngram", :min_gram=>1, :max_gram=>50}, :searchkick_stemmer=>{:type=>"snowball", :language=>"English"}}, :char_filter=>{:ampersand=>{:type=>"mapping", :mappings=>["&=> and "]}}}, :index=>{:max_ngram_diff=>1, :max_shingle_diff=>4}}, # ...省略
max_ngram_diff
は1になったが min と max の実際の差が問題のよう
:searchkick_ngram=>{:type=>"ngram", :min_gram=>1, :max_gram=>50},
analysis.filter.searchkick_ngram.max_gram
を2に設定
class Post < ApplicationRecord searchkick settings: { analysis: { filter: { searchkick_ngram: { max_gram: 2 } } } } end
結果
エラーが変わった
irb(main):001:0> Post.reindex Traceback (most recent call last): 1: from (irb):1 Elasticsearch::Transport::Transport::Errors::BadRequest ([400] {"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"In Shingle TokenFilter the difference between max_shingle_size and min_shingle_size (and +1 if outputting unigrams) must be less than or equal to: [3] but was [4]. This limit can be set by changing the [index.max_shingle_diff] index level setting."}],"type":"illegal_argument_exception","reason":"In Shingle TokenFilter the difference between max_shingle_size and min_shingle_size (and +1 if outputting unigrams) must be less than or equal to: [3] but was [4]. This limit can be set by changing the [index.max_shingle_diff] index level setting."},"status":400})
次は max_shingle_diff
は3にしないといけないとのこと
index.max_shingle_diff
を3に設定
class Post < ApplicationRecord searchkick settings: { index: { max_shingle_diff: 3 }, analysis: { filter: { searchkick_ngram: { max_gram: 2 } } } } end
結果
エラー変わらず
irb(main):001:0> Post.reindex Traceback (most recent call last): 1: from (irb):1 Elasticsearch::Transport::Transport::Errors::BadRequest ([400] {"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"In Shingle TokenFilter the difference between max_shingle_size and min_shingle_size (and +1 if outputting unigrams) must be less than or equal to: [3] but was [4]. This limit can be set by changing the [index.max_shingle_diff] index level setting."}],"type":"illegal_argument_exception","reason":"In Shingle TokenFilter the difference between max_shingle_size and min_shingle_size (and +1 if outputting unigrams) must be less than or equal to: [3] but was [4]. This limit can be set by changing the [index.max_shingle_diff] index level setting."},"status":400})
max_ngram_diff
と同じで実際の数値が問題のよう
:searchkick_suggest_shingle=>{:type=>"shingle", :max_shingle_size=>5},
現状5になっている
analysis.filter.searchkick_suggest_shingle.max_shingle_size
を4に設定
class Post < ApplicationRecord searchkick settings: { analysis: { filter: { searchkick_suggest_shingle: { max_shingle_size: 4 }, searchkick_ngram: { max_gram: 2 } } } } end
結果
reindex成功
irb(main):001:0> Post.reindex D, [2020-05-06T04:53:35.428208 #4] DEBUG -- : Post Load (632.2ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT $1 [["LIMIT", 1000]] D, [2020-05-06T04:53:35.532908 #4] DEBUG -- : Post Import (84.4ms) {"count":3} => true
Railsでモーダルの出し分けを管理する
Railsでモーダルの表示処理をまとめて衝突しないように管理する方法を紹介します。
背景
ツクリンクを運営する中でモーダルが少しづつ増え、衝突することがあったためモーダルの優先順位を付け、衝突しないよう実装をしました。
実装
前提
以下の3つのモーダルがあるとします。
- A: 初回ログインで出すモーダル(全ページ)
- B: 特定のユーザーにだけお知らせを出すモーダル(全ページ)
- C: 特定のページで出すモーダル(Posts#show)
コードサンプル
全ページに出すモーダルはApplicationControllerで該当ユーザーか判断しモーダルに必要な情報をセットします。
# controllers/application_controller.rb class ApplicationController < ActionController::Base before_action :set_modal_A before_action :set_modal_B def set_modal_A return if cookies['modal_A'].present? # 表示済みなら何もしない if is_first_signed_in? # 初回ログインか? @modal_A = { title: '表示に必要な情報など' } end end def set_modal_B return if cookies['modal_B'].present? # 表示済みなら何もしない if show_notice? # お知らせを出すユーザーか? @modal_B = true end end end
Viewごとに出るモーダルは provide
でモーダルをセット
# views/posts/show.html.erb <% provide :modal, render('modal/C') %>
レイアウトのView(もしくはそれに準ずるパーシャル)でモーダルの出し分けを行います。 ifの上位にあるものが優先され、モーダルが複数renderされるのを防いでいます。
# views/layouts/application.html.erb <% if yield(:modal).present? %> <%= yield(:modal) %> <% elsif @modal_B.present? %> <%= render 'modal/B' %> <% elsif @modal_A.present? %> <%= render 'modal/A' %> <% end %>
各モーダルのViewでは表示を管理するCookieを保存するなどの処理をしています。
# views/modal/A.html.erb <% cookies.permanent['modal_A'] = { value: true, expires: 1.day } %> <div class="modal">お知らせだよ!</div>
FirebaseFunctionsで素のJSを返す
実現したいこと
FirebaseFunctionsを使ってリクエスト元やパラメータに合わせたJSファイルを作り返したい
こんな風に使いたい
<script src="https://asia-northeast1-fir-functions-return-js.cloudfunctions.net/hello"></script>
Functionsの実装
functions/index.js
exports.hello = functions .region('asia-northeast1') .https.onRequest((request, response) => { // Using query const name = request.query.name || 'defaultName'; // Return alert js response .contentType('application/javascript; charset=utf-8') .send(`alert('Hello ${name}')`); });
response.send
で返してあげるだけで読み込み可能でした。
サンプル
サンプルページ
RSpec 1つのexpectで複数のchangeを検証する
表題通り1つのexpectに対して複数のchangeを検証したい
it '複数のchangeを見るぞ' do expect { subject }.to change { x }.by(1). and change { y }.by(2) end
見づらいのであまり使いたくない…
RSpec3.1からの機能らしい rspec.info
LastPassエクステンションで共有フォルダの内容が更新されない時の対応
別アカウントで共有フォルダの内容を変更したのにChromeエクステンションのLastPassでは内容が見れなかった時の対応
※2023/12/15更新 新しいUI
Account
→ Fix a problem your self
→ Reflesh your vault
※古いUI
その他のオプション
-> 高度な設定
-> サイトを更新
で無事更新されました。