質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

解決済

【Rails】heroku本番環境のみでtoggleでのデータ送信がうまくいかない(postgreが原因?)

Romay
Romay

総合スコア0

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

2回答

0評価

0クリップ

882閲覧

投稿2019/04/07 06:18

前提・実現したいこと

Ruby 2.4.5
Rails 4.2.8
本番環境:heroku postgreSQL
開発環境:mySQL

以下やりたいことの流れです。

  1. users/editのviewにおける部分テンプレート、_item.html.erbのチェックボックスをチェック


2. javascript発動で、item_controllerのtoggleアクションを動かす(POST送信)

3. item_controllerのtoggleアクションで、「check」カラムが、0だったら1、1だったら0にして保存

itemというテーブルの、checkというカラムをチェックボックスをチェックするごとに0と1に変えるということが目的です。

開発環境では正常に動作しているtoggleの機能(0と1でデータ交換するだけ)が、heroku上の本番環境ではうまくいきません。
herokuのログを見る限り、チェックボックスチェック時にtoggleデータ送信するJavaScriptは動き、コントローラーも動いています。

おそらく、mySQLとpostgresqlの何かしらの仕様の違いによって、この問題が生じているのではと推測しています。

発生している問題・エラーメッセージ

heroku上のログです。

heroku

2019-04-07T05:56:47.929678+00:00 app[web.1]: Item Load (1.1ms) SELECT "items".* FROM "items" WHERE "items"."deleted_at" IS NULL AND "items"."id" = $1 LIMIT 1 [["id", 4]] 2019-04-07T05:56:47.931283+00:00 app[web.1]:  (1.0ms) BEGIN 2019-04-07T05:56:47.934576+00:00 app[web.1]: SQL (1.4ms) UPDATE "items" SET "check" = $1, "updated_at" = $2 WHERE "items"."id" = $3 [["check", 0], ["updated_at", "2019-04-07 05:56:47.931522"], ["id", 4]] 2019-04-07T05:56:47.938156+00:00 app[web.1]:  (2.9ms) COMMIT 2019-04-07T05:56:47.938440+00:00 app[web.1]: Completed 200 OK in 18ms (Views: 0.5ms | ActiveRecord: 9.8ms) 2019-04-07T05:56:47.943427+00:00 heroku[router]: at=info method=POST path="/items/4/toggle" host=********(URL名) request_id=757251******39b-814e-baf49b5fe545 fwd="173*****114" dyno=web.1 connect=0ms service=36ms status=200 bytes=880 protocol=https

該当のソースコード

部分テンプレート
_item.html.erb

ruby

<li class="idea"> <div class="idea-text"> <div class="checked-item_<%= "#{item.id}"%>" > <%= item.text %> </div> </div> <div class="item-menu-right"> <%= link_to item_path(item), method: :delete , remote: true do %> <i class="fa fa-trash fa-fw" aria-hidden="true"></i> <% end %> <%= link_to edit_item_path(item), method: :get ,class: "fa-edit-margin", item_id: item.id do %> <i class="fa fa-edit fa-fw" aria-hidden="true" ></i> <% end %> <%= check_box_tag '', '', item.check, {'data-id' => item.id, 'data-user-id' => item.user_id ,class: "check_#{item.id} option-input"} %> </div> </li> <!-- チェックつけたら赤取り消し線つける --> <script> $(function() { $('.check_<%= "#{item.id}"%>').on('click', function() { if ( $(this).prop('checked') == false ) { $('.checked-item_<%= "#{item.id}"%>').removeClass("delete-text"); } else { $('.checked-item_<%= "#{item.id}"%>').addClass("delete-text"); } }); }); // ロードしたときに、item.check == 1 ならdelete-textをつける処理。 $(function(){ if (<%=h item.check %> == 1) { $('.checked-item_<%= "#{item.id}"%>').addClass("delete-text"); } else { $('.checked-item_<%= "#{item.id}"%>').removeClass("delete-text"); } }); </script>

チェックボックスチェック時にデータ送信するjavascriptファイル

javascrpt

$(document).on('turbolinks:load', function() { $("input[type=checkbox]").click(function(){ $.post('/items/'+$(this).data('id')+'/toggle'); }); });

items_controller.rb

ruby

def toggle render nothing: true @item = Item.find(params[:id]) @item.check = !@item.check @item.save end

試したこと

mySQLだと、checkカラムは、tinyintになっていますが、herokuのpostgreSQLだとこれが違う構造になっているのではないか思います。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

urbainleverrier
urbainleverrier

2019/04/07 06:56

ログでは、transactionも通ってますし、httpレスポンスも200になっています。何がうまくいきませんか?
Romay
Romay

2019/04/07 07:02

コメントありがとうございます。わかりにくくてすみません。。。checkのカラムが、0から1\(True\)になっていないのです。ユーザーがチェックボックスをおしてチェックをつけた場合、checkカラムには1(True)が保存されることを期待しています。そして、チェックボックスのチェックを外した場合、0に戻るようにしたいのです。
urbainleverrier
urbainleverrier

2019/04/07 07:24 編集

`@item\.check = !@item\.check`この前後の`check`は期待された値になっていますか?consoleを使って試してみてください。また、スキーマはbooleanに設定されていますか?
Romay
Romay

2019/04/07 07:41

以下 schema\.rbの一部抜粋です。booleanになっているように思います。 create_table "items", force: :cascade do |t| t\.integer "user_id", limit: 4 t\.text "text", limit: 65535 t\.datetime "created_at", null: false t\.datetime "updated_at", null: false t\.boolean "check" t\.datetime "deleted_at" end そして、以下heroku上のconsoleです。\[7\] pry\(main\)> @item\.check => 0 \[8\] pry\(main\)> @item\.check = !@item\.check => false \[9\] pry\(main\)> @item\.check => 0 この\[8\]の部分がうまくいってないということでしょうか?ローカル環境では動いているので少し謎なのですが。。。
urbainleverrier
urbainleverrier

2019/04/07 15:06 編集

consoleの値がおかしいですね。 本来は\[7\]でfalseなら\[9\]ではtrueを期待するのではないですか? rubyの場合、!0も!1もfalseです。 `t\.boolean "check", default: false, null: false`としてみてください。 \[7\]でfalseと出力されればいいのですが。
Romay
Romay

2019/04/07 21:00

rake db:migrate:reset をして、createItemsのマイグレーションファイルを書き換えて、デプロイしrake db:migrateもしてみました。 しかし、heroku上のコンソールで確認するとうまくいってないようです。 herokuのデータベースへの書き込み権限などの問題でしょうか? herokuのコンソールで、@item\.check = 1で強制的に入れてみたものの、実際のデータベースは0のままでした。
urbainleverrier
urbainleverrier

2019/04/08 05:18 編集

>>herokuのデータベースへの書き込み権限などの問題でしょうか? コンソールでtransactionがcommitされているなら問題ないはずです。 >>herokuのコンソールで、@item\.check = 1で強制的に入れてみたものの、 saveしましたか? `item = Item\.find\(4\); puts item\.check; item\.check = '1'; item\.save!` その後、 `item = item\.reload; puts item\.check` として値を出力し、出力内容を確かめてください。最初のputsでfalseや0が出力され、二番目でtrueか1が出力されることを期待します。reloadでsqlが発行され、データベースから値を取得していることを確かめてください。 saveはsave!に書き換えてください。true or falseでなく、失敗すればエラーが返されます。 また、@item\.check = '1'ではなく、BooleanのtrueやIntegerの1、Stringの1で試してみてください。 この辺りの挙動で何かあると思います。 また、開発環境をmysqlからpostgresqlにしましょう。もし、herokuのconsoleでsql文など、十分に出力が得られないなら、開発環境で試しましょう。
Romay
Romay

2019/04/08 07:59

前回のときは、saveしていませんでした。。。 以下コンソール結果です。 \[2\] pry\(main\)> @item = Item\.find\(4\) \(省略\) \[3\] pry\(main\)> puts @item\.check 0 => nil \[4\] pry\(main\)> @item\.check = 1 => 1 \[5\] pry\(main\)> @item\.save! \(省略\) \[7\] pry\(main\)> @item = @item\.reload \[8\] pry\(main\)> puts @item\.check 1 => nil 最後1と表示されているものの、nilと返されているのは何かおかしいような気がします。 しかし、Dataclipsで直接データベースを見ると、ちゃんと1になっていました。
Romay
Romay

2019/04/08 08:02

そして、以下が、'true'で試してみたものです。 trueを入れたものの、save!後もcheckの値は、0でした。 trueで書き換えようとするものの、実際には保存されずそのまま0になっているように思えます。 これが原因でしょうか。。。 \[2\] pry\(main\)> item = Item\.find\(1\) \[3\] pry\(main\)> item\.check => 0 \[4\] pry\(main\)> item\.check = 'true' => "true" \[5\] pry\(main\)> item\.save! \(1\.3ms\) BEGIN \(1\.3ms\) BEGIN SQL \(1\.2ms\) UPDATE "items" SET "check" = \$1, "updated_at" = \$2 WHERE "items"\."id" = \$3 \[\["check", 0\], \["updated_at", "2019-04-08 07:58:42\.064189"\], \["id", 1\]\] SQL \(1\.2ms\) UPDATE "items" SET "check" = \$1, "updated_at" = \$2 WHERE "items"\."id" = \$3 \[\["check", 0\], \["updated_at", "2019-04-08 07:58:42\.064189"\], \["id", 1\]\] \(3\.8ms\) COMMIT \(3\.8ms\) COMMIT => true \[6\] pry\(main\)> item\.check => 0
urbainleverrier
urbainleverrier

2019/04/08 08:40

>>最後1と表示されているものの、nilと返されているのは何かおかしいような気がします。 putsというメソッドの返り値はnilですので大丈夫です。 >>\[4\] pry\(main\)> item\.check = 'true' ではなく、item\.check = trueではないですか? データベースに保存する内容はデータを節約するために1か0にするのですが、railsかpostgresqlが何を1とし、何を0と変換するのかルールがあるんだと思います。文字列、数字、真偽値、様々なrubyの型があり、trueとしての1を表現するにも色々ありますから、今回その辺りの挙動で戸惑っていらっしゃるのだと思います。
Romay
Romay

2019/04/08 23:23

知識不足ですみません。。。 おっしゃる通り、item\.check = trueで期待する動作(0から1へ変換)できていました。 その後、本番環境のユーザービュー(コンソールではなく\)からチェックボックスを押すと(1から0への変換)期待する動作をし、0になっていました。しかし、逆の動作(0から1への変換\)が、ユーザービューからできていません。 つまり、データベースのcheckの値が、もともと1の場合は、ユーザービューから0にできるのですが、0の場合から1にできていないという不可逆的なtoggleになってしまっているということです。 なぜこのような動きになってしまうのか見当がつきません。また、チェックボックスについてですが、ページ読み込み時に、item\.checkの値が0の場合はチェックがチェックボックスについていない状態にしたい(開発環境ではできている)のですが、本番環境だitem\.checkの値に関係なしにチェックがついてしまっています。これも何か関係しているのではないかと推測しています。
Romay
Romay

2019/04/09 20:02

postgreのboolean型について調べていたところこの記事を見つけました。 これが原因でしょうか。。。 trueはtrueになり、falseは0になる。 http://workmemo\.techblog\.jp/archives/29505582\.html

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。