- 投稿日:2020-10-19T23:38:35+09:00
Nuxt.js × Railsでアプリ作成 CORS policy エラーの解決
やりたいこと
- Railsで作ったAPIに対してNuxt.js側から投稿する(前回の記事の続編です)
開発環境
ruby 2.6.5
Rails 6.0.3.4
node v14.7.0
yarn 1.22.4
フロント(Nuxt.js)のローカルサーバーのport番号は8000
API(Rails)のローカルサーバーのport番号は3000
投稿画面のマークアップ
- sendボタンがクリックされたら、Postmanで投稿ができることを確認できたURI
http://localhost:3000/api/v1/posts
にPOSTリクエスト
を送るような処理を実装pages/index.vue<template> <div class="container"> <h4>新規投稿</h4> <div class="form-control"> <span>Title</span> <input type="text" v-model="title" > </div> <div class="form-control"> <span>Body</span> <input type="text" v-model="body" > </div> <div class="form-control"> <button @click="postMessage">send</button> </div> </div> </template> <script> export default { data: () => ({ title: null, body: null, }), methods: { postMessage() { const url = 'http://localhost:3000/api/v1/posts'; const post = { title: this.title, body: this.body, }; this.$axios.post(url, { post }) .then(res => console.log(res.status)) .catch(error => console.log(error)); }, } } </script> <style> .container { width: 60%; max-width: 600px; margin: 0 auto; } .form-control { margin: 20px 0; } h4 { text-align: center; } span { width: 4em; display: inline-block; } input[type="text"] { width: calc(100% - 6em); } button { margin: auto; display: block; } </style>CORSでのエラーになる時の解決方法
- 上記で実装すると、console.logに下記が出力される
Access to XMLHttpRequest at 'http://localhost:3000/' from origin 'http://localhost:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
なぜ正しくリクエストが送れていないのか?
結論
Nuxt側(フロント側)からそのままURIを指定してしまうと CORSの制限がかかっているため 正しくリクエストが送れていないCORSとは
オリジン間リソース共有Cross-Origin Resource Sharing (CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組みです。
ウェブアプリケーションは、自分とは異なるオリジン (ドメイン、プロトコル、ポート番号) にあるリソースをリクエストするとき、オリジン間 HTTP リクエストを実行します。MDNより抜粋
CORS (オリジン間リソース共有) の問題を解決する
Nuxt公式ページに書いてある方法をそのまま実施します
※ 公式ページではnpmでインストールしていますが、今回はyarnで開発しているので下記コマンドを使います(npmやyarnのコマンドについてはこちらも参照ください)// @nuxtjs/proxyのインストール $ yarn add @nuxtjs/proxyapp/nuxt.config.jsmodules: [ '@nuxtjs/axios', '@nuxtjs/proxy' ], proxy: { '/api': { target: 'http://localhost:3000', pathRewrite: { '^/api' : '/api/v1' } } },
pathRewrite
の'^/api' : '/api/v1'
の記述は、 @nuxtjs/proxyのgithubを参考にしています上記では、vue側でリクエストとして指定している
/api
がつく接頭辞を/api/v1
にリライト(書き換え)て、http://localhost:3000
に送ってね、と指定していますproxyやpathRewriteについての記述方法はこのサイトも参考になりました
Nuxt側の修正
上記でProxyを設定してCORSの問題を解決する設定をしたので、NuxtのファイルでリクエストをPOSTしている箇所を修正します
pages/index.vue// 上の部分は省略 methods: { postMessage() { const url = '/api/posts'; const post = { title: this.title, body: this.body, }; this.$axios.post(url, { post }) .then(res => console.log(res.status)) .catch(error => console.log(error)); }, } // 以下省略
const url = '/api/posts';
と訂正する
※ Proxyの設定、pathRewriteの設定により、http://localhost:3000/api/v1/posts
にリクエストして、と変換されるRails側の修正
api/app/controllers/api/v1/posts_controller.rb# 上の部分は省略 private def set_post @post = Post.find(params[:id]) end def post_params params.require(:post).permit(:title, :body) end end送られてくるパラメーターは、Nuxt側でこのようなオブジェクト型で指定しているため、
require(:post)
をする必要があるpages/index.vueconst post = { title: this.title, body: this.body, };※このオブジェクト名がhogeだったら、
require(:hoge)
となる
- 投稿日:2020-10-19T22:35:01+09:00
Vue-Vuetify-Cordova コマンド集
私のスタイル
初めまして。翁と申します。
ミニマルで強迫観念やストレスなく、かつ最大限を提供する
"Huge Minimalism"
を提唱し、スタイルとして活動させていただいてます。
お手柔らかによろしくお願いいたします。あくまで"より高みへ。"を意識しており
一記事執筆5分以内と制限しております。ご理解いただけたらと思います。少しでも痒い所に手が届くような貢献が出来たらと思います。
1.Cordovaによるapk作製
vue create sample-app vue add vuetify vue add cordova cd src-cordova以下を使うことで、普通のdistへのjs吐き出しじゃなくて、cordova内に吐き出す
yarn cordova-serve-android # Development Android yarn cordova-build-android # Build Android //これそのままBuild全部、リリースまでしてくれる //その他 yarn cordova-serve-ios # Development IOS yarn cordova-build-ios # Build IOS yarn cordova-serve-browser # Development Browser yarn cordova-build-browser # Build Browser2.署名していく
署名がないとapkファイルが開けない。
1.署名
//keytool -genkey -v -keystore <鍵ファイル名> -alias <エイリアス名> -keyalg RSA -validity <有効期間> keytool -genkey -v -keystore .keystore -alias test -keyalg RSA -validity 10000 //jarsigner -verbose -keystore .keystore unsigned.apk test jarsigner -verbose -keystore .keystore unsigned.apk test2.最適化する
//zipalign -v 4 <元のapkファイル> <最適化後のapkファイル> zipalign -v 4
- 投稿日:2020-10-19T20:09:08+09:00
【Nuxt.js】ページ移動先の、非同期通信のお作法
ページ移動先で使うプロパティ
よくページ構築時で使うプロパティとして
mouted
がありますが、それだと例えばv-for
でコンポーネントを作成する時に、移動した後に構築される動きが見られてしまいます。そうならないためにも、ページコンポーネントを作成された段階には、v-forで回すデータを格納しておく必要があります。
ここで、登場するのがNuxt.jsだけに許された
asyncDataプロパティ
というものがあります。ページコンポーネント構築前の非同期通信と、後の非同期通信の比較
通信タイミング プロパティ 用途 /_idの取得 データ初期化前 async asyncData (context) コンポーネントのdataにデータを格納したい時 context.params.id データ初期化前 async fetch (context) Vuexのstateにデータを格納したい時 context.params.id データ初期化以降 async mounted () コンポーネントのdataにデータを格納したい時 this.$route.params.id mounted等と違うのは、ページロード前にデータを取得できるので、コンポーネントが完成された状態でページを表示することができる点
Usage
async asyncData(context) { const res = await context.$axios.$get(`/api/offices/${context.params.id}`); return { office: res, office_name: res.name, office_introduction: res.introduction, }; },データ初期化前の処理のため、thisや$メソッドを使うことができない
- 投稿日:2020-10-19T16:24:40+09:00
ジャルジャルの凄さを証明するために、お笑いネタ動画ランキングサイトを作った話。【個人開発】
こんにちは、かしわ(@kasiwa9494)と申します。
1年前にプログラミングを勉強し始めて、お笑いのwebサービスを今回作成しました。
何を作ったのか?
ネタTube
芸人さんの公式Youtubeチャンネルの人気の動画をランキング形式で確認できるサイト。
ざっくりいうと、ネタ(漫才、コント)だけのYoutubeの急上昇ページみたいな感じです。芸人さんの公式Youtubeチャンネルの
— かしわ (@kasiwa9494) October 18, 2020
人気ネタ(漫才、コント)を
日、週ごとに簡単に確認できる
webサービスを作りました。https://t.co/uZ72quXi4J今日の再生回数ランキング
— ネタtube (@neta_tube) October 19, 2020
第1位
『ゲップして後悔する奴』ジャルジャルのネタのタネ【JARUJARUTOWER】
第2位
【一緒に踊ろうぜ!!】ナイロンDJ 〜著作権フリー音源 NON STOP MIX〜
第3位
【コント】飲み物いただいていいですか?って30秒に一回いう女#ネタTube https://t.co/GQsNmrWvUs今週の再生回数ランキング
— ネタtube (@neta_tube) October 19, 2020
第1位
【コント】彼女はやる気満々なのに彼氏が乗る気じゃないカップルYouTuber
第2位
『雑踏、真似する奴』ジャルジャルのネタのタネ【JARUJARUTOWER】
第3位
『咳払い泣きする奴』ジャルジャルのネタのタネ【JARUJARUTOWER】#ネタTube https://t.co/bmmyqok0H6なぜ、作ったのか?
私はお笑いが好きで、TVのバラエティ番組をよくみます。
番組では、Youtubeをやっているタレント、芸人さんが
チャンネル登録者数を中心にして紹介されることが多いです。しかし、ジャルジャルがTVで紹介される時は
「毎日ネタを更新している」
この見出しで紹介されています。ここから、毎日面白いネタ(漫才、コント)を更新している芸人が
評価されるシステム(指標)がないことに気付きました。よって、「Youtubeのチャンネル登録者数」に変わるネタ(漫才、コント)だけの指標を
作りたいと考えました。毎日、毎週の再生回数の多い動画がランキング形式で紹介されれば、
ジャルジャルに限らず、たくさん面白いネタを上げている芸人さんが得するのではないかこういった気持ちでこのwebサービスを作りました。
後、今人気があるネタを確認できるサイトがあったらいいなという自分の欲望です笑
どうやって、作ったのか?
使った技術
Nuxt.js
firebase上にホスティングしています。SPAです。
Youtube Data Api
芸人さんの公式のチャンネルから再生回数、
タイトル等の情報を取得するために利用しています。Firebase
データストアとしてFirebase Firestore、
Youtube data api を使って定期実行するために、
Cloud Functions For Firebaseを利用しています。どのくらいの期間で作ったのか?
3週間で完成しました。作業時間は90~100時間ぐらいだと思います。
Cloud Functionsの扱いに慣れていなかったため、時間がかかりました。
もっと早く作れるようになりたいです。今後の展望は?
今は1日、一週間のランキングだけですが、
月ごとのランキングも追加する予定です。今回は再生回数のみのランキングのサイトだったので、
今後、再生回数やいいねでの指標に頼らず、
面白い動画を評価できるwebサービスを作ってみたいです。今回の振り返り
個人開発をしたいとずっと思っていて、中々手が出せず、
やっと、今回、お笑いwebサービス「ネタTube」をリリースできました。正直、このサービスはエンジニアなら簡単に実装できると思います。
オーソドックスのブログサービスを作る方がサービスの手間、時間はかかります。でも、どんなに簡単なものでも、自分の好きなジャンルで
webサービスを作れるのめちゃくちゃ楽しいです!!!これからも小さなwebサービスを作り続けていきたいです。
ここまで読んでくれた方へ
以上、お笑いネタ動画ランキングサイトを作った話でした。
ここまで読んでくださりありがとうございます。
芸人さんのYoutubeをよく見る方は使っていただけると嬉しいです。
ランキングに追加して欲しい芸人さんのYoutube公式チャンネルがあれば、ネタTube公式Twitterに連絡していただけるとありがたいです?
- 投稿日:2020-10-19T12:40:15+09:00
Ionic Vue のデフォルト言語をTypeScriptからJavaScriptに修正する
前提
- 2020年10月15日にionic vue が正式リリースされました。
- ionic vue のデフォルト言語TypeScriptでした。
目的
- ionic vue の開発言語をTypeScriptからJavaScriptに変更したいと思います。
修正
- TypeScriptのModuleを削除する
$ npm uninstall --save typescript @types/jest @typescript-eslint/eslint-plugin @typescript-eslint/parser @vue/cli-plugin-typescript
router/index.ts
とmain.ts
の拡張子を.ts
から.js
に変更する
.eslintrc.js
を下記のように修正する.eslintrc.jsmodule.exports = { root: true, env: { node: true }, 'extends': [ 'plugin:vue/vue3-essential', 'eslint:recommended', - '@vue/typescript/recommended' // 削除 ], parserOptions: { ecmaVersion: 2020 }, rules: { 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'vue/no-deprecated-slot-attribute': 'off', - '@typescript-eslint/no-explicit-any': 'off', // 削除 }, overrides: [ { files: [ '**/__tests__/*.{j,t}s?(x)', '**/tests/unit/**/*.spec.{j,t}s?(x)' ], env: { jest: true } } ] }
- 先程ファイルの名前を変更した
router/index.js
からArray<RouteRecordRaw>
を削除するindex.jsimport { createRouter, createWebHistory } from '@ionic/vue-router'; import { RouteRecordRaw } from 'vue-router'; import Page1 from '../views/page1.vue'; import Page2 from '../views/page2.vue'; const routes = [ // ここを変更 { path: '/', redirect: '/page1' }, { path: '/page1', name: 'Page1', component: Page1 }, { path: '/page2', name: 'Page2', component: Page2 } ] const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes }) export default router感想
- TypeScriptからJavaScriptへの変更はそんなに煩わしくなく変更することができた。
- 投稿日:2020-10-19T12:35:40+09:00
Ionic Vueが正式にリリースされたからページ遷移のあるアプリを開発してみたよ
前提
2020年10月15日にIonic Vueが正式リリースとなりました。
https://ionicframework.com/blog/announcing-ionic-vue/なので、早速ionic vueを使用してページ遷移を持ったアプリを作成してみました。
開発
準備
- 最新の ionic CLIをインストールする
npm install -g @ionic/cli@latest
- Typeに Vueを指定してionicアプリを作成する
Startコマンドの詳細
ionic start my-vue-app --type vue
- ionic vueのTree構造
. ├── babel.config.js ├── capacitor.config.json ├── cypress.json ├── ionic.config.json ├── jest.config.js ├── node_modules ├── package-lock.json ├── package.json ├── public │ ├── assets │ └── index.html ├── src │ ├── App.vue │ ├── main.ts │ ├── router │ ├── shims-vue.d.ts │ ├── theme │ └── views ├── tests │ ├── e2e │ └── unit └── tsconfig.json
- ローカルで実行する
ionic serveと出れば成功。
実装
遷移先のページを作成
src/views/page2.vue
を作成するpage2.vue
内を作成するpage2.vue<template> <ion-page> <ion-header :translucent="true"> <ion-toolbar> <ion-title>Mock Vue</ion-title> </ion-toolbar> </ion-header> <ion-content :fullscreen="true"> <ion-header collapse="condense"> <ion-toolbar> <ion-title size="large">Page 2</ion-title> </ion-toolbar> </ion-header> <div id="container"> ページ2です! </div> </ion-content> </ion-page> </template> <script lang="ts"> import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/vue'; import { defineComponent } from 'vue'; export default defineComponent({ name: 'Page2', components: { IonContent, IonHeader, IonPage, IonTitle, IonToolbar }, }); </script> <style scoped> #container { text-align: center; position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%); } #container strong { font-size: 20px; line-height: 26px; } #container p { font-size: 16px; line-height: 22px; color: #8c8c8c; margin: 0; } #container a { text-decoration: none; } </style>ルーティングを作成する
index.ts
内を下記の用意に修正index.tsimport { createRouter, createWebHistory } from '@ionic/vue-router'; import { RouteRecordRaw } from 'vue-router'; import Home from '../views/home.vue'; import Page2 from '../views/page2.vue'; const routes: Array<RouteRecordRaw> = [ { path: '/', redirect: '/home' }, { path: '/home', name: 'Home', component: Home }, { path: '/page2', // page2 の Pathの追加 name: 'Page2', component: Page2 } ] const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes }) export default routerページ遷移先の修正
home.vue
にページ遷移させるボタンを配置home.vue<template> <ion-page> <ion-header :translucent="true"> <ion-toolbar> <ion-title>Mock Vue</ion-title> </ion-toolbar> </ion-header> <ion-content :fullscreen="true"> <ion-header collapse="condense"> <ion-toolbar> <ion-title size="large">Page 1</ion-title> </ion-toolbar> </ion-header> <div id="container"> <!-- 追加 --> <ion-button @click="() => router.push('/page2')">ページ2への遷移</ion-button> </div> </ion-content> </ion-page> </template> <script lang="ts"> import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/vue'; import { useRouter } from 'vue-router'; // 追加 import { defineComponent } from 'vue'; export default defineComponent({ name: 'Home', components: { IonContent, IonHeader, IonPage, IonTitle, IonToolbar }, setup() { // 追加 const router = useRouter(); return { router }; } }); </script> <style scoped> #container { text-align: center; position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%); } #container strong { font-size: 20px; line-height: 26px; } #container p { font-size: 16px; line-height: 22px; color: #8c8c8c; margin: 0; } #container a { text-decoration: none; } </style>成果物
感想
- ionic vueのデフォルト言語はTypeScriptであったことに驚いた
- Vueは 1つのコンポーネントの処理を一つのファイルに記載できるので開発が早い
- ionic vueのルーティングはionicの独自実装ではなく、vueの公式ルーティングを使用しており、vue開発者であれば、すごくとっつきやすいと思いました。
- 投稿日:2020-10-19T09:35:43+09:00
Spotify APIについて
Spotifyって?
Spotifyは4000万以上もの曲へのアクセスを提供するデジタル音楽配信サービスです。
https://www.spotify.com/jp/Spotify APIについて
Spotify APIはpremium会員以上だと利用できます。
https://developer.spotify.com/
サクッと概要知りたい方はこちらの記事がおすすめです。
APIを叩く際に必要となるもの
client_id
client_secret
redirect_uri最低限こちらの3つが必要になります。
Spotify for Developersにて作成したアプリより取得、設定できます。手順
1.codeを取得
client_id、client_secret、redirect_uriが必要
リンクに上記を含めて叩きます。
指定したURLにリダイレクト後クエリパラメータからcodeが取得できます。2.access_tokenを取得
curlで叩いた際は簡単だったのですが、axiosから取得する際にハマりました。。
3.色々なAPIを叩いて遊んでみる
ようやくaccess_tokenが取得できたので、こちらをheadersに含めて色々なendpointを叩いてみましょう!
- 投稿日:2020-10-19T00:07:20+09:00
Vue CLI + axiosで通信する方法
【Vue.js】Vue CLIでaxiosを使って通信する
Vue CLIでaxiosを使って通信する際に躓いたため、メモ程度にまとめたのでどうぞ
バージョンなど
vue/cli 4.5.6
axios 0.20.0手順
1.プロジェクトの作成(本題ではないため割愛)
2.axiosのインストール
3.vueでaxiosの読み込み
4.テストやってみよう
1.プロジェクトの作成(本題ではないため割愛)
今回はaxiosの導入の仕方なのでプロジェクトが作成されている前提で進めます。
まだプロジェクトが出来ていない場合はこちらを参考に...2.axiosのインストール
プロジェクトに
axios
をインストールします。
インストールするにはプロジェクトのディレクトリに移動して
npm install axios
を実行するだけです。
+ axios@0.20.0 added 1 package from 1 contributor and audited 1306 packages in 4.757s 60 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
このような表示が出ればOKです。
3.vueでaxiosの読み込み
次に
axios
を読み込みます。
src/main.js
を編集します。import Vue from 'vue' import App from './App.vue' import axios from 'axios' // 今回追加 Vue.config.productionTip = false Vue.prototype.$axios = axios // 今回追加 new Vue({ axios, // 今回追加 render: h => h(App), }).$mount('#app')
今回追加
のコメントの行を追加してください次に通信を行いたいページ(今回はテストなのでデフォルトでプロジェクト作成時に作られるsrc/App.vue)に記述します
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <HelloWorld msg="Welcome to Your Vue.js App"/> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld }, // ここから created(){ this.$axios .get('https://api.coindesk.com/v1/bpi/currentprice.json') .then( response => ( console.log(response) )) } // ここまで追加 } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
ここから
とここまで追加
の間が今回追加したコードです
ページが読み込まれた時にhttps://api.coindesk.com/v1/bpi/currentprice.json と通信してBitcoin の価格を取得してコンソールに表示しています。4.テスト
作成したプロジェクトを起動させ表示させてみてください。
コンソール
に画像のような通信結果が表示されていたら成功です。
参考にさせていただいたサイト
https://jp.vuejs.org/v2/cookbook/using-axios-to-consume-apis.html
https://public-constructor.com/how-to-create-spa-with-vue/#toc9
最後まで見ていただいてありがとうございました。
- 投稿日:2020-10-19T00:07:20+09:00
Vue CLI で axios を使って通信する方法
【Vue.js】Vue CLIでaxiosを使って通信する
Vue CLIでaxiosを使って通信する際に躓いたため、メモ程度にまとめたのでどうぞ
バージョンなど
vue/cli 4.5.6
axios 0.20.0手順
1.プロジェクトの作成(本題ではないため割愛)
2.axiosのインストール
3.vueでaxiosの読み込み
4.テストやってみよう
1.プロジェクトの作成(本題ではないため割愛)
今回はaxiosの導入の仕方なのでプロジェクトが作成されている前提で進めます。
まだプロジェクトが出来ていない場合はこちらを参考に...2.axiosのインストール
プロジェクトに
axios
をインストールします。
インストールするにはプロジェクトのディレクトリに移動して
npm install axios
を実行するだけです。
+ axios@0.20.0 added 1 package from 1 contributor and audited 1306 packages in 4.757s 60 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
このような表示が出ればOKです。
3.vueでaxiosの読み込み
次に
axios
を読み込みます。
src/main.js
を編集します。import Vue from 'vue' import App from './App.vue' import axios from 'axios' // 今回追加 Vue.config.productionTip = false Vue.prototype.$axios = axios // 今回追加 new Vue({ axios, // 今回追加 render: h => h(App), }).$mount('#app')
今回追加
のコメントの行を追加してください次に通信を行いたいページ(今回はテストなのでデフォルトでプロジェクト作成時に作られるsrc/App.vue)に記述します
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <HelloWorld msg="Welcome to Your Vue.js App"/> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld }, // ここから created(){ this.$axios .get('https://api.coindesk.com/v1/bpi/currentprice.json') .then( response => ( console.log(response) )) } // ここまで追加 } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
ここから
とここまで追加
の間が今回追加したコードです
ページが読み込まれた時にhttps://api.coindesk.com/v1/bpi/currentprice.json と通信してBitcoin の価格を取得してコンソールに表示しています。4.テスト
作成したプロジェクトを起動させ表示させてみてください。
コンソール
に画像のような通信結果が表示されていたら成功です。
参考にさせていただいたサイト
https://jp.vuejs.org/v2/cookbook/using-axios-to-consume-apis.html
https://public-constructor.com/how-to-create-spa-with-vue/#toc9
最後まで見ていただいてありがとうございました。