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

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回答

1859閲覧

いいねしてない方のいいねの表示が切り替わります

s.k

総合スコア423

Ruby on Rails 4

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

Ajax

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

0グッド

2クリップ

投稿2016/10/24 13:44

編集2016/10/24 15:29

###前提・実現したいこと
クリックしたいいねリンクをajaxでいいねを取り消すへ切り替えたい。

【元の状態】

test2の投稿のいいねをクリック

このようにクリックしたリンクがajaxにより切り替わるようにしたいです。

###発生している問題・エラーメッセージ

小泉(Userモデル)というユーザーがtest1とtest2という投稿をしており、
Shop(Shopモデル)というユーザーが小泉のtest2の投稿にいいねをする場合です。(私は小泉という苗字ではないんですが!)

test2投稿のいいねを押すと
test1の投稿のajaxが作動します。。。↓

データの流れる順番にコードを書いていきます。

①いいねを押す
【micropost.html.erb】(いいねのリンクが貼ってあるファイル)

<% if shop_signed_in? %> <div id="sympathizes_ajax"> <%= render 'sympathizes/sympathize_links', micropost: micropost %> </div> <% end %>

↓①いいねを押す
【sympathizes/_sympathize_links.html.erb】

<% if micropost.sympathized_by? current_shop %> <%= link_to 'いいね!を取り消す', micropost_sympathizes_path(micropost.id), method: :delete, remote: true %> <% else %> <%= link_to 'いいね!', micropost_sympathizes_path(micropost.id), method: :post, remote: true %> <% end %>

↓②createアクションへ
【sympathizes.controller.rb】

def create @micropost = Micropost.find(params[:micropost_id]) @sympathize = current_shop.sympathizes.build(micropost: @micropost) @sympathize.save end def destroy @micropost = Micropost.find(params[:micropost_id]) @sympathize = current_shop.sympathizes.find_by!(micropost_id: params[:micropost_id]) @sympathize.destroy end

@sympathizeにデータが入り保存される。

③ここで、create.jsファイルが起動!
【sympathizes/create.js.erb】

$('#sympathizes_ajax').html('<%= escape_javascript(render("sympathizes/sympathize_links", micropost: @micropost)) %>');


ここで、いいね→いいねを取り消すとなります。
④もう一度クリックすると

【sympathizes/destroy.js.erb】

$('#sympathizes_ajax').html('<%= escape_javascript(render("sympathizes/sympathize_links", micropost: @micropost)) %>');


いいねを取り消す→いいねに切り替わります。

これかな?と思った原因を一応書きます
(ここから違っていればガンガンご指摘お願いします。)

・createもしくはdestroyファイルのデータの送信先が指定されていないために、
下のいいねをクリックすると上のいいねにデータが送られてしまう。(上のいいねはクリックするといいねを取り消すに切り替わります。下のいいねの表示は切り替わりません。)

ですので、createとdestroyのデータ送信先を区別できるような方法をとればいいのか。。。?
と思ったのですが、まったく想像がつかずご相談にあがりました。。。

ユーザーの関連づけコードも載せておきます。

【shop.rb】

#sympathizes(shop-to-micropost.user) has_many :microposts, dependent: :destroy has_many :sympathizes, dependent: :destroy has_many :sympathize_microposts, through: :sympathizes, source: :micropost

【micropost.rb】

#sympathizes(shop-to-micropost.user) has_many :sympathizes, dependent: :destroy has_many :sympathize_users, through: :sympathizes, source: :shop belongs_to :shop

【sympathize.rb】

belongs_to :shop belongs_to :micropost validates :shop, presence: true validates :shop_id, uniqueness: { scope: :micropost_id } validates :micropost, presence: true

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2016/10/24 13:53

そもそも html の id属性はユニークでなくてはいけない。 
cameluby

2016/10/24 13:57 編集

投稿1と投稿2の関連性はどうなっているのでしょうか? すいません、ちょっと問題が読み取れませんでした。。。
s.k

2016/10/24 14:25

xa051さん タイトルですよね?修正しました。表現の仕方が間違っていました。ご指摘ありがとうございます!
s.k

2016/10/24 14:25

camelubyさん 情報を追加しました。こういうことでしょうか?
guest

回答2

0

できました!

①各リンクタグにidを指定
②idの値はmicropost(投稿)のidを代入
③create.destroyのjsファイルのセレクタにid値を代入

で行けました~
みなさん、ありがとうございます。
今回もたくさん勉強させていただきました。

【sympathizes/_sympathize_links.html.erb】

<div id="sympathizes_ajax">←削除 <% if micropost.sympathized_by? current_shop %> <%= link_to 'いいね!を取り消す', micropost_sympathizes_path(micropost.id), method: :delete, :id => "#{micropost.id}", remote: true %>← :id => "#{micropost.id}"をリンク内に追加 <% else %> <%= link_to 'いいね!', micropost_sympathizes_path(micropost.id), method: :post, :id => "#{micropost.id}", remote: true %>← :id => "#{micropost.id}"をリンク内に追加 <% end %> </div>←削除

【sympathizes/create.js.erb】

$('#<%= @micropost.id %>').html('<%= escape_javascript(render("sympathizes/sympathize_links", micropost: @micropost)) %>');←$()内をsympathizes_ajax→@micropost.idに変更

【sympathizes/destroy.js.erb】

$('#<%= @micropost.id %>').html('<%= escape_javascript(render("sympathizes/sympathize_links", micropost: @micropost)) %>');←$()内をsympathizes_ajax→@micropost.idに変更

参考記事
Railsでcreate.js.erbが動かない為、どこに問題があるか知りたい

投稿2016/10/25 04:08

編集2016/10/25 04:10
s.k

総合スコア423

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

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

0

ベストアンサー

micropost.html.erb が

erb

1<% if shop_signed_in? %> 2 <div id="sympathizes_ajax"> 3<%= render 'sympathizes/sympathize_links', micropost: micropost %> 4 </div> 5<% end %>

となっているので、たとえば投稿が3件あるページを表示させるとHTMLは

html

1test1 2<div id="sympathizes_ajax"> 3 <a>'いいね!</a> 4</div> 5 6test2 7<div id="sympathizes_ajax"> 8 <a>'いいね!</a> 9</div> 10 11test3 12<div id="sympathizes_ajax"> 13 <a>'いいね!</a> 14</div>

さてここで、あなたが「#sympathizes_ajax のリンクを いいね!を取り消す に書き換えて!!!」と言われたら、何番目を書き換えますか???

js.erbは $('#sympathizes_ajax') となっていて何番目という指定もなく #sympathizes_ajax は3つある。という状態なので jQuery さんは困ってしまって、何も仕事しないのも悪いし。。と。。。くるしまぎれに一番最初を書き換えてるんじゃないかなぁと思います。


コメント欄が違う方向で盛り上ってますねww

では、hana-daさんが指摘してくださった問題を解決するためには
idを指定した配列では不可能ということでしょうか?

何か対策を取りたいです。
・idにランダムな文字列を返す変数を代入する
以外に思いつかないのですが、おそらくidの値を変えたとしても問題は解決されないですよね。。。

(なんか色々、用語の使い方がおかしいような気もしますが。。。そこはスルーして。。。)

id属性の値をちゃんと一意なものにしてあげて、それをjavascriptで操作対象にしてあげればいいと思います。

ちょっと時間がないので検証してないコードを書いちゃいますが

まず micropost.html.erb

erb

1<% if shop_signed_in? %> 2 <div id="sympathizes_ajax_<%= micropost.id %>"> 3<%= render 'sympathizes/sympathize_links', micropost: micropost %> 4 </div> 5<% end %>

id属性の値に micropost.id をつけてあげる事で一意にする。

sympathizes/_sympathize_links.html.erb

erb

1<% if micropost.sympathized_by? current_shop %> 2 <%= link_to 'いいね!を取り消す', micropost_sympathizes_path(micropost.id), method: :delete, remote: true %> 3<% else %> 4 <%= link_to 'いいね!', micropost_sympathizes_path(micropost.id), method: :post, remote: true %> 5<% end %>

ここでは、ちゃんと micropost.id を送信しているので問題なし

sympathizes/xxx.js.erb*

javascript

1$('#sympathizes_ajax_<%= @micropost.id %>').html.........

操作対象を micropost.html.erb の変更に合せてあげる。

で、どうですかね?

投稿2016/10/24 23:39

編集2016/10/25 04:12
hana-da

総合スコア1728

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

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

退会済みユーザー

退会済みユーザー

2016/10/24 23:53

苦し紛れでもなくRFCに乗っ取った仕様です。
hana-da

2016/10/25 00:06

わかりやすくお伝えしたかっただけです。。。ごめんなさい。
hana-da

2016/10/25 00:07

RFCだっけ?? まぁいいか。。。
退会済みユーザー

退会済みユーザー

2016/10/25 00:20

ああ一般的には W3C のほうが有名だった><
kopio

2016/10/25 00:43

後学のために仕様が定義されている場所を教えてください。 jqueryの実装によると思うので、RFCではないような気がします。 投げっぱなしも何なので、自分が調べた範囲を載せておきますね。 RFCではRFC2854でhtmlのことはW3Cを参照しろという感じ。 https://tools.ietf.org/html/rfc2854 W3C HTML5では当然のようのIDは一意にしろとなっていますが、先頭オブジェクトを返す仕様とは関係なし。 https://www.w3.org/TR/2014/REC-html5-20141028/dom.html#the-id-attribute W3C DOMのgetElementById の仕様であれば、IDが重複した場合の動作は未定義。 https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-getElBId jquery のAPIドキュメントだと、ID重複時は最初に見つけたものを返すが、この動作は信用するな。そもそもIDが重複した文書は無効だ。 http://api.jquery.com/id-selector/
退会済みユーザー

退会済みユーザー

2016/10/25 00:53

場所はこちらの記憶違いだったが [W3C 日本語訳/H93: ウェブページのid属性値が一意的(ユニーク)であるようにする](http://waic.jp/docs/WCAG-TECHS/H93.html) とある以上 1番最初にでる項目=1番最後にある項目が成り立っているはずなので
s.k

2016/10/25 03:37

hana-daさん ありがとうございます! では、hana-daさんが指摘してくださった問題を解決するためには idを指定した配列では不可能ということでしょうか? 何か対策を取りたいです。 ・idにランダムな文字列を返す変数を代入する 以外に思いつかないのですが、おそらくidの値を変えたとしても問題は解決されないですよね。。。 micropost.html.erbの構造を変えないければならないと思ったのですが、わからなくて、、、
s.k

2016/10/25 04:41 編集

hana-daさん ありがとうございます! micropostのidなら重複を避けられるんですね! 編集してくださったコードですが、動きませんでした。。。 test1の投稿もtest2の投稿もいいねが切り替わらないという状態です。。。 一応、変数や表記をいろいろ試してみたのですが、、、 それと、自己解決方法書きました! micropost.idをidに代入して<%= link_to ....%>内に仕込む方法を試してみました!
s.k

2016/10/25 06:16

ありがとうございましたー!!!!! 本当に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問