ダメでしょ!

プログラミングとか怒られた話とか…

rails_admin と devise を導入したプロジェクトで、root_path と rails_admin_path が異なる場合のログアウト遷移先設定方法

前提

rails_admin
devise

困っていたこと

一般向けサイトと管理サイトを作成し、管理サイトのみ devise でログイン処理を作成しました。
プロジェクト自体の root_path は一般向けサイトを指定したのですが、そうすると、管理サイトからログアウトした際に root_path に遷移してしまい、非常に不便でした。

対応方法

結論から言うと、application_controller.rb にメソッドを追加しました。

  def after_sign_out_path_for(resource)
    rails_admin_path
  end

これでログアウトしたら rails_admin_path に遷移するようにできます。

github.com

rails_admin 側に設定が存在するだろうと考えて調べていたため、devise 側だということに気づくのに時間がかかってしまった。。。

複数選択可能なチェックボックスやリストボックスで選択された内容を一つのカラムに保存する方法

前提

Rails 4系
haml 4.0系

どういう場面で使うか

入力画面で複数チェックボックスやリストボックスを表示するのは以下のようにかけます。(例としてリストボックス)

= m.select :answer, [['', ''], ['', ''], ['', ''], ['', '']], {}, { multiple: true, size: 4 }

このようにして作成したリストボックスで、以下のようにセットすると、controller には以下のように配列で返却されます。

# 'ア'と'ウ'を選択した場合
"answer" => [
        [0] "",
        [1] "ア",
        [2] "ウ"
    ]

これには問題点があります。

  • そのままではカラムに入らないこと
  • 最初に空の値が存在すること

対処方法

そこで、以下のように array のメソッドである、 delete を使って空の値を削除し、 join を使ってカンマ区切りで結合します。

params[:questionnaire][:answer].delete('')
params[:questionnaire][:answer] = params[:questionnaire][:answer].join(',')

上記を行うことで、返却値は

# 'ア'と'ウ'を選択した場合
"answer" => "ア,ウ"

となり、1カラムに格納することができるようになります。

データベースに格納した後に、その値を配列に戻して、画面に再表示しなければならないような場合はだんだんつらくなると思いますが、格納するだけでOKな場合はこのようなやり方はありだと思います。

rails_admin 導入時の 管理サイトタイトル変更方法

rails_admin を導入してカスタマイズ

rails アプリケーションを作成していて、管理サイトがほしい、と言われることが結構あります。
あんまりこだわりがないお客様の場合、rails_admin を導入することが多いです。
rails で良く利用されている管理画面の gem は他にもありますが、導入が簡単なんですよね。
で、導入した後に毎回躓くのがこれ。

サイトタイトルってどうやって変更する?

通常通りに導入すると、サイトのタイトルがrails アプリケーション名になってしまうんですよね。

f:id:hideukin:20160827174005p:plain

rails アプリケーション名は英語ですので、日本語化が必要になるんです。
で、どうすればいいかというと

  # ./config/initializers/rails_admin.rb
  config.main_app_name = %w(〇〇システム 管理サイト)

と、rails_admin の config に記載すればいいです。

f:id:hideukin:20160827174016p:plain

毎回忘れて、過去に作ったアプリを見て思い出すので、ブログに書いておきます。

simple_form を利用している時にsubmit ボタンにボタン名と value をセットする方法

前提

導入gem

普通の書き方だと、ボタン名が value の値になってしまう

通常、submit ボタンは以下のように記載すると思います。

= f.button :submit, 'ボタン名' { name: "#{f.object_name}[completed]", value: '1', class: 'btn btn-primary' }

しかし、この状態で実際に動作させてみると、ボタン名には value に指定した"1" が表示されてしまいます。
simple_form では、通常ボタン名が value にセットされますが、 value がセットされている場合はボタン名が反映されないためです。

こうすればうまくいく

では、どうすればいいのかというと、以下のように submit を指定せず、button を指定し、 do を付けてボタン名を入れ子にするとうまくいきます。

= f.button :button, { name: 'test', value: '1', class: 'btn btn-primary' } do
  ボタン名

simple_form 手強い...

simple_form を利用していない場合はハマらないと思うんですが、simple_form を導入していると最終的な html の出力が simple_form 次第になるので、ハマってしまった時に解決させるまでには試行錯誤が必要になることが多いです。。

simple_form と bootstrap を利用した環境で f.collection_select をどう書くか

前提

rails 4系
simple_form 3.2.1
bootstrap-sass 3.3.7

そのままだと(非bootstrap になる)

通常、collection_selectは以下のように記載しています。

= f.collection_select :option_id, OptionMaster.all, :id, :option_name, { prompt: true, class: 'form-control' }

しかし、これだと以下の画像のように、非bootstrapな表示をされてしまいます。 f:id:hideukin:20160822144011p:plain

bootstrap に対応した書き方

下のように記載することで、bootstrapに対応した表示になります。

= f.input :option_master_id, collection: OptionMaster.all.map { |v| [v.option_name, v.id] }

f:id:hideukin:20160822144109p:plain

f.input とした上で、collection: の後ろに配列で value と text の組を記載するのがポイントです。

公式も確認したのですが、いまいち曖昧に読み取れたので、ブログに書いてみました。

github.com

ruby において pry を利用している際に、binding.pry を強制的に停止する方法

ちょっと知らなかったので、小ネタですがご紹介。

pry を利用している場合、 ソースコード中に binding.pry と記載することで、記載した場所でデバッグが可能です。
これをループ中に利用し、どのように値が変わっていくかをチェックすることがあるのではないでしょうか。
そして、ある程度確認して、もうとりあえず停止したいけど、停止の仕方がわからない。。

こんな時には、コンソールに !!!と入力してください。

例外を発生させて、強制終了してくれます。

本当は以降の処理をそのまま流してくれるコマンドが知りたかったんだけど、そっちはわかりませんでした。
知っている人がいればぜひ教えて下さい。

ActiveRecord から取得した1レコードから配列を作成する

例として、option_mastersというテーブルが存在していた場合

#
# Table name: option_masters
#
#  id                 :integer          not null, primary key
#  option_name        :string
#  option1            :string
#  option2            :string
#  option3            :string
#  option4            :string
#  option5            :string
#  option6            :string
#  option7            :string
#  option8            :string
#  option9            :string
#  option10           :string
#  operator           :string
#  created_at         :datetime         not null
#  updated_at         :datetime         not null
#

このテーブルに登録されているはじめの1レコードを取得し、配列化したい場合は

OptionMaster.first.attributes.values

とすることで取得できます。
これはattributesでレコードをハッシュとして取得することができ、valuesでハッシュの値を配列として取得することができるためです。

今回は更に、テーブルに登録されているはじめの1レコードを取得し、option1~10 を取得したいとなりました。("option_name"や"operator"は値として必要なかった)
その場合、以下のように記載することで、目的を達することができました。

OptionMaster.first.attributes.select { |k, v| k =~ /option\d/ && v.present? }.values

これは、selectで条件に合致したキーの値だけを取得するためにk =~ /option\d/でキーに対して正規表現で記載しています。
更に、値が入っていない場合は必要なかったので、v.present?で除外しています。

まだまだこういったことがすぐにできるほど Ruby のメソッドを知らないので、作業速度が遅いですが、調べるたびに Ruby は書きやすいなぁと感じます。