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

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

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

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

Ruby on Rails

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

Ajax

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

Q&A

解決済

3回答

1215閲覧

そのurl名はすでに取得されていますのAjax。Railsでのjsonの返し方

Romay

総合スコア40

Ruby

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

Ruby on Rails

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

Ajax

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

0グッド

2クリップ

投稿2019/04/26 22:14

編集2019/05/04 02:02

前提・実現したいこと

Ruby 2.4.5
Rails 4.2.8
本番環境:heroku postgreSQL
開発環境:mySQL

ユーザーが設定画面でオリジナルのfriendly_url(Twitterの@以下のような一意制約)を設定した時に、すでに取得済みの場合、アラートを出す処理を実装しています。

Ajaxで入力値をPOSTし、その値がすでに DBにあるかどうかで条件分岐しています。
コントローラーでのJSONの処理などがうまくできておらず、困っております。

  1. users/edit.html.erbでユーザーが入力
  2. AjaxでPOST送信
  3. Userコントローラーのcheckアクションに飛ぶ
  4. checkアクションでDB検索、ここでjsonを返す

friendly_urlは、userテーブルの1カラムとして存在しています。
そのため、userモデルを通じてDB検索をしています。

該当のソースコード

users/edit.html.erb

javascript

1 2//フォーム該当部 3<li> URL (3~20文字英数字)<%= f.text_field :friendly_url,:required => true %></li> 4 5// friendly_urlのバリデーションチェック 6$(function(){ 7 $('#user_friendly_url').on('blur',function(){ 8 $(this).next('span.error').remove(); 9 $(this).removeClass('input_error'); 10 let f_url = $(this).val(); 11 if(f_url == ""){ 12 $(this).addClass('input_error'); 13 $(this).after('<span class="error">必ず入力してください</span>'); 14 $(this).focus(); 15 return; 16 } 17//ここまでは問題なさそう。以下が問題あり。 18 $.ajax({ 19 type:'POST', 20 url:'/users/check', //ここのurlはコントローラーに飛ばすため? 21 data:{url:f_url}, 22 dataType:'json', 23 }).done(function(data, status, xhr) { 24 if(status === "success"){ 25 if(data.isduplicated){ 26 $('#user_friendly_url').addClass('input_error'); 27 $('#user_friendly_url').after('<span class="error">既に利用されています</span>'); 28 $('#user_friendly_url').focus(); 29 } 30 } 31 }).fail(function(xhr, status, error) { 32 console.log(xhr); 33 }); 34 }); 35 }); 36

Routes.rb

ruby

1post '/users/check' => 'users#check' 2#このルーティングは必要?

user_controller

ruby

1 def check 2 @users = User.where('friendly_url LIKE(?)', "#{params[:url]}") 3 #paramsとして送られてきたurlで、Userモデルのfriendly_urlカラムを検索し、その結果をどうすればいい...? 4 respond_to do |format| 5 format.json { render 'edit', json: @users } 6 #json形式のデータを受け取ったら、@usersをデータとして返す? 7 end 8 end

DB検索して、DBに存在するかどうかを調べるので@usersは返す必要がないと思いますが、ここをどうすればいいのかわからずにいます。

試したこと

補足情報(FW/ツールのバージョンなど)

こちらでの質問内容に関連しています。
以前の質問

--5月3日 補足--

以下のようにUserコントローラーを編集し、ユーザー入力値でDB検索したとき、friendly_urlが存在する場合は、「isdupricated_true」存在しない場合は「isdupricated_false」がコンソール上で出力されているのが確認できました。

しかしやりたいことは、isdupricatedというキーにtrueとfalseを設定して返すことなので、これでは不十分です。
いくつか回答いただいたなかでモジュール変換というのがこれに当たるのでしょうか...。
かなり調べてみたのですが、format.json の1行に関して参考にできるものが見つからず。。。

user_controller

ruby

1 def check 2 if User.where('friendly_url LIKE(?)', "#{params[:url]}").exists? 3 #paramsとして送られてきたurlで、Userモデルのfriendly_urlカラムを検索し場合分け 4 respond_to do |format| 5 format.json { render :json => :isdupricated_true} #存在する場合 6 #format.json { render :json => :isdupricated :true } エラー 7 #format.json { render :json => (:isdupricated :true) } エラー 8 end 9 else 10 respond_to do |format| 11 format.json { render :json => :isdupricated_false } #存在しない場合 12 end 13 end 14 end

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

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

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

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

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

siruku6

2019/05/02 06:06

> //ここのurlはコントローラーに飛ばすため? > このルーティングは必要? > json形式のデータを受け取ったら、@usersをデータとして返す? 上記3つの疑問については全てその通りです > paramsとして送られてきたurlで、Userモデルのfriendly_urlカラムを検索し、その結果をどうすればいい...? ここで何がしたいのかがはっきりしないのですが、 「既にfriendly_urlとして登録されているurlを検索したい」ということでいいのでしょうか? もしそうであれば、まずmodel側のvalidationでunique制約をつけておいた方がいいと思います。 あとは、「どこでどんなエラーが発生しているのか」を追記していただけるとより正確な回答が得られると思います。 --- それと個人的には、ここにconsole.log()を差し込んで、dataが正しく送られてきているかどうかを確認したいところです。 }).done(function(data, status, xhr) {  console.log(data)  if(status === "success"){ このdataの中には、いったいどんな形のデータが入っていてほしいのでしょうか? それも追記しておいた方がいいと思います。 (@user内のデータがすべて欲しいわけではありませんよね?)
Romay

2019/05/04 01:00

> paramsとして送られてきたurlで、Userモデルのfriendly_urlカラムを検索し、その結果をどうすればいい...? 入力値として送られてきたparams[:url]が既にfriendly_urlとして登録されているかどうかを検索したいです。つまり、「登録されているかどうか」なので@userの中身は必要ないのですが、どういう書き方が適切か分からないので質問のような形で書いています。 params[:url]というのが正しい書き方なのかも分かっていないのですが...。Userモデルにはunique制約をつけております。
guest

回答3

0

Ajaxで受けとるのは実行先プログラムからの「出力」です。
それがJSON形式のデータ(文字列)であれば良いので、配列やオブジェクトにしたのであればJSONエンコードした情報をprint文などで出力すれば良いと思います。

サーバーサイドからの返却値はisduplicatedというキーのbool値により判断されているようですからサーバーサイドからの返すJSONデータにもisduplicatedというキーにtrue/falseを設定してあげないとステータスsuccessで返ってもキーの未定義エラーが出ると思います。

投稿2019/04/27 01:06

m.ts10806

総合スコア80850

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

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

m.ts10806

2019/04/27 01:07

なお、前の質問にも書いたかもしれませんが私はRubyがかけるわけではないので、Rubyでの書き方は調べてください。 書き方が違うだけでロジック、考え方は同じというだけです。
Romay

2019/04/27 22:23

回答いただきありがとうございます。考え方としての全体像はmts10806さんが以前に教えていただいたおかげで理解できたのですが、RailsのDBとのやりとり部分をどう書くべきなのか分からずにいます。自分はRailsに関しても知識が浅いためこちらで質問させていただいておりました。
m.ts10806

2019/04/27 23:14

それはajax限らず、例えば入力フォームからの送信でのDB検索もわからない(または固定でのDB検索も)ということでしょうか? チュートリアルやサンプルコードはきちんとあるようには思いますが…
Romay

2019/05/01 22:41

DB検索自体は理解しているのですが、'jsonで返す'あたりの知識が薄く困っている状況です...。
m.ts10806

2019/05/02 01:00

ruby 配列 json 変換 で検索するとモジュールがでてきますのでそれで試してみては。 jsonもオブジェクトですが形式は連想配列のようなものです。(もとの由来はJavaScriptの連想配列ですね)
Romay

2019/05/06 22:08

連想配列についても曖昧だったので勉強になりました。ありがとうございます!
guest

0

ベストアンサー

  • 現状

render :json に Objectを渡すと次のような結果になるそうです。(私も初めて知りました。)
参考URL => JSONを返す

  • 提案

追記を読んで考えたのですが、こんな感じでいかがでしょう?

ruby

1 def check 2 if User.where('friendly_url LIKE(?)', "#{params[:url]}").exists? 3 respond_to do |format| 4 format.json { render json: { isdupricated: true } } #存在する場合 5 end 6 else 7 respond_to do |format| 8 format.json { render json: { isdupricated: false } } #存在しない場合 9 end 10 end 11 end

参考URL => Rails render :json => [1,2,3] behaving differently in production (json root)

  • 注意

1点注意して欲しいことがありまして、javascript と ruby では型の扱いが若干違ったような気がしています。
ruby から javascript にわたるときだったか、逆のときだったか忘れてしまったのですが、もしかしたら true や false が文字列として javascript にわたってしまうかもしれません。
そのときは適切に変換してあげて下さい。

追記

動いているのであればそれでよいと思います。
どうしてもきれいなコード書きたい、という場合はいろんな人のコードを見るのが参考になるので、あくまで参考までに私だったらどう修正するかを載せてみます。

ruby

1【user_controller】 2# Ver.1 (DRYにしてみた) 3def check 4 unless params[:url] == current_user.friendly_url 5 # INFO: is_duplicated <= true or false が代入される 6 # paramsとして送られてきたurlで、Userモデルのfriendly_urlカラムを検索 7 is_duplicated = User.where('friendly_url LIKE(?)', "#{params[:url]}").exists? 8 respond_to do |format| 9 format.json { render json: { isduplicated: is_duplicated }} 10 end 11 else 12 render nothing: true #何もしない動作 13 end 14end 15 16# Ver.2 (好みの問題) 17def check 18 if params[:url] == current_user.friendly_url 19 render nothing: true #何もしない動作 20 return 21 end 22 23 # INFO: is_duplicated <= true or false が代入される 24 # paramsとして送られてきたurlで、Userモデルのfriendly_urlカラムを検索 25 is_duplicated = User.where('friendly_url LIKE(?)', "#{params[:url]}").exists? 26 respond_to do |format| 27 format.json { render json: { isduplicated: is_duplicated }} 28 end 29end

これが正しいのかどうかはわかりません。
きれいなコードを書くためには、rubocopというgemがかなりおすすめですので、少しずつこのgemの言うとおりに修正していくとよいと思います。

補足

render nothing: true #何もしない動作
の部分は、何か必要に応じてパラメータを渡してあげてもいいかもしれませんね。
今のところはjavascript側で受け取る処理がないので、このままでもよいと思いました。

投稿2019/05/05 12:37

編集2019/05/06 02:22
siruku6

総合スコア1382

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

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

Romay

2019/05/06 00:18

まさにこれで期待する動きができました!ありがとうございます! ただ入力しているユーザー自身のfriendly_urlにも反応してしまっていたため、その条件式を追加しました。 以下のコードで動いてはいるのですが、よりよい書き方があればご教授いただけますと嬉しいです。 【user_controller】 def check unless params[:url] == current_user.friendly_url if User.where('friendly_url LIKE(?)', "#{params[:url]}").exists? #paramsとして送られてきたurlで、Userモデルのfriendly_urlカラムを検索 respond_to do |format| format.json { render json: { isduplicated: true }} #存在する場合はtrue end else respond_to do |format| format.json { render json: { isduplicated: false }} #存在しない場合はfalse end end else render nothing: true #何もしない動作 end end
siruku6

2019/05/06 02:29 編集

動いたようで私もうれしいです! それから、回答に追記してみました。 何度も言いますがrubocopはオススメです^^
Romay

2019/05/06 22:07

追記もありがとうございます!DRYな書き方勉強になりました。rubocopも試してみます。
guest

0

JSONモジュールのdumpメソッドを使えば、RubyのオブジェクトをJSON文字列に変換できますよ。
https://docs.ruby-lang.org/ja/latest/method/JSON/m/dump.html

投稿2019/05/02 01:56

iwamot

総合スコア1154

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

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

Romay

2019/05/06 22:08

dumpメソッド知らなかったので勉強になりました。ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問