Railsでajaxを使ったupdate処理を実装したい
解決済
回答 2
投稿
- 評価
- クリップ 0
- VIEW 3,003
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')) %> ");
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
まず、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メソッドを書き換えておけばよいでしょう。
def update
status = Relationship.find_by(params[:follow_id])
status.update(:status => 'allow')
@followers = @current_user.followers # @current_userはbefore_filterとかで設定済みと想定
@follower_relationships = @current_user.follower_relationships
end
ただ、これだと、折角Ajaxで呼び出しているうまみがありません。
ループで回しているところを全て取得し直して、該当部分を全て書き換えている訳ですから、通常のページ遷移と変わりないのではないかと思います。
Ajaxを使ってやるのであれば、変更した部分だけを変えてあげる方が良いでしょう。
# 大前提として、before_filter等でログイン中のユーザーが@current_userに格納されているとする
# information.html.erb
<div id="information">
<% @current_user.follower_relationships.each do |follower_relationship| %>
<% unless follower_relationship.status == 'allow' %>
<%= render partial: 'relationship_submit', locals: {follower_relationship: follower_relationship %>
<% end %>
<% end %>
</div>
# _relationship_submit.html.erb
<div id="relationship<%= follower_relationship.id %>">
<p>
<%= "#{follower_relationship.follow.first_kana}さんが友達申請をしてきました。" %><br />
<%= "友達申請を承認しますか?" %>
</p>
<%= link_to "承認", {controller: :relationships, action: :update, id: follower_relationship.id }, method: :post, remote: true %>
</div>
# RelationshipController
def update
@follwer_relationship = Relationship.find(params[:id])
@succeed = false
if @follower_relationship.update(status: 'allow')
@succeed = true
end
end
# update.js.erb
<% if @succeed %>
$("#relationship<%= @follower_relationsip.id %>").remove();
<% else %>
// 失敗したアラート見せる処理
<% end %>
概要としては、
承認のところでralationshipの全データをhiddenで送信するのは無駄なので、link_toでidだけを送信
updateメソッドで対象となるrelationshipだけを取得、ステータスは固定なのでそれで更新。
js.erbでは、対象となる”承認”の周辺を削除しているだけなので、対象のdivブロックを削除。
とまあ、こんなところでしょうか。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
render: :jsonの行を削除してあげれば、自動的にupdate.js.erbがレンダリングされます。
(そもそも何でJSONでレンダリングしたんでしょう?)
あと、提示されたコードでは、@followersが生成されていないので、ビューのレンダリングでエラーになります。
それから、@statusって、どこで使ってます?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 89.99%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/03/30 01: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は設定してあるのですが、
なぜエラーが発生してしまうのでしょか(^^;)??
2016/03/30 02: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
```
2016/03/30 02:33
2016/03/30 09:10
rifuchさんのおかげで無事実装することができました!
本当にありがとうございます!!
今後同じような機能を実装することになった際は、
自分でできるよう頑張ります(^。^)
本当にありがとうございました(^。^)!!