Web Marina

日々の業務や勉強などで得た知識をアウトプットしていきます。

【jQuery】Ajaxでサーバー側にアクセスする

f:id:song-of-life1352607:20180113005923j:plain

こんにちは、マリンです。

今更ながら、「Ajaxでサーバーのアクセスする」と言う意味がわかりました。

というか、それで何ができるのかということがわかったので、

嬉しくて思わず書き記したくなりました。


Ajaxとは?

ウィキペディアによると、

Ajax(エイジャックス、アジャックス)は、ウェブブラウザ内で非同期通信を行いながらインターフェイスの構築を行うプログラミング手法である。XMLHttpRequest(HTTP通信を行うためのJavaScript組み込みクラス)による非同期通信を利用し、通信結果に応じてダイナミックHTML (DHTML) で動的にページの一部を書き換えるというアプローチを取る。

……え、なんて??

理解力の乏しい私にはなかなかです。。。

順を追って噛み砕いてみましょう。


従来とAjaxの違い

通常のデータ通信は同期通信と言って、

クライアントがサーバーへリクエストを送り、

そのレスポンスを受け取って画面遷移を行うという流れです。

クライアントとサーバーのリクエスト・レスポンス、

それぞれの送受信のタイミングが揃っていないといけないので、

レスポンスが帰ってくるまでの間他の処理はできません。

双方が同期しているので、同期通信です。


一方ここにある非同期通信とは、

「リクエストは送るが、レスポンスが帰ってくるのを待たない」

という通信方法です。

待たないということは、その間に別の処理を行えるということです。


更に「ウェブブラウザ内で」という点もポイントです。

つまりJavaScriptがこの送受信を行ってくれるので、

画面遷移をしなくて済むということです。


よくある例ですが、Google mapで見てみましょう。

Google mapは地図をドラッグすると、自動的に新しい未表示部分を表示してくれますよね?

これはJavaScriptが足りない地図を非同期通信でリクエストしてくれているからです。

レスポンスを待たないのでドラッグし続けられるし、

画面遷移しないのでいちいちリロードすることもありません。


つまるところ

XMLHttpRequest(HTTP通信を行うためのJavaScript組み込みクラス)による非同期通信を利用し、

リクエストは送るけどコレ非同期通信だから、


通信結果に応じてダイナミックHTML (DHTML) で動的にページの一部を書き換えるというアプローチを取る。

結果出たらそれに合わせて画面調整するから教えてね。その間に先進んどきます!


ということを可能にする仕組みがAjaxです。

語弊があったら指摘してください!!


Ajaxを使ってサーバーにアクセスする

さてここからが本題です。これによって何ができるのか?

まぁ、上にあげたことが全てではあるのですが、

理解が浅かったせいで気づかなかったんですね。

JavaScriptを使ってサーバーにアクセスするってことは、

ブラウザ側でデータ扱えるってことじゃないですか!


仕事でjQueryとかも書くようになってきた最近。

「あ〜。。。でもここJSだからデータ取ってこれないもんなぁ〜。。。」

ってことが度々ありました。

これを解決してくれるわけですね!

いや、そもそもそのためでしょ?ってのはよくわかってますから!

なので今更ながらAjaxの利用価値に気づいたというお話です。


使い方

では使い方。むしろ本題はこっちか。

Railsを使っているのでCoffeeScriptの記述方式です。

jquery-rails 4.3.1を使っています。

$.ajax "url"
    success: (value) =>
        // 通信成功時の処理内容
    error: =>
        // 通信失敗時の処理内容

$.ajax "url"

urlのサーバーにアクセスします。


success: (value) =>

これ以降に通信に成功した時の処理を記述します。

引数のvalue(名前は自由)にサーバーから返された値が入ります。


error

これ以降に通信に失敗した時の処理を記述します。

引数を取る場合はsuccessと同じようにしてください。


因みに、サーバー側から返す値はJSON形式にする必要があるようです。

def return_jquery
    # result = 処理
    render json: result
end

こんな感じで。


以上となります。

理解できたことが嬉しくて書きましたが、

単に自分の理解力の無さが露呈しただけで終わりました。。。

ご指摘がございましたらぜひともご教示ください。

【Ruby】RubyでURLにクエリ情報を追加する

f:id:song-of-life1352607:20180204234624j:plain

こんにちは、マリンです。

現在上司からjQueryの本を貸していただき、

その中から出された課題を解いています。

PHPを使ってYoutube Data APIにアクセスし動画情報を取得。

それをjQueryからAjaxを使って表示するという内容で、

PHPの部分をRubyに置き換えて行うというものです。


未だ課題クリアに至らないのですが、

その過程で学んだ様々なことを忘れないように書き記しておこうと思います。

今回は「RubyでURLにクエリ情報を追加する」というものです。

ちなみにこの課題、よせばいいのにRailsを使わず、

あくまでRubyだけで頑張っています。。。





Youtube Data API

そもそもYoutube Data APIとはなんぞや?

それはGoogleが提供するAPIの一つで、

Youtubeの機能をお手軽に使わせていただけるありがたい便利ツールです。


基本的にはお目あての機能のURLにアクセスすることで使用可能です。

(ただ書籍の仕様とはちょっと変わったみたいで、

APIキーなどの取得が必要となり、

まずそこで困惑したことは秘密です。。。)


今回はAPIのお話ではないので詳しい使い方は省きますが、

アクセスする際に特定のクエリパラメータを渡す必要があります。

今回はその部分をRubyを使って実装しよう!というお話です。


Youtube Data APIの使い方はこちらをどうぞ

YouTube Data API の概要  |  YouTube Data API (v3)  |  Google Developers




URLを書き換える

ソースコード

Rubyは2.4.0を使っています。

require 'uri'

uri = URI('https://www.googleapis.com/youtube/v3/search')

uri.query = URI.encode_www_form({
    part: 'snippet', q: ’〇〇', key: '〇〇'
  })

.query=.encode_www_formを使うため、

RubyのライブラリからURIライブラリを読み込んでいます。

class URI::Generic (Ruby 2.4.0)




詳細

Youtube Data APIURI

まず最初にYoutube Data APIにアクセスするためのURIを変数に入れています。

uri = URI('https://www.googleapis.com/youtube/v3/search')

今回使用する昨日は動画検索機能なので、

最後にsearchという文字が付いています。


.query=

RubyURIライブラリのURL::Genericクラスのメソッドです。

対象のインスタンスのクエリを設定します。

ここでは、youtubeのsearchのURIを格納したuriに対して設定しています。

uri = URI('https://www.googleapis.com/youtube/v3/search')

uri.query = ~




URI.encode_www_form

RubyURIライブラリのURIモジュールのメソッドです。

引数からapplication/x-www-form-urlencoded 形式の 文字列を生成します。

application/x-www-form-urlencodedはこちら

リクエストとレスポンスの仕組み



引数には通常は[key, value]の配列の形で渡します。

[key, value]の形ならハッシュも可です。

今回はAPIにパラメータを渡すために使用しています。

uri.query = URI.encode_www_form({
    part: 'snippet', q: ’〇〇', key: '〇〇'
  })

各パラメータの説明はこちら

Search: list  |  YouTube Data API (v3)  |  Google Developers

keyには最初の登録で取得したAPIキーを入れます。


まとめ

URIの書き換えはAPIに限らず役に立つと思うので、

今回勉強できてよかったです!

ついでにエンコードらへんの仕組みとかもサラッとなでれたし、

今度参考にさせていただいた記事をじっくり読み込んでみます。


ちなみに、現在Rubyでアクセスした結果をAjaxを使ってjQueryの方で処理する段階で、

なぜかRubyの実行結果ではなく、ソースコードがそのまま渡ってくる謎現象にハマっています。

お心当たりのある方、よろしければご教授願います。。。

【jQuery】要素をコピーする

f:id:song-of-life1352607:20180113005923j:plain

こんにちは、マリンです。

今回は要素をコピーする方法をご紹介しようと思います。

概要

ユーザー一覧を表示しているテーブルの行にコピーボタンを表示。

そのボタンを押すとその行のコピーを直下に挿入します。

userモデルにはnameとemailのカラムがあるとします。

コントローラには@users = User.allを記述しておきます。


ソースコード

views/users/index.html.erb

<table>
  <tbody>
    <% @users.each do |user| %>
      <tr class="copy-row">
        <td><%= user.name %></th>
        <td><%= user.email %></th>
        <td><%= link_to 'copy', "#", class: 'copy-user' %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<script>
  users.copy();
</script>




assets/javascripts/users.coffee

class UsersController
  copy: ->
    $('.copy-user').on 'click', () ->
      currentRow = $(@).parents('.copy-row')
      currentRow.clone(true).innsertAfter(currentRow)
      false
this.users = new UsersController

解説

HTML

まずはビューの方の解説です。

あまり説明することはないのですが...


<tr class="copy-row">

行全体をコピー対象にするためtrにクラスをつけます。

trだけでも良いのですが、もし入れ子になっていた時など、

予期しないtrを取ってこないためにも指定した方が安全だと思います。


<td><%= link_to 'copy', "#", class: 'copy-user' %></td>

ここがコピーボタンになります。

link_toである必要は特にないのですが、

jQueryのソースの最後に使っているfalseの説明のためこれにしました。

copy-userと言うクラスをクリックのセレクターにします。


<script>
  users.copy();
</script>

jQueryの呼び出しです。


CoffeeScript

では本題のjQueryの部分です。

class UsersController
  .
  .
  .
this.users = new UsersController

まず最初と最後のこの記述ですが、

このように書くと、HTMLの最後に書いたような記述で

メソッドを指定して呼び出すことができます。

仕組みについては現在勉強中です。すみません...

ちゃんと理解したらまた記事に書きます。


$(.copy-user).on 'click', () ->
    currentRow = $(@).parents('.copy-row')

まずはリンクをクリックした時に、

そのリンク(またはボタン等)の親の行を持ってきます。


currentRow.clone(true).innsertAfter(currentRow)

ここがキモです。

まずcurrentRow(コピー対象の行)をclone(true)でコピーします。

引数のtrueで対象のイベントや変数もコピーしてくれます。


ちなみに(true, false)と第2引数をとることもでき、

この場合は子要素のイベントはコピーされません。

こちらを参考にさせていただきました。

jQuery リファレンス:clone


次にinnsertAfter(currentRow)でオリジナルの直下に挿入しています。

.cloneはただ要素の中身諸々をコピーするだけですので、

このように必ずどこかに表示してあげないと画面には反映されません。


なお、もしコピーする行に固有のidとかが付いていた場合、

それも一緒にコピーしてしまって予期しない動作が起こったりしますので、

その場合はそれらを削除する必要があります。

(私の場合はid番号が付いていてdeleteでオリジナルも消えました...)

コピーの動きについては以上です。


補足

コピーの話とは関係ありませんが、最後にあるfalseについてです。

これは該当要素の本来の動きを打ち消してくれるようです。


今回で言えばクリックの対象をlink_toにしていました。

falseなしだとクリックした時に、一瞬行が表示されて、そして消える。

というような不可解な挙動をしたりします。

これはクリックイベントの処理の後にlink本来の動きをしたために起こることです。

この動きを打ち消すことで消えることなく無事表示されます。


まとめ

要素をコピーして表示するというのは結構見かける機能な気がします。

今回はただ単に一覧の行をコピーして入れただけですが、

実際には複数のデータを一括で編集するフォームに実装しました。

覚えておけばまたどこかで使えそうです。

なんだかんだ1年経ってた。

今回は何のためにもならないボヤキです。

タイトルの通りなんですけど、

年明けて改めて初投稿の日付け見たら

とっくに1年経ってましたww

と言うお話し。(笑)


この1年、あっという間ではありましたが、

それなりに環境は大きく変わったなと思います。

適当に何となく独学してた1年前から、

バイトを始めた約半年前。

てか大きく変わったのは半年前か…


あの時思い切って一歩踏み出して本当に良かったと思います!

基礎的な勉強だけでは分からなかった、

というか私の勉強方法では絶対に分からなかった事を沢山学びました。

まだ全然足りてないんですけど…


今さらですがブログの名前、

「主婦がアプリをリリースするまでの軌跡」

なんですよね。

なんて大それた名前付けちゃったんだろ…(笑)

でも今ならちょっとしたものなら作れる気がする!


とは言え、未だ職場でちゃんと戦力になれていなくて焦ってるので、

実現はまだまだ先になりそうです。

(アイデアも全然浮かばないし)


ということで、

1年経ってもブログ名の目標を達成していない事への言い訳でした。

とりあえず上半期の目標は、

バイト始めて1年になる7月までにはせめて、

ちゃんと戦力になって完全在宅になっている事を目指します!(笑)

【jQuery】クリックでテーブルの行をハイライトさせる。

f:id:song-of-life1352607:20180113005923j:plain

皆さん明けまして(だいぶ経ちますが)おめでとうございます。

本年もまったり更新していこうと思いますので、どうぞよろしくお願い致します。


さて、2019年最初の一発目は、

jQuryです!

最近「勉強してください・・・」と上司にガッカリされましたorz

今回は、クリックしたテーブルの行をハイライトさせてみました。

ポイントはハイライトなので”1行だけ”というところです。

クリックした行全ての色が変わるのを防止します。




ソースコード

今回のコードはCoffeeScriptで書いています。

(基本Railsで書いてるので...)

highlightRow: ->
    $('.select-row').off 'click'
    $('.select-row').on 'click', () ->
        currentTr = $(@).parents('tr')
        if currentTr.hasClass('selected')
            currentTr.removeClass('selected')
        else
            $('tbody>tr').removeClass('selected')
            currentTr.addClass('selected')

select-rowというクラス名のボタンをクリックすると、

その行をハイライトし、もう一度クリックすると消えます。


// ハイライト用のスタイル
.selected {
 background-color: #f5f5f5;
}

ハイライトをする行にはclass="selected"を付け、

スタイルシートselectedにハイライト用のスタイルを適用させます。

ハイライトのON/OFFはこのselectedの有無で切り替えます。


解説

ハイライトOFF

まずは最初からハイライトを消すところまでです。

// 読み込まれた際に一度イベントハンドラーを削除。
$('.select-row').off 'click'

$('.select-row').on 'click', () ->
    // クリックされたselect-rowの親のtrを持ってくる。
    currentTr = $(@).parents('tr')
    // 親のtrが既にselectedを持っていたら(ハイライト状態なら)
    if currentTr.hasClass('selected')
        // selectedを削除してハイライトを解除する。
        currentTr.removeClass('selected')
    else
        // ハイライト用

今回はボタンにselect-rowをつけ、それをクリックすることでハイライトを切り替えます。

なのでスタイルを行全体につけるため、

クリックした時にまずはボタンの親要素であるtrを取得します。


次に、取得したtrが既にselectedを持っていたら、

そのクラスを削除します。

これでハイライトを解除します。


ハイライトON

最後にハイライトをONにする部分です。

else以降を書きます。

 .
 .
 .
 else
  // 一度全trのselectedを削除する。
  $('tbody > tr').removeClass('selected')
  // currentTrにだけselectedを追加。(ハイライト)
    currentTr.addClass('selected')

currentTrへのselected追加だけだと、

どこかをハイライトした状態で別の行のボタンをクリックすると、

そちらの行と前にクリックした行の両方がハイライトしてしまいます。

そのため、一度全部のtrからselectedを削除します。


改めて対象の行にselectedを追加。

これでその行だけをハイライトすることができます。


まとめ

今まで人の書いたものを真似するだけでしたが、

今回が初めて自分で考えて作る作業となりました。

最初は「全部のtrからクラスを削除する」ことをしなかったために、

クリックした行全てがハイライトされてしまったり、

$('tbody > tr')セレクターの取り方をせず、

tbody配下のtrを一つずすeachで回してselectedを調べて...」

なんてjQueryの意味がない!なんてことやってました。

結局上司の助言をいただいて完成した形になりましたが、

良い勉強になりました。

今年はjQueryもいっぱい勉強することになりそうです。

皆さま、本年もどうぞご教授のほど、宜しくお願い致します。

【Git】コマンド: いい加減覚えが悪いのでまとめとく。

f:id:song-of-life1352607:20170220105406j:plain

こんにちは、マリンです。

7月から今の職場でお世話になり始め、はや5ヶ月経ちます。

・・・が、いつも使ってるGitコマンドを全然覚えなくていい加減上司にブチ切れられそうなので、

理解も兼ねてまとめておきます・・・orz




git fetch

ローカルの環境を最新の状態にします。

と言ってもこの時点では作業中のファイルが更新されるわけではありません。

更新されるのは、ローカルにあるorigin/masterです。

リモートにあるmasterを参照して、ローカルのorigin/masterを更新します。




originとmaster

二つは別物で、両方ともローカルにあるブランチです。

(masterはリモートにもあるブランチですが、リアルタイムで連携してるわけではないです)

origin/master

  • リモートの状況を追跡するためのブランチ

  • originという名前のリモートの、masterブランチを追跡していますよ。

  • git fetchすることでこのブランチが最新になる。(連携は手動で。)




master

  • ただの作業ブランチ(語弊がある??)

  • issue~create-userとか、そんな感じと一緒。

  • git fetchしただけでは変更されない。




originとmasterについてはこちらの記事がオススメです。

gitのふわっとした知識を調査してみたnekosoftware.wordpress.com


git checkout ブランチ名

対象のブランチに切り替えます。

もしそのブランチがローカルにない場合には、新規に作成して切り替えます。

そして新しいブランチで作業を始める際、

いつもこれとfetchを組み合わせて使っています。

$git fetch && git checkout ブランチ名




git tr --all

正確には

$git tree --all

です。

最新までのgitのツリー状況を見ることができます。


git merge origin/ブランチ名

先にgit fetchを出しましたが、あれだけでは作業ディレクトリは最新になりません。

mergeをすることで、初めて現ブランチを最新にできます。

現在いるブランチを指定したブランチの状態に上書きします。

(上書きという表現が正しいか分かりませんが、私は一番しっくりきました。)


ブランチを最新にする一連の流れ

$git fetch
$git tr --all
$git merge origin/ブランチ名
  1. fetchでローカルのツリーを最新に
  2. trでマージするブランチを確認
  3. mergeで現在のブランチを最新にする




git pull

職場では使っていませんが、

前述のブランチを最新にする一連の流れをまとめたコマンドです。

手間は省けますが、やはり一つずつ確認してからのが安心な気がします。


git diff

差分を確認するコマンドです。

確認対象は様々に指定できますが、指定がない場合は

インデックス(add後commit前のもの)と作業ディレクトリとの差分を表示します。

それぞれの指定方法はこちらが分かりやすかったです。

qiita.com




まとめ

今回はこんな感じでしょうか。

いつも迷うものをあげたので、commitとかpushとかは出していません。

多分コマンド自体の意味より、

originとかmasterとかがよくわかっていなかったから、

これをするとどこに何が反映される?という点でこんがらがっていたんだと思います。

まだ怪しい気がするので、もし間違いがありましたらぜひご指摘ください。

よろしくお願い致します。

【Rails】$rake db:rollbackしたい時の間違えない手順

f:id:song-of-life1352607:20170220105406j:plain

こんにちは、マリンです。

未だ初心者の域を脱しない私は、よくmigration周りでやらかします。

一人でやっていた頃は失敗すると

ロールバックしちゃえ〜」「migrationファイル消しちゃえ〜」

とかやっていましたが、

チームでやっているとそんな横暴は許されません・・・

今回丁度勉強で作っていたサンプルで失敗したので、

ロールバックの正しいやり方?を学びました。




migration周りの注意

そもそもなぜこのあたり注意しなきゃいけないのか?

今更気づいたので一応書いておきます。


migrationファイルを書き換えたり削除した場合、

当然次回$rake db:migrateした時にテーブル構造が変わってきます。

一人でやっている分には大して支障はないですが、

これをチームでやっているリモートリポジトリなんかにあげちゃったりすると・・・


それをマージした他の方の環境まで変わってしまい、

最悪「コードの辻褄が合わない!」なんてことになりかねません。

ということで、この辺のファイルがどれほど恐ろしいものか気づいた私は、

今後は普段から取り扱いに注意する癖をつけようと肝に銘じました。


rollbackの手順

さて本題です。前述の通りこの辺は取り扱い注意なので、

失敗しない手順を学びました。


現在の状況を確認する

まずはどこまでmigrateが実行されているかを確認しましょう。

$rake db:version

このコマンドで確認できます。


$ rails db:version
Current version: 20171112122350

こんな感じで出てきます。

20171112122350まで実行されていますね。


ロールバック

次に戻したいところまでロールバックします。

[一つ前まで戻す]

$rake db:rollback



[任意のファイルまで戻す]

$rake db:rollback STEP=○

現在地を含めた○個前までなかったことにしてくれます。

(つまり○+1個前のファイルまで実行された状態)


migrateされていないファイルを確認

念のためどのファイルが実行されていないか確認します。

$rake db:abort_if_pending_migrations
You have 1 pending migrations:
  20171112131249 CreateUsers

20171112131249のUserテーブルが作られていないようです。


ファイルを修正

class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.references :comment, index: true, foreign_key: true    # null: falseを削除
      t.string :name
      t.string :email
      t.timestamps
    end
  end
end

今回はCommentテーブルにレコードが何も入っていない状態で

NOT NULLにしてしまったため失敗したので、

null: falseを削除します。


migrate

修正が完了したらマイグレートを実行します。

$rake db:migrate
== 20171112131249 CreateUsers: migrating ===============================
-- create_table(:users)
   -> 0.0026s
== 20171112131249 CreateUsers: migrated (0.0027s) ========================

これで無事修正完了です。


こちら参考にさせていただきました。

www.d-wood.com

追記

1ヶ所$rails db:versionと書いてしまいましたが、

Rails5の場合これでもいけます。

Rails4以前の場合は$rakeでお願いします。