動画のような非同期のカウンターアプリを作った時に苦労したので共有します。
# 実装した手順
1.現在の番号をHTMLから取得
2.その番号をajaxでrailsのAPIに送信
3.API内で 送った番号 + 1 の数字にactive recordeの該当カラムを更新。
4.jbuilderでデータを返し、HTML上に反映。
この手順のうち、3で苦戦しました。
この記事では3のみ解説します。
## 当初のコード
js
$(function(){
$(".counter").on("click", function(){
var ccc = Number($(this).text()); //カウンターをクリックするとカウンターの数字を文字列から数字に変換する。
$.ajax({
type: 'post',
url: "/counter",
data: {count: ccc},
dataType: 'json'
})
.done(function(data){
$(".counter").text(data.count); //railsでデータを返し、HTMLを更新する。
})
});
});
controller.rb
def create #ajaxではpatchメソッドに対応していないブラウザがあるようなのでpostメソッド内でupdateを行なっています。
@user = User.find(current_user.id)
@co = params[:count] + 1 #ここで送られた数字+1を定義。
@user.update(counter: @co) #usersテーブルのcounterカラムを更新
respond_to do |format|
format.html
format.json #返すデータはjson.jbuilderで定義。
end
end
#jbuilderファイルは省略。
このコードだと以下のエラーを吐き出しました。
TypeError in CounterController#create
no implicit conversion of Integer into String
Extracted source (around line #9)
//(around line #9)は @co = params[:count] + 1 をさしています。
意味としては整数(この場合は1
)を文字列に変えてくださいという内容です。
つまりは、+
を四則演算ではなく、文字列結合に使おうとしているようです。
原因がわからず手当たり次第にコードを変えたら、以下のコードで問題なく動作しました。
controller.rb
def create
@user = User.find(current_user.id)
@co = params[:count].to_i + 1 #この行のみ変更
@user.update(counter: @co)
respond_to do |format|
format.html
format.json
end
end
## 結論
結論としてはajaxで送られた数字は、paramsで取得すると、文字列となってしまうということです。
ちなみにrails内のみで渡したparamsも元データの形に関わらず、文字列となるようです。(この辺りは実験がまだ足りていないので要検証)。
## 別解
js
$(function(){
$(".counter").on("click", function(){
var ccc = Number($(this).text()) + 1; //ここのみ変更
$.ajax({
type: 'post',
url: "/counter",
data: {count: ccc},
dataType: 'json'
})
.done(function(data){
$(".counter").text(data.count); //railsでデータを返し、HTMLを更新する。
})
});
});
そもそも入手した数字+1
の処理をjs内ですれば
update(counter: params[:count])
だけでできた・・・