TECH EXPERT 31日目

TECH::EXPERT

実装に入ったけど、地味なところでつまづいては調べるの繰り返し。
カリキュラムになかなか追いつかない。

rails

carrierwave

.url

image.urlとすると画像のURLを取得する。
通常はuploadsフォルダ以下の階層が入っている。

jQuery

append()

jQueryオブジェクトに対してしか使えない。
不用意に使うとappend is not a functionエラーが出る。

target = e.srcElement
target.append(test_div);
↑これはDOMオブジェクトなのでエラー。

jQueryならこう。
$(target).append(test_div);

javascriptならこう。
target.appendChild(test_div);

非同期通信でのsubmitボタンの連続入力

連続送信を避けるため、標準で送信中は再び押せないようになっている。
いつの頃からかdata: disable_withが標準実装されたらしい。

f.submit "Send", data: {disable_with: '送信'}

非同期通信する際には入力が連続できずに困るのでこれを解除する。

$('#submit-btn').removeAttr('data-disable-with');

もしくはformないしsubmitに対してfalseを返してやれば再び押せるようになる。

$("#new_message").on('submit',function(e){
return false;
})

.animate(properties, duration, easing)

cssの値を持つプロパティを第1引数に指定し、durationの時間をかけて指定の値まで変化させる。

$('.target').animate({scrollTop: $(".target")[0].scrollHeight});

scrollTop

scrollHeightはJavaScriptのメソッドなので使えない。
使う場合には$(‘target’)[0].scrollHeightとしてDOM要素に変換してから使うこと!

.reset()

フォームオブジェクトに対して使う。
フォーム内容を全てクリアする。
JSのメソッドのため[0]でDOMオブジェクトに戻す必要あり。

$("#new_message")[0].reset();
  • フォーム要素をresetすることで全ての項目をリセット可能(個別にvalをしなくて済み、コード量が減って可読性も向上)
  • inputの初期値があった場合、resetを使うとvalueにその初期値を入れることが可能

動的に生成した要素に対してイベントを設定する方法

通常は以下のようにするが、このイベントで追加された要素に対してイベントが設定できない。

$(selector).on(event, function)

後から追加した要素にイベントを設定するには、元から存在する要素にイベントを設定する。そしてイベントの発生源が第2引数のtargetだった場合にイベントを発生させる。

$(selector).on(event, target, function)

これなら後から生成した要素に対してもイベントを起こせる。
なおこのfunction内で$(this)とした場合には、$(selector)ではなく、targetが格納される。

.eq()

指定した要素のn番目の要素を取得する。
0番目から数える。

$('.form__field--right').eq(1).append(buildHTML(user))

ajax

400 bad request

送信するデータの形が間違っていてもbad request

$.ajax({
  url: url,
  type: 'POST',
  data: {message: {body: body} },
  dataType: "json"
})

下のように手抜きしてるとエラーを吐く。
data: {body: body},

API

返却されるjson形式のデータ

インスタンスを渡すとそのモデルの情報のみがjson内に格納される。

format.json {render json: @message}

この場合@messageのインスタンス変数は呼べるが、アソシエーションを組んだモデル@message.userは呼べない。
なので@message.user.nameが欲しい時はjson.jbuilderファイル内で以下のように別途定義する。

json.body @message.body
json.name @message.user.name

APIで返した画像ファイルの出力

意識せずに@message.imageとして式展開したら謎のobjectでエラー。

/create.json.jbuilder
json.image @message.image

/create.js
<img src=${message.image}>

html
<img src="[object" object]="">

一応文字列にして渡したら動きはした。
これでいいのか?

json.image "#{@message.image}"

turbolinks

ブラウジング高速化のためのgem。
HTMLロード→CSS, JavaScriptロード→レンダリング
の流れの中で中間部分を飛ばす手法。

具体的には初回ロード時には附帯情報を取得するが、以降のページ遷移では附帯情報を保持したままでHTML情報のみを取得する。

ここで問題となるのはページ読み込みを起点としたJavaScriptが動かなくなること。

$(function() {
    #処理
});

で始まるjQueryは全てページ読み込み完了を起点に動くようになっているので、turbolinksが有効だと動かなくなります。正確には初回アクセスのページでは動作しますが、リンクを踏んで移動すると機能しなくなります。
ロードしてしまえば動くので、F5リロードで再び動作するようになります。

解決法

1.gem自体を削除する (非推奨)

gemfileからturbolinksを削除。

app/assets/javascripts/application.js から「//= require turbolinks」を削除する。

views/layouts/application.html.erb or hamlから以下の’data-turbolinks-track’: ‘reload’の記述を削除

= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload'
= javascript_include_tag 'application', 'data-turbolinks-track': 'reload'

2. JSファイルの記述を変更する。 (推奨)

jQueryなら$(function(){}で始まる記述を以下へ変更する。

$(document).on('turbolinks:load', function() {
}

JavaScriptなら以下のように変更する。

document.addEventListener("turbolinks:load", function() {
  // ...
})
【Ruby on Rails】Turbolinksについてご意見お聞かせ下さい|teratail
Ruby on Railsまだ2か月程度の者です。 「Turbolinks」のおかげで、jQueryが時折意図した動きをせず。。。 度々悩まされております。 Turbolinksの目的はおおよそ分かりました。 現在、作成中のアプリが多様なjs, cssを使用しない

= form_for group do |f|
 .chat-group-form__field--right
  = f.text_field :name
 - group.users.each do |user|
  .chat-group-user
    %input{name: "group[user_ids][]", type: "hidden", value: user.id}/
    %p.chat-group-user__name= user.name
    .user-search-remove.js-remove-btn 削除

6行目の%inputで=をつけていないのにuser.idが展開されるのはなぜ?

{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"teow24w==", 
"group"=>{
    "name"=>"@@p@000000000000", 
    "user_ids"=>["1", "2", "3"]
    }, 
"commit"=>"登録する", 
"controller"=>"groups", 
"action"=>"update", 
"id"=>"12"}

paramsにgroup[user_ids][]にvalueが入った配列ができているのはなぜ?

コメント