今日は新しい方の建物で勉強。
ガラス張りなので窓際は暑い。
応用カリキュラム以降はこっちで勉強するように促されたのもあって異常に人が多い。アジアビルの方が少ないので楽だ。
私はフォンティスが近いし、このビルで勉強する意味はないな。
土足だし長時間戦う場所じゃない。
ruby
attr_accessor, attr_reader, attr_writer
attr_accessor ゲッターとセッター
attr_reader ゲッターのみ
attr_writer セッターのみ
rails
buildとnew
同じ機能。昔は違ったようだがver4以降では特に差はない。
かつてbuildはアソシエーションありのモデルに使われていたみたい。
form_with
Rails5.1からはform_tagとform_forはform_withメソッドに統合
collection_check_boxes
APIドックによると以下の引数を持つ。
collection_check_boxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
具体的には以下のように用いる。
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial)
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
b.label(:"data-value" => b.value) { b.check_box + b.text }
end
なおform_for等のインスタンスをオブジェクトに持つ場合には1つ目の引数は省略できる。
例 f.collection_check_boxes
第2引数のmethodの意味がわからない?
後ろの3つの引数だけで動きそうに思うが、第1,2引数を指定することで内部で何をしているのでしょうか?
以下のように定義してpryでparamsの内容を確認してみた
= form_for @group do |f|
= f.text_field :name, placeholder: "グループ名を入力してください", class: "chat-group-form__input", id: "chat_group_name"
= f.collection_check_boxes :user_ids, User.all, :id, :name
= f.submit :commit, value: "登録する", class: "chat-group-form__action-btn", "data-disable-with": '送信中'
paramsの:groupに ”user_ids”=>[“”, “1”, “2”] と書いてあるのがcheckboxで選択したID。
もしかしてcheckboxの第2引数がparamsのキーに入る???
確認するとやっぱりそうでした。ただ、第2引数を闇雲に指定してもundefinedと言われるので、第1引数のオブジェクトに関連する変数じゃないとダメみたい。
pry> params
=> <ActionController::Parameters {
"utf8"=>"✓",
"authenticity_token"=>"wmjtg==",
"group"=>{
"name"=>"hogehoge",
"user_ids"=>["", "1", "2"]
},
"commit"=>"登録する",
"controller"=>"groups",
"action"=>"create"
}
permitted: false>
ここでpermitする項目を抜粋 permit(:name, { user_ids: [] })
pry> params.require(:group).permit(:name, { user_ids: [] })
=> <ActionController::Parameters {
"name"=>"e3333333333",
"user_ids"=>["", "1", "2"]
}
permitted: true>
{ user_ids: [] }の部分は:user_idsでもいいんじゃないかと思ったけど、
unpermitted parameterと言われてしまいました。
配列には配列であることを明示しないと受け付けてくれない感じ。
pry> params.require(:group).permit(:name, :user_ids)
Unpermitted parameter: user_ids
=> <ActionController::Parameters {"name"=>"e3333333333"} permitted: true>
user_ids:[]として見たら通りました。
user_ids: []と半角スペースでも問題なくOK。
pry> params.require(:group).permit(:name, user_ids:[])
=> <ActionController::Parameters {
"name"=>"e3333333333",
"user_ids"=>["", "1", "2"]
} permitted: true>
ここまで書いて気づいたけど、railsはハッシュの{}は省略できるんだったわ。
https://railsguides.jp/action_controller_overview.html#ネストしたパラメータ
params.require(:group).permit( {user_ids: []}, :name)
これは通る
params.require(:group).permit( user_ids: [], :name)
これは通らない
syntaxエラー unexpected ')' で止まる。
params.require(:group).permit(:name, user_ids:[])
これが通るのだから通りそうなものなのに。
配列指定の後に続けて書く場合は{}で囲わないとエラーになっちゃいますね。
has_many throughのsave時の挙動
def new
@group = Group.new
@group.users << current_user
end
def create
@group = Group.new(create_params)
@group.save
end
private
def create_params
params.require(:group).permit(:name, user_ids: [])
end
group.saveする時にgroupのテーブルのみならず、group_userテーブルにも保存される。
save直前でpryで止めて確認すると、
@group
=> #<Group:0x00007ffb6f749268 id: nil, name: "sgggg", created_at: nil, updated_at: nil>
@group.users
=> [#<User id: 1, email: "aaa@aaa", name: "hogehoge">,
#<User id: 2, email: "fdg@dfg", name: "fugafufa">]
@product = Product.new
@product.save
とする際に、
Productモデルのインスタンスであるため、そのモデルが管理するテーブル(products)だけが更新されると思っていました。
ところがgroupとuserを中間テーブルを用いてアソシエーションを組んだ場合に、
@group.saveを行うと、groupテーブルのみならず中間テーブルも更新されます。
さらに@group.users[1][:name] = “hoge”のような処理を加えて
@group.saveを行うとuserテーブルも更新されます。
つまり標準ではアソシエーションを組むと自動的に連携するすべてのテーブルを更新するのだと思います。
rails guideのautosaveの項目に同様の記述があります。
.new(class)に外部キーっぽい配列を引き渡した場合の処理
has_many throughでuserとgroupモデルが繋がっているときに
def create
@group = Group.new(create_params)
@group.save
end
private
def create_params
params.require(:group).permit(:name, user_ids: [])
end
“user_ids”=>[“”, “1”, “2”]を引き渡したところ、
@group
=> #<Group:0x00007ffb6f749268 id: nil, name: "sgggg", created_at: nil, updated_at: nil>
@group.users
=> [#<User id: 1, email: "aaa@aaa", name: "hogehoge">,
#<User id: 2, email: "fdg@dfg", name: "fugafufa">]
が返った。.newに配列を渡すと複数生成されるのか?
そもそも配列を渡してよいのか?
initializeメソッドでの処理だと思うが、その実態はどのように確認したらよいのか?
flashメッセージ
一時的に表示させるメッセージ
:notice :alert :flashの3つが使える。
def create
@group = Group.new(create_params)
if @group.save
redirect_to controller: :messages, action: :index
flash[:notice] = 'グループを作成しました'
else
flash[:alert] = 'グループ名を入力してください'
render :new
end
redirect_toには直接引き渡すこともできる。
redirect_to :root, notice: "グループ作成"
errorsメソッド
validationで失敗した場合、保存しようとしたインスタンスはnilではなく、エラー情報を含んだインスタンスになる。(情報が追加される)
これをrenderで再度同じページに飛ばすことで、エラー情報を持つ場合の分岐が作れる。
.full_messages
エラーメッセージを配列で取得できる。
- if @group.errors.any?
.chat-group-form__errors
%h2= "#{@group.errors.full_messages.count}件のエラーが発生しました。"
%ul
- @group.errors.full_messages.each do |message|
%li= message
.any? {|item| block }
配列に対して処理する。block内での処理でtrueが返ればtrueを。
配列が空であったり、処理結果が全てfalseだった場合にfalseを返す。
haml
form_for
f.text_field等は1段インデントする。
また属性はカンマ区切りで続けてかける。
= form_for @group do |f|
= f.text_field :name, placeholder: "グループ名を入力してください", class: "chat-group-form__input", id: "chat_group_name"
data-disable-with
多重送信を防ぐためにrails5から実装。
連続でsubmitをクリックできなくなるが、代わりに表示する名称を設定できる。
f.submit "Send", "data-disable-with": "送信中..."
GIT
Reset, Checkout, Revert
戻す際に使うコマンド。
それぞれ違うが詳細は勉強中
コメント