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

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

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

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

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

2回答

6150閲覧

Railsでajaxを使ったupdate処理を実装したい

NaojirouHisada

総合スコア60

Ruby on Rails 4

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

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2016/03/28 13:13

Facebookのようなアプリを作成しており、
現在友達申請->友達申請待ち->お知らせに「友達承認/拒否」を表示
https://gyazo.com/d7f017add647dc208b9a9b8184b835d0
->承認or拒否を押す->お知らせページの申請部分だけを更新して表示を無くすようにしようとしています。
https://gyazo.com/cffea1831decd6ebe0a0c95e80ccd8a8

そのため、
友達管理を行うrelationshisテーブルに、
友達申請のステータスのためのstatusを作成し、
status = 'allow' =>友達というようにしています。

友達申請->友達申請待ち->お知らせに「友達承認/拒否」を表示
https://gyazo.com/d7f017add647dc208b9a9b8184b835d0
->承認or拒否を押す
までの部分は実装できたのですが、
お知らせページの申請部分だけを更新して表示を無くすところができません。

どのように実装すればよろしいのでしょうか??

ソースコードを載せますので、
お手数おかけしますがアドバイス宜しくお願いします。

relationshipsテーブル class CreateRelationships < ActiveRecord::Migration def change create_table :relationships do |t| t.references :follow, index: true t.references :followed, index: true t.string :status t.timestamps null: false t.index [:follow_id , :followed_id] , unique: true end end end
relationshipモデル class Relationship < ActiveRecord::Base belongs_to :follow , class_name: "User" belongs_to :followed , class_name: "User" end ユーザーモデル。 class User < ActiveRecord::Base has_one :member has_many :microposts has_many :comments has_many :following_relationships, class_name: "Relationship" , foreign_key: "follow_id" , dependent: :destroy has_many :following_users , through: :following_relationships , source: :followed has_many :follower_relationships, class_name: "Relationship" , foreign_key: "followed_id",dependent: :destroy has_many :follower_users, through: :follower_relationships , source: :follow has_secure_password accepts_nested_attributes_for :member # 他のユーザーをフォローする def follow(other_user ,status) following_relationships.create(followed_id: other_user.id , status: status.status) end # フォローしているユーザーをアンフォローする def unfollow(other_user) if following_relationships.exists?(:followed_id => other_user.id) following_relationships.find_by(:followed_id => other_user.id).destroy else follower_relationships.find_by(follow_id: other_user.id).destroy end end # あるユーザーをフォローしているかどうか def following?(other_user) following_users.include?(other_user) end # あるユーザーにフォローされているかどうか def follower?(other_user) follower_users.include?(other_user) end end
友達申請をされたことを知らせるinfomation.html.erb <div id="information" > <%= render 'follow_update' %> </div>
友達を承認させるための更新処理を行う_follow_update.html.erb <% followers = @followers.to_enum follower_relationships = @follower_relationships.to_enum %> <% loop do follower = followers.next follower_relationship = follower_relationships.next %> <% if follower_relationship.status == 'allow' %> <% else %> <hr > <p><%= follower.first_kana + "さんが友達申請をしてきました。" %><br /> <%= "友達申請を承認しますか?" %></p> <%= form_for(follower_relationship,:url =>{ :controller => "relationships" , :action => "update", :id => "#{follower_relationship.id}" }, remote: true) do |f| %> <%= p follower_relationship.follow_id %> <%= hidden_field_tag :follow_id , follower_relationship.follow_id %> <%=f.hidden_field :status %> <%= f.submit "承認"%> <hr > <% end %> <% end %> <% end %>
この更新を行うrelationshipコントローラのupdateメソッド def update @status = Relationship.find_by(params[:follow_id]) if @status.update(:status => 'allow') render json: @status else flash[:danger] = 'missing' end end
ajax操作を行うための記述のupdate.js.erb $("#information").html("<%= escape_javascript(render ('users/follow_update')) %> ");

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

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

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

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

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

guest

回答2

0

ベストアンサー

まず、render :jsonするのは、Ajaxの呼び出し元がJavascript等で、レスポンスをJavascriptで受け取って処理するときや、API処理するときに使うもので、レスポンスの内容は、JSON書式のテキストデータになります。
という事は、ビューに配置された.js.erbや.html.erbは呼び出されないという事です。
ですから、RelationshipControlerのupdateメソッドのrender: :jsonの行を削除する必要がある訳です。

あなたのコードのupdate.js.erbの中では、_follower_update.html.erbがレンダリングされています。
_follower_update.html.erbの内部では@followersと@follower_relationshipsが参照されていますが、
updateメソッドで@followersと@follower_relationshipsが生成されていないため、このままではnilに対してメソッドをコールするので、たいていの場合エラーが起きます。
あなたのコードで最低限エラーが起きないようにするには、以下のようにRelationshipControllerのupdateメソッドを書き換えておけばよいでしょう。

Ruby

1 def update 2 status = Relationship.find_by(params[:follow_id]) 3 status.update(:status => 'allow') 4 @followers = @current_user.followers # @current_userはbefore_filterとかで設定済みと想定 5 @follower_relationships = @current_user.follower_relationships 6end

ただ、これだと、折角Ajaxで呼び出しているうまみがありません。
ループで回しているところを全て取得し直して、該当部分を全て書き換えている訳ですから、通常のページ遷移と変わりないのではないかと思います。
Ajaxを使ってやるのであれば、変更した部分だけを変えてあげる方が良いでしょう。

Ruby

1# 大前提として、before_filter等でログイン中のユーザーが@current_userに格納されているとする 2# information.html.erb 3<div id="information"> 4 <% @current_user.follower_relationships.each do |follower_relationship| %> 5 <% unless follower_relationship.status == 'allow' %> 6 <%= render partial: 'relationship_submit', locals: {follower_relationship: follower_relationship %> 7 <% end %> 8 <% end %> 9</div>

Ruby

1# _relationship_submit.html.erb 2<div id="relationship<%= follower_relationship.id %>"> 3 <p> 4 <%= "#{follower_relationship.follow.first_kana}さんが友達申請をしてきました。" %><br /> 5 <%= "友達申請を承認しますか?" %> 6 </p> 7 <%= link_to "承認", {controller: :relationships, action: :update, id: follower_relationship.id }, method: :post, remote: true %> 8</div>

Ruby

1# RelationshipController 2 def update 3 @follwer_relationship = Relationship.find(params[:id]) 4 @succeed = false 5 if @follower_relationship.update(status: 'allow') 6 @succeed = true 7 end 8 end

Ruby

1# update.js.erb 2<% if @succeed %> 3 $("#relationship<%= @follower_relationsip.id %>").remove(); 4<% else %> 5 // 失敗したアラート見せる処理 6<% end %>

概要としては、
承認のところでralationshipの全データをhiddenで送信するのは無駄なので、link_toでidだけを送信
updateメソッドで対象となるrelationshipだけを取得、ステータスは固定なのでそれで更新。
js.erbでは、対象となる”承認”の周辺を削除しているだけなので、対象のdivブロックを削除。

とまあ、こんなところでしょうか。

投稿2016/03/29 13:24

rifuch

総合スコア1901

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

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

NaojirouHisada

2016/03/29 16:02

丁寧な解説本当に助かります(^^;) ここまでコードが少なくなるとは思いませんでした(^^;) 申し訳ないのですが、 友達申請しますか??までは問題なく実装できましたが、 ``` <%= link_to "承認", {controller: :relationships, action: :update, id: follower_relationship.id }, method: :post, remote: true %> </div> ``` を実装し、 承認を押してみますと、 ``` ActionController::RoutingError (No route matches [POST] "/relationships/15"): actionpack (4.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call' web-console (2.2.1) lib/web_console/middleware.rb:31:in `call' actionpack (4.2.1) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call' railties (4.2.1) lib/rails/rack/logger.rb:38:in `call_app' railties (4.2.1) lib/rails/rack/logger.rb:20:in `block in call' activesupport (4.2.1) lib/active_support/tagged_logging.rb:68:in `block in tagged' activesupport (4.2.1) lib/active_support/tagged_logging.rb:26:in `tagged' activesupport (4.2.1) lib/active_support/tagged_logging.rb:68:in `tagged' railties (4.2.1) lib/rails/rack/logger.rb:20:in `call' actionpack (4.2.1) lib/action_dispatch/middleware/request_id.rb:21:in `call' rack (1.6.4) lib/rack/methodoverride.rb:22:in `call' rack (1.6.4) lib/rack/runtime.rb:18:in `call' activesupport (4.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call' rack (1.6.4) lib/rack/lock.rb:17:in `call' actionpack (4.2.1) lib/action_dispatch/middleware/static.rb:113:in `call' rack (1.6.4) lib/rack/sendfile.rb:113:in `call' railties (4.2.1) lib/rails/engine.rb:518:in `call' railties (4.2.1) lib/rails/application.rb:164:in `call' rack (1.6.4) lib/rack/lock.rb:17:in `call' rack (1.6.4) lib/rack/content_length.rb:15:in `call' rack (1.6.4) lib/rack/handler/webrick.rb:88:in `service' /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/webrick/httpserver.rb:138:in `service' /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/webrick/httpserver.rb:94:in `run' /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/webrick/server.rb:294:in `block in start_thread' Rendered /usr/local/rvm/gems/ruby-2.2.1/gems/actionpack-4.2.1/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb (0.8ms) Rendered /usr/local/rvm/gems/ruby-2.2.1/gems/actionpack-4.2.1/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb (18.7ms) ``` のようなルーティングエラーが発生しました。 routesではきちんとupdateは設定してあるのですが、 なぜエラーが発生してしまうのでしょか(^^;)??
NaojirouHisada

2016/03/29 17:20

``` <%= link_to "承認", {controller: :relationships, action: :update, id: follower_relationship.id }, method: :post, remote: true %> ``` のmethod: :postの部分を method: :putにかえましたら、 <%= link_to "承認", {controller: :relationships, action: :update, id: follower_relationship.id }, method: :put, remote: true %> 正常に動作しました!! ですが、 putではだめなのでしょうか(^^;)?? これが、relationshipのrouteです。 ``` relationships POST /relationships(.:format) relationships#create edit_relationship GET /relationships/:id/edit(.:format) relationships#edit relationship PATCH /relationships/:id(.:format) relationships#update PUT /relationships/:id(.:format) relationships#update DELETE /relationships/:id(.:format) relationships#destroy ```
rifuch

2016/03/29 17:33

link_toのmethodオプションは、:postは間違いですね。updateなら:putが正しいです。
NaojirouHisada

2016/03/30 00:10

コメントありがとうございます。 rifuchさんのおかげで無事実装することができました! 本当にありがとうございます!! 今後同じような機能を実装することになった際は、 自分でできるよう頑張ります(^。^) 本当にありがとうございました(^。^)!!
guest

0

render: :jsonの行を削除してあげれば、自動的にupdate.js.erbがレンダリングされます。
(そもそも何でJSONでレンダリングしたんでしょう?)

あと、提示されたコードでは、@followersが生成されていないので、ビューのレンダリングでエラーになります。
それから、@statusって、どこで使ってます?

投稿2016/03/29 02:24

rifuch

総合スコア1901

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

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

NaojirouHisada

2016/03/29 11:09

render: :jsonの行を削除しますと、 ajaxの更新がされた際、 ``` Completed 500 Internal Server Error in 93ms (ActiveRecord: 0.9ms) ActionView::Template::Error (undefined method `each' for nil:NilClass): 4: 5: 6: <% loop do 7: follower = followers.next 8: follower_relationship = follower_relationships.next %> 9: 10: <% if follower_relationship.status == 'allow' %> app/views/users/_follow_update.html.erb:7:in `next' app/views/users/_follow_update.html.erb:7:in `block in _app_views_users__follow_update_html_erb__922133743095404908_69892989505320' app/views/users/_follow_update.html.erb:6:in `loop' app/views/users/_follow_update.html.erb:6:in `_app_views_users__follow_update_html_erb__922133743095404908_69892989505320' app/views/relationships/update.js.erb:1:in `_app_views_relationships_update_js_erb__3383092756043455873_69893008020780' Rendered /usr/local/rvm/gems/ruby-2.2.1/gems/actionpack-4.2.1/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb (1.5ms) Rendered /usr/local/rvm/gems/ruby-2.2.1/gems/actionpack-4.2.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb (1.3ms) Rendered /usr/local/rvm/gems/ruby-2.2.1/gems/actionpack-4.2.1/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb (54.7ms) ``` というエラーが出たので、追加しました。 そうなのですか、、、(^^;) ご迷惑をおかけして申し訳ないのですが、 どのようにすれば、生成されるのでしょうか(^^;)?? @stausは、エラーを無くすために記述しただけで、 viewには使っていません(^^;)
rifuch

2016/03/29 12:36 編集

@followersが生成されていないせいで、update.js.erbの中でrenderしている_follow_update.html.erがエラーを吐いています。 解説が長くなりそうなので、別回答で続きを答えます
NaojirouHisada

2016/03/29 13:06

ありがとうございます。 つきましては、 同じ内容で新しい質問を作成した方がよろしいでしょうか??
rifuch

2016/03/29 13:25

別回答の方を投稿しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問