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

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

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

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

Ruby on Rails

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

1回答

8241閲覧

rails4 再読み込み(リロード)するとうまくいくのですが...

takyas

総合スコア54

Ruby

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

Ruby on Rails

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

1クリップ

投稿2016/03/07 15:25

編集2016/03/08 14:38

###Rails4のeach、form_for関連でハマっております。
開発環境
Ruby 2.3
Rails 4.2.5

教えていただきたい箇所は以下です。
Userモデル、Skillモデル、UserSkillモデルがあり、UserのMyPage内でAjaxを使ったSkillの新規登録・編集・削除がしたいです。
今現時点では、新規登録・削除は実装できているのですが、編集の「更新」の部分でハマっております。
1回、「更新」ボタンをクリックしても何も反応しないのですが、リロードして「更新」クリックを押すときちんと更新がされます。
素人が故にどのような情報をこちらに記載すれば、閲覧者様の解決のお力になるのか理解していないので、追加で必要な情報がございましたら、ご教示いただけますと幸いです。

(Ajaxの部分の追加)
Ajaxの部分は、eachで回したskillのリストの中で、「編集」ボタンが押されたリストの行のみを「編集可能」にするというものです。
「submit」はAjax化しておりません。
説明不足で申し訳ございません。

skillリスト
編集ボタンクリック後
devtool
ルーティング

Userskillカラム
id,user_id,skill_id,level,detail

User has_many :skills
User has_many :user_skills
Skill has_many :users
Skill has_many :user_skills
Userskill belongs_to :user
Userskill belongs_to :skill

users/show.html(Mypage内)

<div id="user_skill"> <%= render partial: "skill", locals: {user: @user} %> </div>

users/_skill.html.erb

<table class="table table-striped"> <thead> <tr> <th>No.</th> <th>スキル</th> <th>レベル</th> <th>詳細</th> <th>編集</th> <th>削除</th> </tr> </thead> <tbody> <% @user.user_skills.each_with_index do |userskill, i| %> <tr class="skill_list_<%= i+1 %>"> <%= render partial: "skill_list", locals: {i: i, userskill: userskill} %> </tr> <% end %> </tbody> </table>

users/_skill_list.html.erb

<td><%= i+1 %></td> <td><%= userskill.skill_id %></td> <td><%= userskill.level %></td> <td><%= userskill.detail %></td> <td><%= link_to '編集', edit_skill_path(userskill, list_num: i+1, uid: current_user.id), remote: true %></td> <td><%= link_to '削除', edit_destroy_skill_path(userskill), method: :delete %></td>

users/edit_skill.js.erb

$('.skill_list_<%= @list_num %>').html('<%=j render partial: "edit_skill_form", locals: {userskill: @userskill, list_num: @list_num} %>');

users/_edit_skill_form.html.erb

<%= form_for(userskill, url: userskill_path(userskill)) do |f| %> <td><%= list_num %></td> <td><%= f.select :skill_id, { :html5 => "1", :css3 => "2"} %></td> <td><%= f.select :level, { :初心者 => "1", :経験者 => "2", :プロ => "3"} %></td> <td><%= f.text_area :detail %></td> <td> <%= f.submit "更新" %> </td> <td> <%= link_to '戻る', user_path(current_user.id) %> </td> <% end %>

UserskillsController

class UserskillsController < ApplicationController before_action :set_skill, only: [:update] def update respond_to do |format| if @userskill.update(userskill_params) format.html { redirect_to root_path, notice: 'UserSkill was successfully updated.' } end end end private def set_skill @userskill = UserSkill.find(params[:id]) end def userskill_params params.require(:user_skill).permit(:id, :skill_id, :level, :detail) end end

routes.rb

resources :userskills

質問の方法等で不足があればご教示下さい。
「このへんどうなってんの?」等もどんどんご連絡下さい。
宜しくお願い致しますm(_ _)m

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2016/03/07 15:42

おそらくバグの原因は JavaScript なので、JavaScript のコードがないとなんとも言えないですね
takyas

2016/03/07 16:07

yamagen様 コメントありがとうございます。 javascript部分のコードとご説明、図を追加致しました。 お時間のある時で結構ですので、お知恵をお貸しいただけますと幸いです。
guest

回答1

0

ベストアンサー

サブミット部分をjsのリクエストに変えているという理解でよろしいでしょうか?

ajaxの実装部分が解っていないので推測で書きますが、updateアクションのルーティングされたURLにPUTメソッドでリクエストを行った時にレスポンスが返って来るようにコントローラー側(もしくはルーティング側のフォーマット指定)で設定が必要です。このときformatがhtmlに引っかからず,リダイレクトがかかっていないためサーバ上では更新されているが,リダイレクトがかかっていないため,クライアント側で更新されないという現象が起こっているように思います。

完璧なajaxで実装する場合はフォームに反映させたいレスポンスをコントローラー側で記述し,js側で受け取り,レスポンスをフォームに反映させる処理を書かなければいけません。

追記

追記ありがとうございます。だいぶ見通しが良くなりました。railsの機能でajaxを行いたいなら以下のような例を挙げます。ただ直す方法は沢山あり,これは一例にすぎないこと,エラーチェックをこちらからはできないのでこのコードでも動作が上手くいかない可能性もあるので,どういう方針で直すのか参考程度のものと思っていただければと思います。パラメータの意味などは適宣調べてもらえると助かります。変更を加えた行にはコメントをつけました。

erb

1#_edit_skill_form.html.erb 2<%= form_for(userskill, url: userskill_path(userskill),{remote:true,method:PUT}) do |f| %> #処理をAjaxにPUTメソッドを明示的に 3 <%= f.hidden_field :list_num, :value => list_num % > #list_numでどの行のUserSkillを変えたか識別する 4 <td><%= list_num %></td> 5 <td><%= f.select :skill_id, { :html5 => "1", :css3 => "2"} %></td> 6 <td><%= f.select :level, { :初心者 => "1", :経験者 => "2", :プロ => "3"} %></td> 7 <td><%= f.text_area :detail %></td> 8 <td> 9 <%= f.submit "更新" %> 10 </td> 11 <td> 12 <%= link_to '戻る', user_path(current_user.id) %> 13 </td> 14<% end %> 15 16#file追加 17Userskill/update.js.erb 18 19$('.skill_list_<%= @list_num %>').html('<%=j render partial: "skill_list", locals: {userskill: @userskill, list_num: @list_num} %>'); #Ajaxコード 20 21

ruby

1#UserskillsController.rb 2 3def update 4 respond_to do |format| 5 if @userskill.update(userskill_params) 6 format.html { redirect_to root_path, notice: 'UserSkill was successfully updated.' } 7 format.js #アクションと同名の.js.erbコードのレンダリング 8 end 9 end 10 end 11 12def set_skill 13 @userskill = UserSkill.find(params[:id]) 14 @list_num = params[:list_num] if params.key?(:list_num) #リストの何番目からのリクエストか記憶 15end 16 17

エラーなどが出てしまった場合は引数などが変わっているところを参考に,適宣修正してください。方針としてはajaxで書き換えたDOMをupdateメソッドの実行後に違うajaxコードを読み込んで元に戻すという方法です。
Userskill/update.js.erbのフォルダ位置が気持ち悪い場合は(hogeは任意の名前),Users/hoge.js.erbを作成し,UserskillsController.rbでのrender: {template: users/hoge.js.erb}を使って参照先を変更して@list_numの受入先を修正してください。

画面遷移を許すのであれば,

ruby

1 2#_edit_skill_form.html.erb 3<%= form_for(userskill, url: userskill_path(userskill),{method:PUT}) do |f| %>#ajaxではなくredirectで更新する。PUTメソッドを明示的に 4 <%= f.hidden_field :list_num, :value => list_num % > #list_numでどの行のUserSkillを変えたか識別する 5 <td><%= list_num %></td> 6 <td><%= f.select :skill_id, { :html5 => "1", :css3 => "2"} %></td> 7 <td><%= f.select :level, { :初心者 => "1", :経験者 => "2", :プロ => "3"} %></td> 8 <td><%= f.text_area :detail %></td> 9 <td> 10 <%= f.submit "更新" %> 11 </td> 12 <td> 13 <%= link_to '戻る', user_path(current_user.id) %> 14 </td> 15<% end %> 16

ruby

1#UserskillsController.rb 2 3def update 4 respond_to do |format| 5 if @userskill.update(userskill_params) 6 format.html { redirect_to root_path, notice: 'UserSkill was successfully updated.' } 7 format.js { redirect_to root_path, notice: 'UserSkill was successfully updated.' } #js formatの時に処理が定義されていないのが原因であればリダイレクトする事で直るかも 8 end 9 end 10 end 11 12def set_skill 13 @userskill = UserSkill.find(params[:id]) 14 @list_num = params[:list_num] if params.key?(:list_num) #render用にlist_numを記憶 15end 16 17

とやればリダイレクトで更新かけれると思います。

ただ現在のコードを見ると,フォームのメソッドがデフォルトのPOSTになっている気がしていて,updateアクションが呼ばれず,正常に更新できないように思えるので,更新されるという事に違和感があって,直接的なバグの原因がちょっと直感的に分かり兼ねています。PUTでリクエストすべきアクションがPOSTになっていた(これだとupdateメソッド自体呼ばれないはず),formatがjsでリクエストされた時の動作を返していない(format.htmlは記憶違いでなければ該当フォーマットがない時にもhtml返すんじゃなかったっけ?)事くらいかなと予測しています。(が,あまり釈然としていません)。
もしかすると他の要因も絡んでいるかもしれないので,binding.pryなどを使ってupdateにリクエストが飛んでいるか。formatが正しいかsaveメソッドは成功しているか,指定されたHTTPメソッドは正しいかなど調べてみてください。

ruby

1#UserskillsController.rb 2 3def update 4 respond_to do |format| 5     binding.pry #break point 6 if @userskill.update(userskill_params) 7     binding.pry #break point 8 format.html { redirect_to root_path, notice: 'UserSkill was successfully updated.' } 9 end 10 end 11 end 12 13def set_skill 14 @userskill = UserSkill.find(params[:id]) 15 @list_num = params[:list_num] if params.key?(:list_num) 16end 17 18

など上記のようにブレイクポイントを貼って変数の中身やちゃんとupdateが呼ばれているかなどを調べてみてください。

投稿2016/03/07 15:56

編集2016/03/07 19:31
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

takyas

2016/03/07 16:13

tkow様 コメントありがとうございます。 また、説明不足で申し訳御座いません。 今回Ajaxの部分は、submitではなく「編集」ボタンのlink_toの部分でございます。 ``` updateアクションのルーティングされたURLにPUTメソッドでリクエストを行った時にレスポンスが返って来るようにコントローラー側(もしくはルーティング側のフォーマット指定)で設定が必要です。このときformatがhtmlに引っかからず,リダイレクトがかかっていないためサーバ上では更新されているが,リダイレクトがかかっていないため,クライアント側で更新されないという現象が起こっているように思います。 ``` 正直申し上げてこのご助言いただきました箇所の理解が浅いので、キーワードを拾ってググってみます。 また、javascriptのコード・ご説明、図を追加致しましたので、ご確認いただき、新たにお気付きの点がございましたら、ご助言いただけますと幸いです。
takyas

2016/03/08 14:36 編集

tkow様 再コメント(コメントのレベルではなく、解説・リファクタリングのレベルですが)本当にありがとうございます! まだ、ご教示いただきましたアドバイスを参考にしての実装には取り掛かれてはいないのですが、このコメントを投稿後取り掛かります!! また開発中でハマった時に、ここ(teratail)に投稿することもあるかと思いますが、その際は是非宜しくお願い致しますm(_ _)m 本当にありがとうございます! (追記) tkow様がおっしゃられています。 「ただ現在のコードを見ると〜」のPUTの部分に関しては、PUTではなくPATCHがhiddenで渡されており、そのルーティングでuserskills#updateが呼ばれているようです。 画像をUP致します。
退会済みユーザー

退会済みユーザー

2016/03/08 15:08

そう言えばrailsはedit _formだとデフォルトPATCHで実行してくれるとかあるんでしたっけ。 であればupdateメソッドがtrueになってるか。なっていれば正しくレスポンスが返せてるか、リダイレクト出来てるかあたりを調べれば原因が特定出来ると思います。webrickの出力ログなんかも参考になると思います。頑張って下さい。
takyas

2016/03/09 11:08

tkow様 コメントありがとうございます。 アドバイス頂きました内容を参考にさせていただき、原因を追求したところ、解決まではいっていないのですが、解決の糸口の部分までは見えてきました。 このエントリの内容とは違った部分に原因がありそうです。 今一度エントリする予定ですので、お時間に余裕がございましたら、チラ見していただけますと幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問