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

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

ただいまの
回答率

90.49%

  • Ruby on Rails 4

    2455questions

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

  • Ajax

    1113questions

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

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,813

NaojirouHisada

score 52

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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

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ブロックを削除。

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 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

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

    キャンセル

  • 2016/03/30 09:10

    コメントありがとうございます。
    rifuchさんのおかげで無事実装することができました!

    本当にありがとうございます!!

    今後同じような機能を実装することになった際は、
    自分でできるよう頑張ります(^。^)

    本当にありがとうございました(^。^)!!

    キャンセル

+1

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/29 20: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には使っていません(^^;)

    キャンセル

  • 2016/03/29 21:32 編集

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

    キャンセル

  • 2016/03/29 22:06

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

    キャンセル

  • 2016/03/29 22:25

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

    キャンセル

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

  • ただいまの回答率 90.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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

  • Ruby on Rails 4

    2455questions

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

  • Ajax

    1113questions

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