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

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

新規登録して質問してみよう
ただいま回答率
85.48%
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の基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

1170閲覧

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

Romay

総合スコア40

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の基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿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

12019-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]] 22019-04-07T05:56:47.931283+00:00 app[web.1]:  (1.0ms) BEGIN 32019-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]] 42019-04-07T05:56:47.938156+00:00 app[web.1]:  (2.9ms) COMMIT 52019-04-07T05:56:47.938440+00:00 app[web.1]: Completed 200 OK in 18ms (Views: 0.5ms | ActiveRecord: 9.8ms) 62019-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

1<li class="idea"> 2 <div class="idea-text"> 3 <div class="checked-item_<%= "#{item.id}"%>" > 4 <%= item.text %> 5 </div> 6 </div> 7 <div class="item-menu-right"> 8 <%= link_to item_path(item), method: :delete , remote: true do %> 9 <i class="fa fa-trash fa-fw" aria-hidden="true"></i> 10 <% end %> 11 <%= link_to edit_item_path(item), method: :get ,class: "fa-edit-margin", item_id: item.id do %> 12 <i class="fa fa-edit fa-fw" aria-hidden="true" ></i> 13 <% end %> 14 15 <%= check_box_tag '', '', item.check, {'data-id' => item.id, 'data-user-id' => item.user_id ,class: "check_#{item.id} option-input"} %> 16 17 </div> 18</li> 19 20<!-- チェックつけたら赤取り消し線つける --> 21<script> 22 23$(function() { 24 $('.check_<%= "#{item.id}"%>').on('click', function() { 25 if ( $(this).prop('checked') == false ) { 26 $('.checked-item_<%= "#{item.id}"%>').removeClass("delete-text"); 27 } else { 28 $('.checked-item_<%= "#{item.id}"%>').addClass("delete-text"); 29 } 30 }); 31}); 32 33// ロードしたときに、item.check == 1 ならdelete-textをつける処理。 34$(function(){ 35 if (<%=h item.check %> == 1) { 36 $('.checked-item_<%= "#{item.id}"%>').addClass("delete-text"); 37 } else { 38 $('.checked-item_<%= "#{item.id}"%>').removeClass("delete-text"); 39 } 40}); 41</script>

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

javascrpt

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

items_controller.rb

ruby

1 def toggle 2 render nothing: true 3 @item = Item.find(params[:id]) 4 @item.check = !@item.check 5 @item.save 6 end

試したこと

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

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

urbainleverrier

2019/04/07 06:56

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

2019/04/07 07:02

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

2019/04/07 07:24 編集

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

2019/04/07 15:06 編集

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

2019/04/07 21:00

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

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

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

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

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の値に関係なしにチェックがついてしまっています。これも何か関係しているのではないかと推測しています。
guest

回答2

0

toggle には専用のメソッドがありますでの @item.toggle!(:check) としてみた場合はどうでしょうか?

投稿2019/04/18 09:26

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Romay

2019/04/18 21:11

回答いただきありがとうございます。Rails.envで本番環境と開発環境で分けたところうまくいきました。
guest

0

自己解決

本番環境と開発環境で動作を分けたところうまくいきました。

item_controller.rb

ruby

1if Rails.env.production? 2 if @item.check == 0 3 @item.check = 1 4 else 5 @item.check = 0 6 end 7 @item.save! 8else 9 @item.check = !@item.check 10 @item.save! 11end

投稿2019/04/18 21:13

Romay

総合スコア40

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問