バンビのブログ

駆け出しのエンジニアです!日々の疑問など備忘録として書いていきます。

要件定義のやり方【準備編】

要件定義をするにあたって

要件定義は依頼主と制作主のお互いの納品条件の明確化をする

  • 依頼主と制作主側で作るもののギャップや受け取り方のちがいを無くす
  • お互いに気持ちの良い仕事ができるようにするためのもの

揃える道具

  • 企画書
  • 全体像(オーバービュー)
  • 実装手段
  • やりたいこと一覧(バックログやアイスボックス的なやつ)

    基本的な流れ

  • 依頼主の要望を引き出す
  • 引き出した要望を制作主に要望として伝える
  • 制作主は要望を見て検討する
  • 検討を経て、より良い提案をする
  • またはこれは実現が難しいので、こうしたらどうでしょうと代替案を出す
  • 依頼主はそれらを読み、聞き、検討する
  • そうしてまた2に戻り、繰り返す

企画書を作成する

  1. プロジェクト名
  2. なぜ
    • 目的
  3. 何を
    • 目的達成のために
    • 作るものの説明
    • 作るものを利用する人
    • 利用する人が得られる利益
  4. どのように
    • 作るための体制
    • 期限
    • 費用

      企画書は「通す為のものではなく」「メンバーが理解できるもの」を作成すること。

  5. 企画書を書くときの注意

    • 制作を依頼する側の関係者や関わりが薄い人でも理解できるもの
    • わかりやすくするための細かい解説は別の補助資料にまとめる
  6. 関わるメンバーが走るべき目標を記述する

    • 各々の頭のなかで管理をしていると、時間が立つにつれ目標がずれるため。
  7. プロジェクトで得られる利益

    • この企画を経て得られる利益を明記

利用者たちが実現したいことを図にする(オーバービュー)

図の参考

  • システムを真ん中において、システムの利用者を洗い出す
  • 利用者各々でシステムで利用したいことを書き連ねる
  • すべて洗い出しすることが目的ではないので、大まかなで良い

注意 - アドミン機能も忘れず書くこと - 外部システムとの連携がある場合は外部システムに渡すべき必要な情報を書く

図ができたらきれいな見た目やXDなどで軽いUIを作って提出する - あくまで他者が見て理解しやすくわかりやすいものを書く - 文章の説明より、図や写真をつかった方がイメージが伝わる

実装手段の選定・技術選定

システムの利用環境

  • WEBシステムなのか
  • スタンドアローンのようなシステムなのか
  • WEBは使わないのか(インターネットがなくても使えるものなのか)

インタラクションアーキテクチャにおける検討項目

システムの流れを実現させるために何を使うのかを明文化させる

やりたいこと・実現したいことリストをつくる

!!これは本来企画書前に完璧に完成させておく必要がある!!

実現したいことをとにかく羅列する

  • 粒度の大きなでも詳細なものでも良い
  • とにかく書き出す
  • 決まりきったことでなくてもよい

要求の洗い出しする

  • 明文化する、させることによって相手の要求を共有できる
  • 要求は変更されるに決まっているという前提を理解する

やりたいこと・実現したいこと一覧を整理する

  • 実現したいこと一覧のなかに矛盾などがあるので、その解消をする
  • 実現したい内容があまりにもかけ離れている場合は、その解消をする

完成した後に依頼主の期待が全く反映されていないという事件を回避する為に必ず時間をかけて分析・整理を行う必要がある これを要件定義工程に入る前にやり終えなければ必ず炎上する or 期待に添えないものをつくることになる

IPアドレスとサブネット

IPアドレスの基本

HTTPの仕組みがわかったら次はIPアドレスの話になって、 サブネットマスクとかまじで意味わからんかったからまとめます。

グローバルIPアドレス

インターネットに接続する機器が使用できるIPアドレスで、インターネット上でIPアドレスが重複してはいけません。そのため、グローバルIPアドレスは、IPアドレスの管理団体が厳重に管理しています。

IANAという特定の国に所属しない組織が世界中のIPアドレスを管理しています。

IANAから委託をうけて日本で使用していいIPアドレスを受け取り JPNICという日本のIPアドレスを管理する組織があり、 その下にNTTなどの一般家庭などにインターネットなどを提供している組織があります。

プライベートIPアドレス

インターネットに接続するのではなく、社内や家などで好きなように使えるIPアドレスのこと。

IPアドレスは基本はユニークで唯一無二のものなので、基本はかぶっては行けないものですが、プライベートIPであれば指定された範囲ないで好きなように値を割り振って良いとなってます。

かといって、プライベート内で重複したプライベートIPアドレスを振るとバグります。 同じ住所がいくつもあると届け物がどっちに届けて良いのかわからなくなるのと同じです。

プライベートIPアドレスの範囲 192.168.0.0 - 192.168.255.255 172.16.0.0 - 172.31.255.255 10.0.0.0 - 10.255.255.255

192.168.0.0 - 192.168.255.255 これはルーターでよく使うプライベートIPアドレスで、ルーター192.168.x.xの番号をグローバルIPアドレスに変換しますよ。という機能を持っている。

ループバックアドレス

127.0.0.1 local hostでよく見るIPアドレスで、自分自身のPCを表す表記となっている。

127.0.0.0から127.255.255.255の範囲のアドレスがループバックアドレスとして確保されているのでその範囲内なら設定で変更できる。

IPアドレスの特定方法

IPアドレスはユニークな値が振られていて、人間でいう住所と同じです。

IPアドレス192.168.0.1みたいに番号で振られていて、人間が覚えにくいので名前をつけて、 番号と名前を紐付けることにした。

その紐付けをしたデータが登録されているのがDNSサーバーです。

HTTPリクエストを送信したときにURLを元手にかDNSサーバーに照会を依頼し、登録されている IPアドレスを割り出し、そのIPアドレスのサーバーへリクエストを送信するという流れになっている。

IPアドレスの構造とサブネットマスク

IPアドレスには決まりがあり、

192.168.0.0 - 192.168.255.255 IPアドレスには、 ネットワーク部(ここのネットワークにいるよという住所)と ホスト部(そのネットワーク内のこのPCだよとう住所)にわけられる。

このネットワーク部とホスト部の境目はどこやねん、というのを示しているのが、サブネットマスクなんです。

192.168.0.1/255.255.255.0

192.168.0.1までがIPアドレス

/255.255.255.0サブネットマスクです。

192.     168.     0.       1        IPアドレス
255.     255.     255.     0        サブネットマスク10進数ver
11111111.11111111.11111111.00000000 サブネットマスク2進数ver

ピリオドでサブネットマスクとIPアドレスが対応していて、
サブネットマスクが255の部分がネットワーク部の範囲をしめしていて、
サブネットマスクが0の部分がホスト部をしめしていてます。

サブネットマスクをみて、ネットワーク部とホスト部の境目を見分けましょう。

特徴的なホスト部

ホスト部の番号で実は意味のある番号があります。

サブネット自体を示す

192.168.0.1/255.255.255.0

を例にすると

192.168.0.0/255.255.255.0

ホスト部の番号を「0」にすると、その個々のコンピュータではなくサブネット自体を示します。

ブロードキャストをする

192.168.0.1/255.255.255.0

を例にすると

192.168.0.255/255.255.255.0

ホスト部の番号を「255」にすると、サブネット内全体に配信ができる番号となっている。

【読書】起業のルール

起業・事業を始めるにあたって

自分のできることをまず事業化しよう

まずは自分の持っているスキルをつかって事業をはじめてみよう。全く知らない分野に飛び込むのはあまり現実てきではない。 

  • 僕の場合は、webサイト制作・LP制作・web広告運用・SNS活用・システム構築あたりだろう。

どんなことでも良いので自分の事業の【強み】を見つけよう

これは本当に大切なことで、これがないと他社と差別化ができず、広告を打っても良い結果がでにくいであろう。

  • 僕の場合は【納品が早い】【価格が安価】【サーバーやドメインの構築・運用も行なう】【サイトの文章も作る】【夜中でもいつでも対応する】とかになるのかな。加えて会社のブランディング戦略も今準備しているので、どちらもできたら、webサイト・広告・webをとうしてのブランディングに困ってる会社さんの助けになるのではと思っているよ。

  • それと加えてWEBサービスも立ち上げたいといま計画をしています。誰かを助けつつ地に足つけて運営をすることを目指しているよ。

起業は失敗が基本というスタンス

こんなこと書くと最近は誤解が生まれそうだけど、もちろん成功に向けて全力かつ着実にすすめていくつもりだが、最初から大成功はできないであろう。というマインドでいる。 

  • 失敗を恐れて動けないことが一番の敗北
  • 失敗の穴を塞いでいきながら成功しよう
  • 一人で考えすぎずに知り合いの社長さんなどから意見をもらおう 
  • 失敗が起こっても受け流して成功に近づける受け身をとれるようになろう

自分の想像だけで事業をすすめるのはやめよう

イデアを思いついたときは、天才だとかこれは行ける!とおもうことあるとおもうのだけど、まずはそのアイデアの検証をしてみよう

僕の場合は、

  • 競合他社を見つける・売上を見る

  • 競合他社同士比較して違いを見つける・売り出している強みを見つける

  • 競合他社の企業規模を確認する

  • あらゆる面でのキャッシュポイントを探す(先輩起業家や社長さんに相談してみる)

  • 市場規模を見る

  • 立ち上げにかかる費用を計算してみる

  • 実際の利用しているお客様や利用しそうな人の意見を集める

  • 実際に既存サービスを利用してみる

  • 自分の強みを活かせるか検討する

僕が最近行った思いついたアイデアに対して行ったことはこれくらい。 もっと他にもこれやったほうがいいよというのがあれば知りたいなあ。

事業計画書をつくったらいろんな人に意見をもらおう

  • 事業計画書を作成したら社長さんや先輩や協力してくれそうな人に見てもらって穴を塞いでいこう 僕の場合は、マッチングサービスをやるとなった場合は、サービスが始まったら参加してほしい企業さんやお客さんに見せて、進捗とかも共有して関係の構築も行いたいと思う

財務表は作れなくても読めるようにしよう

  • 財務表は作れなくても会社の状況を見るための大事な資料なので読めるようにしよう

ちなみに僕は会計系の大学時代で過ごしたが、綺麗サッパリ忘れている笑

特異メソッドと特異クラス

この特異メソッドと特異クラスっていつも見かけるけど、なんやねん。 読んでも読んでもわからんってちょうど一年前に思ったので解説します。

特異メソッドとは

単一オブジェクトに対して定義できるメソッドのことをさします。

クラスメソッド

class Test

# selfでクラスを指定しているよ!
  def self.foo
    'foo!!'
  end
end

p Test.foo
# => "foo!!"



class Test

# selfではなく、明示的にクラス名を書くこともできるよ!どっちも同じ意味です。
  def Test.foo
    'foo!!'
  end
end

p Test.foo
# => "foo!!"

クラスメソッドはそのクラスの特異メソッド(Singleton Method)という意味になります。ここがよくわからんポイントです。

これの singleton_methods を使うとそのオブジェクトの特異メソッドが確認できます。
p Test.singleton_methods
# => [:foo]

この特異メソッドというものは、オブジェクトに対してメソッドが定義されていることになります。
オブジェクトはPCのメモリに『オブジェクト番号』みたいなものが振られていて、それぞれまったく異なった番号で管理されていて、

変数・定数・インスタンスとかそれぞれに全く別の『オブジェクト番号』が振られていて、そのオブジェクトごとにメソッドを定義していると考えるとわかりやすいです。

なので、オブジェクトごとにメソッドを設定してる例がこちらになります。

# 上の例で作成したTestクラスをインスタンス化します。
# test1を(オブジェクト番号1とします。)
test1 = Test.new

# Testクラスからできた test1(オブジェクト番号1) インスタンスに特異メソッドを定義します。
def test1.bar
  'bar!!'
end

# test1(オブジェクト番号1)に定義していたので実行できました。
p test1.bar
# => "bar!!"

では、次に同じTestクラスからtest2(オブジェクト番号2)で bar メソッドを実行しましょう。

# 同じTestクラスをインスタンス化
test2 = Test.new
test2.bar
# 定義されてないのでエラーが発生しました。
# => undefined method `bar' for #<Test:0x007fe2e0838018> (NoMethodError)

というように同じクラスから生成したインスタンスなのに同じメソッドが実行できないというようになりました。
その理由は、オブジェクトtest1に対してメソッドを定義しているので、オブジェクトのtest2には定義していなかったら実行できないということになります。

このTestクラスも実は、Classクラスから生成されたインスタンスなので、

はじめに書いたself(またはクラス名).メソッドは、特異メソッドをクラスに定義していることになります。

クラスもオブジェクトなので、インスタンスに特異メソッドを定義したときと同じ考え方になります。

わかりにくいけど、インスタンスの規模が大きくなったとおもうと良いかも!

特異メソッドは特異クラスに定義されている

クラスメソッドはクラスにself.methodで定義できて、インスタンスメソッドは、クラス内に、def メソッド名 endで定義できます。 じゃあ、特異メソッドはどこに定義されるのか、それは特異クラスに定義されることになります。

# Testクラス作成
class Test
end

# Testクラスを継承してExtTestを作成
class ExtTest < Test
end

test = ExtTest.new

# testインスタンスのクラスはExtTest
p test.class
# => ExtTest

# testインスタンスのスーパークラスはTestクラス
p test.class.superclass
# => Test


# インスタンスごとにオブジェクト番号が違います。
test1 = ExtTest.new               #=> #<ExtTest:0xXXXX>
test2 = ExtTest.new               #=> #<ExtTest:0xYYYY>


# testインスタンスの特異クラスは#<ExtTest:0x007fc6a2038020>という特異クラス名とオブジェクト番号が返ってきます。
p test.singleton_class
# => #<Class:#<ExtTest:0x007fc6a2038020>>

# testインスタンスの特異クラスの名前だけ返しています。
p test.class.singleton_class
# => #<Class:ExtTest>

# どちらもスーパークラスの特異クラスを返しています。
p test.class.singleton_class.superclass
# => #<Class:Test>
p test.class.superclass.singleton_class
# => #<Class:Test>

Rubyメソッド探索方法

※まず最初に継承チェーンを読んでからメソッド探索方法を読みましょう。

自分が作成したメソッドたちがどのような順序で探索されて、実行されているか覚えておこう!

継承でのメソッド探索

# クラスとメソッド『hello』を作成
class Class1
  def hello
    puts 'Hello from Class1'
  end
end

obj1 = Class1.new

# インスタンスからhelloメソッドを実行する
obj1.hello #=> Hello from Class1

# 継承チェーンで説明したように、Class1が継承しているクラスを確認
p Class1.ancestors #=> [Class1, Object, Kernel, BasicObject]

obj1インスタンは、Class1のメソッドを探索し、実行したメソッドと一致すれば実行される

スーパークラスのメソッドを呼び出すには

class Class1
  def hello
    puts 'Hello from Class1'
  end
end

# Class1を継承してClass2を作成(Class2には何もメソッドを定義していない)
class Class2 < Class1; end

obj2 = Class2.new

# インスタンスからhelloメソッドを実行する(Class2には何も定義されていないので継承したClass1のメソッドが実行される)
obj2.hello #=> Hello from Class1

# 継承したクラス一覧
p Class2.ancestors #=> [Class2, Class1, Object, Kernel, BasicObject]

このようにクラスのなかでメソッドが見つからない場合はスーパークラスへ探索が行われ、更になければまたその先のスーパークラスへ探索が行われます。

特異メソッドを呼び出したときの探索順序は特異メソッドが優先される

class Class1
  def hello
    puts 'Hello from Class1'
  end
end

# インスタンス作成
obj1 = Class1.new

# 特異メソッドを作成
def obj1.hello
  puts 'Hello From Singleton'
end

# メソッドを実行すると特異メソッドが実行されている。
obj1.hello #=> Hello From Singleton

クラスのメソッドより先にオブジェクトに定義された特異メソッドを探索しにいく。

※この特異メソッドはとてもわかりにくいとおもうので別の解説を用意しておくのでそっちを読んでもえると理解の助けになるかもしれない。

ざっくりいうと、特異メソッドは『オブジェクトに定義するメソッドということ』です。 特異メソッドはクラスにメソッドを定義しているのではなく、オブジェクトに定義している。なのでオブジェクト番号が違うとメソッドが実行できない

Mixin(モジュールをincludeすること)のメソッド探索

module Module1
  def hello
    puts 'Hello from Module1'
  end
end

class Class1
  def hello
    puts 'Hello from Class1'
  end
end

#  クラスを継承しつつモジュールをインクルード
class Class2 < Class1
  include Module1
end

obj2 = Class2.new

# Class1よりもModule1のほうが先にメソッド探索が行われ、メソッドが合致したので実行された。
obj2.hello #=> Hello from Module1

# 継承チェーンで説明したようにincludeしたクラスが先に探索され、その後にモジュールが探索される。
p Class2.ancestors #=> [Class2, Module1, Class1, Object, Kernel, BasicObject]

複数Mixin(モジュールをincludeすること)した場合のメソッド探索

module Module1
  def hello
    puts 'Hello from Module1'
  end
end

module Module2
  def hello
    puts 'Hello from Module2'
  end
end

class Class1
  def hello
    puts 'Hello from Class1'
  end
end

class Class2 < Class1
  include Module1
  include Module2
end

obj2 = Class2.new

# モジュールはインクルードした下から読み込まれていく
obj2.hello #=> Hello from Module2

# 継承チェーンで書いたのと同様にモジュールは書いた下から読み込んで、メソッド探索が実行される。
p Class2.ancestors #=> [Class2, Module2, Module1, Class1, Object, Kernel, BasicObject]

PrependをつかったモジュールのMixinをした際のメソッド探索順の変更

module Module1
  def hello
    puts 'Hello from Module1'
  end
end

module Module2
  def hello
    puts 'Hello from Module2'
  end
end

module Module3
  def hello
    puts 'Hello from Module3'
  end
end

class Class1
  def hello
    puts 'Hello from Class1'
  end
end

class Class2 < Class1
# prependはモジュールを予め読み込ませておくことができる。
  prepend Module3
  include Module1
  include Module2

  def hello
    puts 'Hello from Class2' 
  end
end

obj2 = Class2.new

# prependを行ったことで読み込みがクラスより先にModule3のメソッドが探索され、実行されている
obj2.hello #=> Hello from Module3

# prependを行ったことで読み込みがクラスより先にModule3が読み込まれている
p Class2.ancestors #=> [Module3, Class2, Module2, Module1, Class1, Object, Kernel, BasicObject]

書き途中です。「Rails5.2」 から 「Rails6」へバージョンアップ

「Rails5.2」 から 「Rails6」へバージョンアップ

【注意】 * バージョンアップを行なうときは既存コードでサポートされないコードがあるか確認すること。 * バージョンアップ後に動いていないコードや機能を発見するために自動テストを必ず準備しておくこと(とくにビジネスロジックあたりは必ずテストを用意) * バージョンアップはリリースされているバージョンを飛ばして行わないこと。v5.2 -> v6 は良いが、v4 -> v6はNGです。 * アップデートの必要な箇所を洗い出してから行なうこと。 * 追加機能や機能の変更点を把握しておくこと。

Rails6の更新事項

  • Rails 6ではRuby 2.5.0以降が必須。(うちはRuby 2.6.2なので関係大丈夫です)
  • フロントエンドの管理ライブラリを 『Assert Pipeline』 から 『webpacker』 に移行するかどうか?
  • Action Cable JavaScript APIの変更があるが、action_cableは使われていないので対応しなくて大丈夫です。
  • ActionDispatch::Response#content_typeがContent-Typeヘッダーを変更せずに返すようになった(使っていないので大丈夫です)
  • Zeitwerkというオートローダーが採用された。
※前提として、定数解決というものを理解しないとオートローダーの中身は理解しにくいです。

1. オートローダーはファイルを読み込む際に require '読み込ませたいファイル名' を記述しなくてもファイルや階層などの命名規則に沿った書き方をしていれば自動的に読み込む(探し出してくれる)こと。
2. 1つのファイルにトップレベルのクラス定義できるのは1つのみ。
  例 a.rbファイルに 
  class a 
  end  
  
  class b 
  end と2つ定義するのはNG。 

  Foo = Class.new do
  end
   みたいなクラスの作り方もNG。
 
  ネストして 
  class a 
   class b 
   end 
  end
  となるのはOK3. 標準のconcernsディレクトリ(app/models/concernsなど)に置かれたファイルでは、Concernsを名前空間化できない。
   疑問に思っていなかったかもしれないけど、ディレクトリの配下は基本名前空間を記述するのだけどConcernsは名前空間を書かなくて良いとなっている。
  例 app/models/concerns/hogehoge.rbで定義されるのは

       class Concerns::Hogehoge
       end
       と書くのが一般的だが、Concernsにおいては名前空間を書かなくても良いclass Hogehoge
       end
       と書けば読み込んでくれます。
※もし、作成したファイルが読み込まれていないと思ったときは、このオートローダーをデバックすると読み込まれているか確認できる。
  puts ActiveSupport::Dependencies.autoload_paths
  
   1.もし読み込まれていなかったら、再起動する。(開発環境では config.cache_classes = false で変更があれば更新されるようになってる)
   2.そもそも読み込みされないのであれば config.autoload_paths をつかって config/application.rb に追記する。
   3.追記したあと、それぞれのファイルの命名規則などがあっているか確認する。命名規則が間違えていると読み込まれないので注意。
  • ActionDispatch::HostAuthorizationというDNSバインディング攻撃を防ぐための機能が追加されました。
ローカル実行されているRailsアプリケーションに対して悪意のあるアクセスをし、ローカルENV(環境変数)情報や、ローカルRailsアプリの全情報にアクセスできて、情報丸パクリされる攻撃みたいです。
詳しくは調べて、理解した人追記おねがいします。

自分たちが開発してるPCの開発環境に外部からアクセスする方法があります。ngrokというサービスです。
ngrokとは、localhostで動いているサーバーを、LANの外からアクセスできるようにできるツールです。
vagrantなどのローカル環境を一時的に外部に公開できるため、webhookなどの受信が必要なシステムでも、ローカルで動かすことが可能となります。

基本的にはActionDispatch::HostAuthorizationを変更することはないはず。

develop環境でデフォルト設定されているのが以下です。
Rails.application.config.hosts = [
  IPAddr.new("0.0.0.0/0"), # All IPv4 addresses.
  IPAddr.new("::/0"),      # All IPv6 addresses.
  "localhost"              # The localhost reserved domain.
]

もしどこかのドメインからローカル環境にアクセスを許可したい場合は、

# '○○○.com'からのアクセスを許可する設定はこのように書きます。
/frien/config/environments/development.rb

Rails.application.config.hosts << '○○○.com'

# 'www.○○○.com'や'blog.○○○.com'などの
# サブドメインを許可する設定
Rails.application.config.hosts << '.○○○.com'

※develop環境以外では有効になっていないので、手動で設定が必要となる。
  • コンソールで rails routes を表示させるときに、rails routes --expanded オプションをつけると見やすく表示する機能が追加!

Axios asyncとawait

Axios:

AxiosはAjaxリクエストを簡単にかけるようにしたPromiseベースのjsのライブラリです。

GET通信をするとき

const info
const error

// get()に通信したいURLを記入
axios.get('/user?id=123')
             or
// オプションで第2引数を渡すこともできる
axios.get('/user', params{ id: 123 })

     //通信に成功し、返ってきた値を this.info に代入する
     .then(response => (this.info = response))

     //エラーだった場合はエラーを捕捉する
     .catch(error => (this.error = error))
     
     //続けて書くと成功でも、失敗でもその後実行される処理もかける。PUTでもPOSTでも他でも同様
     .then(function () { 処理 });

POST通信をするとき 第1引数にURLを指定して、第2引数に送信したい値を設定します。

//post送信したいデータを格納する変数を作成
const post-data = { name: 'hoge' };

axios.post('/user', post-data)

    .then(res => {

        //送信成功時の処理
        alert("「" + post-data.name + "」登録完了");
        this.$router.push({path: '/articles/list'});
    })
    .catch(error => {

        //送信失敗時の処理
        alert("「" + post-data.name + "」登録失敗");
        console.log(error, post-data);
    });

PUT通信 データ更新するとき

//更新したいID設定用の変数
const id = '1000';

//更新データ用変数
const modify = { name: 'hoge' };


Axios
    //第1引数にURL設定をし、第2引数に更新するデータを設定
    .put('/api/sample/' + id, modify)
    .then(res => {
        //通信成功時の処理
        alert("「" + modify.name + "」更新完了");

     // リダイレクトさせる
        this.$router.push({path: '/articles/list'});
    })
    .catch(error => {

     //通信失敗時の処理
        alert("「" + modify.name + "」更新失敗");
        console.log(error, id, modify);
    });

DELETE通信をするときは、他と違い第2引数に設定する値のキーを「data」に設定して書かなければだめ。例 {data: params}

//削除対象のIDを設定
const id = '1000';

//削除内容を設定
const params = { name: 'hoge' };

Axios
    //delete通信をし、第1引数にURLとIDを設定し、第2引数に {data: 削除したいデータ} を設定
    .delete('/api/sample/' + id, {data: params})

    .then(res => {
        // 成功時の処理
        alert("「" + params.name + "」削除成功");
        this.$router.push({path: '/sample/list'});
    })
    // 失敗時の処理
    .catch(error => {
        alert("「" + params.name + "」削除失敗");
        console.log(error, id, params);
    });

async awaitを使用したいとき asyncはPromiseオブジェクトを返しますという宣言でつけるらしい。

// asyncをつけてメソッドを定義
async function getUser() {

  //try,catchでエラーを捕捉できるようにしておく
  try {

  //Promiseオブジェクトで「resolve」が返ってくれば実行される
    const response = await axios.get('/user?ID=12345');
    console.log(response);
  } catch (error) {

  //Promiseオブジェクトで「reject」が返ってくれば実行される
    console.error(error);
  }
}

複数のaxiosが実行されたあとに実行したい処理がある時(Promise.allみたいな感じ)

// 1個目のメソッド
function getUserAccount() {
  return axios.get('/user/12345');
}

// 2個目のメソッド
function getUserPermissions() {
  return axios.get('/user/12345/permissions');
}

// Promise.allとほぼ同じで、配列でメソッドを囲う
axios.all([getUserAccount(), getUserPermissions()])

  //囲った2つのメソッドが実行されたら以下の処理が実行される
  .then(axios.spread(function (acct(1個目のメソッドの返り値のこと), perms(2個目のメソッドの返り値のこと)) {
    // Both requests are now complete
  }));

asyncawait.thenの書き方を簡潔にかけるようにしたものです。 asyncをつけるとPromiseオブジェクトが返却されるようになります。

//asyncでかくとこうなる

async function asyncFunc (arg) {

  // 引数の「arg」もここで使える
  const message = 'Hello async';
  return message;
}

//上記をPromiseで書くとこうなります。
function asyncFunc (arg) {
  return new Promise((resolve) => {
    // もちろん引数のargはここで使えます
    const message = 'Hello async';
    resolve(message);
    return;
  });
}

このくらい差があります。

async = 「return new Promise」 と 「resolve」 が入ってるってイメージなのかな?

awaitasync関数内で使用できる予約語です。 Promiseがわかれば何も難しいことはありません。安心してくださいまし。

// Promiseで書いた場合
function main() {
    getX().then(x => {
        getY().then(y => {
            console.log(x + y)
        })
    })
}

function getX() {
    return Promise.resolve(1)
}

function getY() {
    return Promise.resolve(2)
}

main()

//async awaitで書いた場合
async function main() {
    const x = await getX()
    const y = await getY()
    console.log(x + y)
}

async function getX() {
    return 1
}

async function getY() {
    return 2
}

main()
//async awaitで書いたほうが読みやすよね。

//async awaitでaxiosを使ってみる
async function asyncFunc () {

  //axiosでGET通信
  const res1 = await axios.get('/some/path1');

  //res1を使ってaxiosでGET通信(ということは、res1が完了しないと実行してもうまくいかない。)
  const res2 = await axios.get(`/some/${res1.data.nextpath}`);

  console.log(res1.data + res2.data); // => "some data"
}

画像を送信する時 headers'Content-Type': 'multipart/form-data'を設定すること

//HTML
<input id="file-input" type="file" />

//javascript
//paramsにFormに入力した値格納
var params = new FormData()

var file = document.getElementById("file-input")

// ファイルをparamsに格納
params.append('file', file.files[0])

//第3引数にheadersを追加して、'Content-Type': 'multipart/form-data'を設定してあげる必要があります。
const res = await axios.post(url, params, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
})

画像を取得するときに方法。うまく行かないときや、メソッドを書くときはheaderscontentTyperesposeTypeなどが正しいか確認しよう。

//axiosのインスタンス作成し、responseTypeかContent-Typeを指定する。
var instance = axios.create({
  'responseType': 'arraybuffer',
  'headers': {
    'Content-Type': 'image/png'
  }
});
  //こんな感じに書ける
  axios.get(url, { responseType: "arraybuffer", 'headers': {'Content-Type': 'image/png'}});