- 投稿日:2020-09-23T23:21:53+09:00
Vue.jsでMaterial Iconsを使えるようにする
概要
Vue.jsでMaterial Iconsを使うときに毎回使い方を忘れるので、備忘も兼ねて利用方法をまとめました。
ライブラリのインストール
まずはMaterial Icons用のライブラリをインストールします。
yarn add vue-material-design-iconsコンポーネントとしてインポート
Material Design Iconsから利用したいアイコンを探してインポートします。
ファイル名はパスカルケースで宣言。ex)
account-tie
->AccountTie.vue
hoge.vueimport KabbadiIcon from 'vue-material-design-icons/Kabaddi.vue'; components: { KabbadiIcon, },templateで利用
templateでコンポーネントとして宣言することで利用できます。
公式リポジトリに使えるpropsの説明とかがあります。hoge.vue<kabaddi-icon />参考
- 投稿日:2020-09-23T23:14:56+09:00
Vue.js~jestを使ってのテスト~
はじめに
なかなかできなくてやっと簡単なテストならできたので
忘れないうちにメモ
間違いがあったらご指摘いただけると嬉しいです。テスト対象
<template> <div> <p>{{num}}</p> <button class="increment__button" @click="increment">足す</button> <button class="decrement__button" @click="decrement">引く</button> <button class="reset__button" @click="reset">リセット</button> </div> </template> <script> export default { data() { return { num: 0, }; }, methods: { increment() { return this.num++; }, decrement() { if(this.num <= 0) return return this.num--; }, reset() { return (this.num = 0); }, }, }; </script>ボタンをクリックで数字を足したり、引いたり
ただそれだけの物。そしてこれをテストしてみる
テストコード
import Test1 from '../../src/components/test1' import {mount} from '@vue/test-utils' const wrapper = mount(Test1) const vm = wrapper.vm describe('test1', () => { it('初期値は0?', () => { expect(wrapper.html()).toContain('<p>0</p>') }) it('buttonがあるか?', () => { expect(wrapper.contains('button')).toBe(true) }) }) describe('test2', () => { it('increment', () => { const button = wrapper.find('.increment__button') expect(vm.num).toBe(0) button.trigger('click') expect(vm.num).toBe(1) button.trigger('click') expect(vm.num).toBe(2) }) it('decrement', () => { vm.num = 1 const button = wrapper.find('.decrement__button') button.trigger('click') expect(vm.num).toBe(0) button.trigger('click') expect(vm.num).toBe(0) }) it('reset', () => { vm.num = 5 const button = wrapper.find('.reset__button') expect(vm.num).toBe(5) button.trigger('click') expect(vm.num).toBe(0) }) })まず始めにテスト対象のコンポーネントを
mount()
の引数に入れて
それをwrapper
として色々するみたいコンポーネントから取得
const button = wrapper.find('.increment__button')これは
Test1
コンポーネント内のclass="increment__button"
を取得
JavaScriptのdocument.getElementById()
みたいな感じ?
そして今回のだとclick
イベントが各ボタンにあるので、それをtrigger()
を使う事で実行できるbutton.trigger('click')dataの取得
wrapper.vm.num//0 wrapper.vm.num = 10 wrapper.vm.num//10これでコンポーネントの
data
のnum
の値を取得
代入もできる以上を踏まえてもう一度確認
const button = wrapper.find('.increment__button') expect(vm.num).toBe(0) button.trigger('click') expect(vm.num).toBe(1) button.trigger('click') expect(vm.num).toBe(2)最初の結果はなにもしてないので
(0)
次にclick
イベントが実行されるのでインクリメントされた結果が(1)
となる。
残り二つのボタンもやってることはほぼ同じ
今わかってるのはここまで。Vuex使用時とかのテストをできなきゃなぁ。。。
- 投稿日:2020-09-23T23:12:40+09:00
【Vue.js】Firebase独自のメソッドをまとめてみよう
firebaseモジュールのセットアップ
$ yarn add firebase --savemain.jsimport firebase from "firebase"; const config = { apiKey: "", authDomain: "", databaseURL: "", projectId: "", storageBucket: "", messagingSenderId: "" }; firebase.initializeApp(config);コンポーネントでの準備
router/index.jsimport signup from "@/components/signup"; export default new Router({ routes: [ { path: "/signup", component: signup }, ] })components/signup.vue# コンポーネント毎に、モジュール読み込み import firebase from "firebase";Usage ユーザー作成、認証系
サインアップ
signUp: function() { firebase .auth() .createUserWithEmailAndPassword(this.email, this.password) .then(user => { alert(user.email); }) .catch(error => { alert(error.message); }); }サインイン
signIn: function() { firebase .auth() .signInWithEmailAndPassword(this.email, this.password) .then(user => { alert("success"); this.$router.push("/profile"); }) .catch(error => { alert(error.message); }); }ログイン中ユーザーのデータ取得
data () { return { email: firebase.auth().currentUser.email } }ユーザーがログイン中なら、ユーザー情報を返すメソッド(ログインチェック)
firebase.auth().onAuthStateChanged(function(user) { if (user) { //ユーザーログイン時の処理 } else { //ユーザーログアウト時の処理 } })Usage クラウドデータベース
firestoreの全件データを取得
firebase.firestore().collection("message").get() .then(function(query) { query.forEach(function(doc) { console.log(doc.data()); }); }).catch(function(e) { alert(e); });firestoreの全件データの中から、条件を絞って取得
firebase.firestore().collection("message").where("name", "==", "tom").get() .then(function(query) { query.forEach(function(doc) { console.log(doc.data()); }); }).catch(function(e) { alert(e); });firestoreにデータを追加
firebase.firestore().collection("message").add({ name: this.nameData }) .then(function() { alert("成功しました"); }).catch(function(e) { alert("失敗しました"); });firestoreのデータを削除
firebase.firestore().collection("message").doc("directMessage").delete( .then(function() { alert("成功しました"); }).catch(function(e) { alert("失敗しました"); });
- 投稿日:2020-09-23T22:58:57+09:00
(´ω`) CREATE TABLEパースできて楽になって余った時間でコーヒー
なし水を飲みながら書いてるわ。つーわけで書く。Qiitaの記事を書き始めてからこの時点でフォロワーは1人増えたぐらいで全く効果がなかった。まったく俺の書く記事が幼稚でそもそも読み手の意識していないちゃらんぽらんの野郎だって思われているかもしれない。実際その通りだ。かつては丁寧に書いていた時期もあったが今では一日の30分をQiitaに放り込んでいる。まるでゴミのようにだ。読者はその事に絶句しているかもしれない。嘲笑しているかもしれない。それが俺だ。丁寧に書けばいけるんじゃね?...と考えたがこれは質の問題のように思える。今日も最低限の記事を書いて眠ろう。ソースコードはわいの手元にある。完璧に動作する状態だがこの分だと陽の目を見ることもないだろう。終わりだ。そこで今まで通りだらだら書くスタイルにした。文字通りダラダラ書く。帰宅したおっさんが寝ながら書いているのか?それより酷い。みたいに書くぞ。
何作ったの
昔、私はある会社にいた。ウェブ系の案件を任された時に作ったユーティリティだ。これはCREATE TABLE文をパース出来る。JSON形式で。この案件ではエクセルに全てのテーブルとそのテーブルのスキーマが書かれていた。列に対する名前・型・入力値検証・制約・備考などだ。プロジェクトを作りこむ内に整合性が合わなくなってくる。ソースコード上はこちらに変更したが「そういやエクセル更新忘れた」と言っても担当は俺一人だったから何も問題はなかった。引継時は大問題だが。特にここらへんはもうCREATE TABLEのコメント文として真横に記載しておいた方がいいんじゃないか。ぐらいのレベルに思えた。でもそれじゃいけない。やっぱりエクセルに纏めておかないと。ってことで作った。とにかく列名をコピペするのが嫌だったし手入力だと遅いで一発でエクセルにコピーするために作った。
何組み合わせたの
単純だ。エディタはCODE-MIRRORを利用している。UIはいつも通りFOMANTIC-UIだ。テーブルのCSV化とテーブルを画像化したいこともあると思ってPNG化もできる。CHROMEの拡張機能だ。html2Canvasを使っても出来るが全て自作するのはよろしくない。本末点灯だ。エラーも出るようにしてある。
どうやってパースしてるの?
NEARLEYだ。NEARLEYというコンパイラを使えばJSの解析器を作れる。NEARLEYに.NEというファイル(BNFベースのNEARLEY構文)をぶち込めばパーサ(.JS)を出力してくれる。俺はNEファイルを書いてない。実際はGITHUBで楽に作れるライブラリはないかと探してたんだ。解析 mysql create table 语句,用于通过建表语句生成 model 代码文件。を持ってきた。
5ファイルあって
構文はこんな感じ
ソースコード
sample.html<!doctype html> <html> <head> <title></title> <meta charset='utf-8'> <meta content='' name='author'> <meta content='' name='description'> <meta content='' name='application-name'> <meta content='notranslate' name='google'> <!-- GOOGLE:https://support.google.com/webmasters/answer/79812 --> <meta content='telephone=no,address=no,email=no,date=no,url=no' name='format-detection'> <meta content='noimageindex,notranslate,nosnippet,noarchive,nofollow,noindex' name='robots'> <meta content='width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no' name='viewport'> <link href='css/fomantic-ui/2.7.8.min.css' rel='stylesheet'> <link href='asset/manifest.json' rel='manifest'> <link href='asset/favicon.ico' rel='icon'> <style name='editor'> @import url('css/code-mirror/5.49.1.min.css'); @import url('css/code-mirror/addon-5.49.1.min.css'); @import url('css/code-mirror/mode-5.49.1.min.css'); @import url('css/code-mirror/5.49.1.min.css'); </style> <style name='font'> @font-face{ font-family:'M+2VM+IPAG circle'; src:url('asset/m+2vm+ipag-circle.ttf'); } </style> <style> html, body{ font:12px 'M+2VM+IPAG circle'; } /* * 配置(中央) */ body{ display:flex; align-items:center; justify-content:center; } main{ width:999px; height:100%; } .ui.grid{ height:100%; } /* * 見栄(凹凸) */ .ui.label, .ui.table, .ui.segment{ border-bottom:2px solid rgba(34,36,38,.15) !important; box-shadow:rgba(16, 36, 94, 0.4) 0 2px 6px 0 !important; } /* * 調整(位置) */ .ui.table, .ui.segment{ margin-top:0; } /* * 調整(全体) */ .ui.table>thead>tr>th, .ui.table>tbody>tr>td{ padding:.2em; } /* * 調整(個々) */ .ui.table>thead>tr>th:nth-child(2){ width:5em; } .ui.table>thead>tr>th:nth-child(3), .ui.table>tbody>tr>td:nth-child(3), .ui.table>thead>tr>th:nth-child(4), .ui.table>tbody>tr>td:nth-child(4), .ui.table>thead>tr>th:nth-child(5), .ui.table>tbody>tr>td:nth-child(5){ text-align:center; width:3em; } .ui.table>thead>tr>th{ text-align:center; } .ui.table>tbody>tr:hover{ cursor:pointer; } /* * 構造(エディタ) */ #editor{ display:flex; flex-direction:column; } #eidotr #editor-view{ flex:1; } #editor #editor-controller{ } /* * 設定(スクロールとフォント) */ #editor, #editor .ui.segment, #editor .ui.segment .vue-codemirror, #editor .ui.segment .vue-codemirror .CodeMirror{ height:100%; } #editor .ui.segment .vue-codemirror .CodeMirror{ font:12px 'M+2VM+IPAG circle'; } #viewer{ height:100%; overflow-y:scroll; } /* * FOMANTIC-UI(が既に指定してる) * CREATE TABLE->(sql2json):<TABLE>群は * スクロールバーがあるとみっともないので非表示 * #viewer::webkit-scrollbarは効かないので上書き */ body ::-webkit-scrollbar { display:none; } .ui.label>i.icon{ margin-right:0; } /* * FOMANTIC-UI * 2.7.8は古いFONTAWESOMEを利用中 * ので新しいフォントを入れ直して個々に定義する * path:css/fomantic-ui/themes/default/assets/fonts */ i.icon.file-csv:before {content:'\f6dd';} i.icon.file-image:before {content:'\f1c5';} /* * MODEL * CREATE-TABLEをTABLE化したモノ * 画像化した際(クロームの拡張機能による要素指定キャプチャ)影を残す * https://chrome.google.com/webstore/search/element%20capture?_category=extensions */ #viewer div.model{ padding-bottom:.7em; padding-right:.7em; padding-left:.7em; padding-top:0; } /* * sql2json * エラー時の色合わせ */ .ui.label.error-message, .CodeMirror .error-line{ background:#fff0f0 !important; color:#ff7373 !important; } </style> </head> <body> <main> <div class='ui grid internally celled'> <div class='row'> <div class='eleven wide column' id='editor'> <div class='ui labels blue' id='editor-controller'> <div class='ui label pointing below'> 全テーブル </div> <a class='ui label' target='_blank' href='https://chrome.google.com/webstore/detail/html-elements-screenshot/mckfdaahjhmnchjihljdiakamamondld?hl=ja'> <i class='icon file-image'> </i><div class='ui detail'>PNG</div> </a> <a class='ui label' target='_blank' href='https://chrome.google.com/webstore/detail/download-table-as-csv/jgeonblahchgiadgojdjilffklaihalj?hl=ja'> <i class='icon file-csv'> </i><div class='ui detail'>CSV</div> </a> <div class='ui label error-message' v-if='hasErrSql2json'> {{err.message}} </div> </div> <div class='ui segment fitted' id='editor-view'> <codemirror ref='myCm' v-model='content'> </codemirror> </div> </div> <div class='five wide column' id='viewer'> <div ref='models' v-for='(obj,n) in json'> <model v-model='json[n]'> </model> </div> </div> </div> </div> </main> </body> </html> <template id='model' type='text/x-template'> <div v-ui> <div class='ui divider horizontal'> {{table.name}} </div> <table class='ui table attached top single line unstackable celled fixed green'> <thead> <th>名</th> <th>型</th> <th>値</th> <th>虚</th> <th>加</th> </thead> <tbody> <template ref='models' v-for='(obj,i) in table.columns'> <!-- ここ修正 --> <tr v-if='hasName(obj)' :class="[{'positive':highlight[obj.name]}]" @dblclick='highlightRow(obj)'> <td><span>{{getName(obj)}}</span></td> <td><span>{{getDataType(obj)}}</span></td> <td><span>{{getDataTypeParam(obj)}}</span></td> <td> <span> <template v-if='getNullType(obj)'> <i class='icon check'> </i> </template> </span> </td> <td> <span> <template v-if='getAutoIncrementType(obj)'> <i class='icon check'> </i> </template> </span> </td> </tr> </template> </tbody> </table> </div> </template> <!-- native:code-mirror --> <script src='js/native/code-mirror/5.49.1.min.js'></script> <script src='js/native/code-mirror/addon-5.49.1.min.js'></script> <script src='js/native/code-mirror/mode-5.49.1.min.js'></script> <!-- native:sql2json --> <script src='js/native/lodash-4.17.15.min.js'></script> <script src='js/native/nearley/2.19.0.min.js'></script> <script src='js/native/nearley/grammar.js'></script> <!-- vue --> <script src='js/vue/2.6.10.js'></script> <script src='js/vue/code-mirror-4.0.6.min.js'></script> <script> Vue.directive('ui',function(el,binding,vnode){ el.classList.add(vnode.context.$options.name) }) Vue.component('model',{ template:'#model', model:{ prop:'table', event:'input' }, props:{ table:{ required:true, type:Object, default:{} } }, data:function(){ return{ highlight:{ } } }, methods:{ /* * 行色 */ highlightRow:function(obj){ if(this.hasName(obj)){ var name = obj.name var toggle = (name in this.highlight) ? !this.highlight[name] : true this.$set(this.highlight,name,toggle) } }, /* * 取得 */ getName:function(column){ return column.name }, getNullType:function(column){ if(this.hasNullType(column)){ return column.allow_null } }, getDataType:function(column){ if(this.hasDataType(column)){ return column.data_type.type } }, getDataTypeParam:function(column){ if(this.hasDataTypeParams(column)){ return column.data_type.params[0] } }, getAutoIncrementType:function(column){ if(this.hasAutoIncrementType(column)){ return column.auto_increment } }, /* * 検証 */ hasAutoIncrementType:function(obj){ return 'auto_increment' in obj }, hasDataTypeParams:function(obj){ return this.hasDataType(obj) ? 'params' in obj.data_type : false }, hasDataType:function(obj){ return 'data_type' in obj }, hasNullType:function(obj){ return 'allow_null' in obj }, hasName:function(obj){ return 'name' in obj } } }) /* * view-source:https://codemirror.net/mode/sql/ */ Vue.use(VueCodeMirror,{ options:{ scrollbarStyle : 'simple', theme : 'default', mode : 'text/x-mysql', firstLineNumber : 1, tabSize : 2, indentUnit : 2, matchTags : {bothTags: true}, htmlMode : true, autoCloseTags : true, foldGutter : true, lineNumbers : true, lineWrapping : true, styleActiveLine : true, styleActiveSelected : true, extraKeys: { 'Ctrl-A': 'autocomplete', 'Ctrl-Q': function(cm){ cm.foldCode(cm.getCursor()) }, 'F11': function(cm){ cm.setOption("fullScreen", !cm.getOption("fullScreen")) } } } }) new Vue({ el:'main', data:{ err:{ message:'', line:0, col:0 }, json:[], content:` CREATE TABLE action_protocol ( id int(11) NOT NULL AUTO_INCREMENT, createdbyuserkey varchar(40) NOT NULL DEFAULT '', userkey varchar(40) NOT NULL DEFAULT '', dt_created datetime NOT NULL DEFAULT '0000-00-00 00:00:00', servicekey varchar(40) NOT NULL DEFAULT '', information text NOT NULL, objectkey varchar(40) NOT NULL DEFAULT '', action varchar(50) DEFAULT '', PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE crm_reports ( id int(11) NOT NULL AUTO_INCREMENT, entrykey varchar(40) NOT NULL, userkey varchar(40) NOT NULL, reportname varchar(255) NOT NULL, description varchar(255) NOT NULL, tablekey varchar(40) NOT NULL, dt_created datetime NOT NULL, dt_start datetime NOT NULL, dt_end datetime NOT NULL, date_field varchar(100), displayfields text NOT NULL, specials text NOT NULL, interval varchar(255) NOT NULL, filter text NOT NULL, defaultreport int(11) NOT NULL DEFAULT '0', basedonaddressbook int(11) NOT NULL, allow_select_fields int(11) NOT NULL DEFAULT '1', PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE adminactions ( id int(11) NOT NULL AUTO_INCREMENT, dt_created datetime NOT NULL DEFAULT '0000-00-00 00:00:00', userkey varchar(50) NOT NULL DEFAULT '', urlvariables text NOT NULL, formvariables longtext NOT NULL, resellerkey varchar(50) NOT NULL DEFAULT '', companykey varchar(50) NOT NULL DEFAULT '', href text NOT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; ` }, watch:{ content:{ /* * 監視(入力) */ deep:true, handler:function(newSQL,oldSQL){ /* * 保存 */ localStorage.setItem('cache',this.content) /* * 解析 */ var self=this var editor=self.$refs.myCm.codemirror /* * 保存間隔は850ms */ var processing = _.throttle(function(){ // 消去:前回のエラー editor.removeLineClass(self.err.line,'wrap','error-line') try{ // 変換 self.sql2json() // 変換:正常 self.err.message = '' }catch(exception){ // 取得:エラーの情報と内容 var errInfo = exception.message.split('\n')[0] var errContent = exception.message.split('\n')[2] // 整形:エラーとして表示するメッセージ self.err.message = errInfo + ':' + errContent // 取得:エラーの発生した行と列(https://www.regextester.com/97589 "Syntax error at line 111 col 1:: test") self.err.line = parseInt(errInfo.match(/line\s[0-9]+/g)[0].replace('line ','')) - 1 self.err.col = parseInt(errInfo.match(/col\s[0-9]+/g)[0].replace('col ','')) // 追加:今回のエラー(https://codemirror.net/doc/manual.html#removeLineClass) self.$refs.myCm.codemirror.addLineClass(self.err.line,'wrap','error-line') } },850) /* * 処理 */ processing() /* * 表示 */ console.dir( this.json ) } } }, computed:{ hasErrSql2json:function(){ return this.err.message.length > 0 } }, methods:{ init:function(){ if('cache' in localStorage){ this.content = localStorage.getItem('cache') } }, sql2json:function(){ this.json = new nearley.Parser(grammar).feed(this.content).results[0] } }, created:function(){ this.init() this.sql2json() } }) </script>備考
CODE-MIRRORはmode/, addon/ とか別個に読み込まずにモジュール事に全ての*.jsをuglifyjs-folder使って1ファイルに纏めてる。CSSもcssclean *.css使って1ファイル化している。
さて
SQL以外にも何かできたらええよな。というお話でしたとさ。
- 投稿日:2020-09-23T21:30:54+09:00
[初心者]Rails6 Vue Postgres開発環境をDocker-Composeを使って構築する方法
はじめに
Dockerを用いてRails,Vue,Posgre環境下で開発したいなと思った時に、
Rails,Vueの環境作りに手こずりましたので自分のメモとして保存します。この記事で分かること
・Rails6とVueとPostgresのDocker環境が構築できる
・RailsとVueの連動ができる
・PryにてインスタンスとDBの操作ができる環境
MacOS Mojave
Ruby 2.6.4
Rails 6.0.3.3
Vue 2.6.12
Webpack 4.44.2
yarn 1.22.5
Docker 2.3.0.5
VScodeGithubのリンク
僕のGithubのDocker-Start-Kitです。よろしければご活用ください。
Whiro0501/Docker_Rails6_VueDocker環境をMacに構築
ターミナルを開く
mkdirで任意の名前のディレクトリを作成
cdで作成したディレクトリに移動
code.でVScodeを開くterminalmkdir qiita cd qiita code .
VScodeが起動
VScode上のターミナルで作業していくので
ターミナルが起動していなければ⬆︎+Control+@でターミナルを開くVScodeのターミナル上で以下コマンドを入力してリモートリポジトリのファイルをローカルにコピー
VScodegit clone https://github.com/Whiro0501/Docker_Rails6_Vue.gitcdでDocker_Rails6_Vue/ディレクトリに移動
VScodecd Docker_Rails6_Vue/以下コマンドを実行してDockerイメージをビルド
VScodedocker-compose build以下を実行して、必要なノードモジュールを取得
VScodedocker-compose run web yarn install --check-files以下を実行して DB(Postgres)を作成
VScodedocker-compose run web rake db:create別のターミナルを開く
以下を実行してレールズアプリケーションを起動VScode#別ターミナルが億劫なら、docker-compose up -dでも良い docker-compose upさらに別のターミナルを開く
Viewを更新するたび毎回コンパイルが発生し、時間がかかるため以下を実行VScodedocker-compose exec web ./bin/webpack-dev-serverWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Railsアプリケーションが起動することを確認
VueとRailsの連動ってどうやるの?
初期構築時点ではRailsとVueが連動されておりませんので連動させていく。
以下でhomeコントローラを作成する(コントローラー名はなんでも良い)。
VScodedocker-compose exec web rails g controller home indexindex.html.erbが作成
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p>以下ファイルに"root to: 'home#index'"を追加
routes.rbRails.application.routes.draw do root to: 'home#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000まずはindex.html.erbに記述されている内容が表示
Rails側で下地ができたので、次にVueとの連動の設定
app.vueの初期設定app.vue<template> <div id="app"> <p>{{ message }}</p> </div> </template> <script> export default { data: function () { return { message: "Hello Vue!" } } } </script> <style scoped> p { font-size: 2em; text-align: center; } </style>hello_vue.jsの初期設定
hello_vue.jsimport Vue from 'vue' import App from '../app.vue' document.addEventListener('DOMContentLoaded', () => { const app = new Vue({ render: h => h(App) }).$mount() document.body.appendChild(app.$el) console.log(app) })app.vueが単一ファイルコンポーネントであり、
hello_vue.jsにオブジェクトとして渡される。
それをindex.html.erbに表示させるよう設定する。index.html.erbを以下の通り設定
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> <%= javascript_pack_tag 'hello_vue.js' %> <%= stylesheet_pack_tag 'hello_vue.js' %>Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Vueとの連動が完了!!
Githubののファイルの説明
Whiro0501/Docker_Rails6_Vue
まず上記リンクのGithubの状態から説明する
端的に説明すると以下2つを設定した後の状態となる
従ってRails6とVueとPostgresが使用できる環境を整えることができるという理屈である。VScodedocker-compose run web rails new . --force --database=postgresql --webpack=vue加えて上記の状態だとPostgresがうまくRailsと連動できないため以下のように設定する。
こちらも公式ドキュメントを参考とした。database.ymldefault: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5 development: <<: *default database: myapp_development test: <<: *default database: myapp_test production: <<: *default database: myapp_production username: myapp password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>Dockerfile
公式ドキュメントのベストプラクティスを参照にした。
DockerはFROM, RUN, COPY毎にレイヤーが作成されるため
RUNやCOPYはできるだけまとめると少ないレイヤーで収めることができるとのこと。DockerfileFROM ruby:2.6 # `apt-get install yarn`とするとエラーになる # プロジェクトに必要なツールをインストール # &&で繋げてコマンドを実行することによりレイヤーを1つとする #apt-get update と apt-get installは同一RUN上で行う(分けると最新版を使用できない) #RUNはイメージの作成次に実行(CMDはコンテナ起動時に実行) RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update -qq && apt-get install -y nodejs postgresql-client vim && \ apt-get install -y yarn # ディレクトリの作成 RUN mkdir /myapp # 作業ディレクトリの指定 #RUN , COPY, ADD 命令のみレイヤを作成するためWORKDIRは気にしなくて良い # 絶対パスとする WORKDIR /myapp # Gemfileが更新された時のみ、レイヤを再構築 #先にプロジェクト全体をコピーしないのはレイヤーを分けるため COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock # ライブラリの依存関係をインストール RUN bundle install # プロジェクト全体をコピー(Gemfile/Gemfile.lockはコピーされない) COPY . /myapp #コンテナを起動する毎に実行されるスクリプトを追加 COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] #コンテナの公開ポート番号の指定 EXPOSE 3000 #指定しなければコンテナ起動時にデフォルトで実行する処理 #Dockerfile では CMD 命令を 1 つしか記述できない #ENTRYPOINT 命令に対するデフォルト引数としてCMDを使用可能 CMD ["rails", "server", "-b", "0.0.0.0"]docker-compose
docker-compose.ymlもDocker公式ドキュメントを参考にした。
docker-compose.ymlversion: '3' services: db: # DBにpostgresを使用 image: postgres # ホストの./tmp/dbと/var/lib/postgresql/dataを同期させる volumes: - ./tmp/db:/var/lib/postgresql/data # 環境変数の指定 environment: POSTGRES_PASSWORD: password web: build: . # コンテナ起動時にserver.pidを削除し、rails sを実行する command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" # ホストのカレントディレクトリをコンテナの/myappと同期させる volumes: - .:/myapp # ホストとコンテナ間をポートフォワードする ports: - '3000:3000' # サービス間の依存関係 depends_on: - db # Docker環境でByebugを使用 stdin_open: true tty: trueGemfile
Gemfileに関してはデフォルトで入っているもの主となる。
追加したパッケージはコメントしているため不要であれば削除して構わないGemfilesource 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.6' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.0.3', '>= 6.0.3.3' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 4.1' # Use SCSS for stylesheets gem 'sass-rails', '>= 6' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] #デバックツールの導入 gem 'pry-rails' gem 'pry-byebug' end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' #自動補完用ツールの導入 gem 'solargraph' #静的コード解析ツールの導入 gem 'rubocop' gem 'rubocop-rails' #erbのフォーマットツールの導入 gem 'htmlbeautifier' end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]package.json
package.jsonについてはvue-routerとvuexを使いたいため追加している
Vuetify等、UIフレームワークを使用したいようであれば追加する。package.json{ "name": "myapp", "private": true, "dependencies": { "@rails/actioncable": "^6.0.0", "@rails/activestorage": "^6.0.0", "@rails/ujs": "^6.0.0", "@rails/webpacker": "4.3.0", "turbolinks": "^5.2.0", "vue": "^2.6.12", "vue-loader": "^15.9.3", "vue-template-compiler": "^2.6.12", "vue-router": "^3.0.1", "vuex": "^3.0.1" }, "version": "0.1.0", "devDependencies": { "webpack-dev-server": "^3.11.0" } }Railsでデバッグする
VScode上のターミナルを開く
以下をターミナルで実行VScodedocker-compose exec web rails consolepry が起動
VScode[1] pry(main)>postコントローラーを作成
docker-compose exec web rails g controller post indexpost_controller.rbを修正
post_controller.rbclass PostController < ApplicationController def index @post = Post.all end endpostのモデルを作成
VScodedocker-compose exec web rails g model post name:string age:integerDBにモデルを反映させる
VScodedocker-compose exec web rails db:migrateindex.html.erbを以下に書き換え
index.html.erb<%= @post.name %> <%= @post.age %>routes.rbを以下に修正
routes.rbRails.application.routes.draw do root to: 'post#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endpryでPostモデルのインスタンスを作成
VScode@post = Post.new => #<Post:0x00005589bc4beb78 id: nil, name: nil, age: nil, created_at: nil, updated_at: nil> #まだnameやageにはデータを入れていない #DBに保存もされていない Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [] #DBにインスタンスを保存する @post.save (0.7ms) BEGIN Post Create (5.9ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2020-09-23 13:06:47.962085"], ["updated_at", "2020-09-23 13:06:47.962085"]] (3.1ms) COMMIT => true #もう一度Post.allをしてデータをDBから取得すると保存したインスタンスが呼び出される Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [#<Post:0x00005589bceec5f0 id: 1, name: nil, age: nil, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00>] #@postインスタンスにデータを入れてみる @post.name = "Hiro" => "Hiro" @post.age = "29" => "29" #再び保存 @post.save Post Update (4.0ms) UPDATE "posts" SET "name" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["name", "Hiro"], ["updated_at", "2020-09-23 13:10:26.486888"], ["id", 1]] Post Update (2.0ms) UPDATE "posts" SET "age" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["age", 29], ["updated_at", "2020-09-23 13:10:56.785029"], ["id", 1]] (1.0ms) COMMIT => true #データが保存されている Post.all => Post Load (1.4ms) SELECT "posts".* FROM "posts" [#<Post:0x00007f1ddc7a77a8 id: 1, name: "Hiro", age: 29, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:10:56 UTC +00:00>]Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000以下のようにDBからデータを取得できればOK
Binding.pryを試してみる
post_controller.rbを修正
class PostController < ApplicationController def index binding.pry @post = Post.all end endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000pryのターミナルに戻る
pry(main)>以上で、pryでデバッグする環境が整った
参考
以下のサイトを参考にさせていただきました。
Docker ドキュメント日本語化プロジェクト
クィックスタート: Compose と Rails
Dockerfile のベストプラクティス
Webpacker の基本的な仕組み
Dockerを使って「Rails / PostgreSQL」の開発環境を作ろう!
- 投稿日:2020-09-23T21:30:54+09:00
Rails6 Vueの連動方法(環境構築から)
はじめに
Dockerを用いてRails,Vue,Posgre環境下で開発したいなと思った時に、
Rails,Vueの環境作りに手こずりましたので自分のメモとして保存します。この記事で分かること
・Rails6とVueとPostgresのDocker環境が構築できる
・RailsとVueの連動ができる
・PryにてインスタンスとDBの操作ができる環境
MacOS Mojave
Ruby 2.6.4
Rails 6.0.3.3
Vue 2.6.12
Webpack 4.44.2
yarn 1.22.5
Docker 2.3.0.5
VScodeGithubのリンク
僕のGithubのDocker-Start-Kitです。よろしければご活用ください。
Whiro0501/Docker_Rails6_VueDocker環境をMacに構築
ターミナルを開く
mkdirで任意の名前のディレクトリを作成
cdで作成したディレクトリに移動
code.でVScodeを開くterminalmkdir qiita cd qiita code .
VScodeが起動
VScode上のターミナルで作業していくので
ターミナルが起動していなければ⬆︎+Control+@でターミナルを開くVScodeのターミナル上で以下コマンドを入力してリモートリポジトリのファイルをローカルにコピー
VScodegit clone https://github.com/Whiro0501/Docker_Rails6_Vue.gitcdでDocker_Rails6_Vue/ディレクトリに移動
VScodecd Docker_Rails6_Vue/以下コマンドを実行してDockerイメージをビルド
VScodedocker-compose build以下を実行して、必要なノードモジュールを取得
VScodedocker-compose run web yarn install --check-files以下を実行して DB(Postgres)を作成
VScodedocker-compose run web rake db:create別のターミナルを開く
以下を実行してレールズアプリケーションを起動VScode#別ターミナルが億劫なら、docker-compose up -dでも良い docker-compose upさらに別のターミナルを開く
Viewを更新するたび毎回コンパイルが発生し、時間がかかるため以下を実行VScodedocker-compose exec web ./bin/webpack-dev-serverWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Railsアプリケーションが起動することを確認
VueとRailsの連動ってどうやるの?
初期構築時点ではRailsとVueが連動されておりませんので連動させていく。
以下でhomeコントローラを作成する(コントローラー名はなんでも良い)。
VScodedocker-compose exec web rails g controller home indexindex.html.erbが作成
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p>以下ファイルに"root to: 'home#index'"を追加
routes.rbRails.application.routes.draw do root to: 'home#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000まずはindex.html.erbに記述されている内容が表示
Rails側で下地ができたので、次にVueとの連動の設定
app.vueの初期設定app.vue<template> <div id="app"> <p>{{ message }}</p> </div> </template> <script> export default { data: function () { return { message: "Hello Vue!" } } } </script> <style scoped> p { font-size: 2em; text-align: center; } </style>hello_vue.jsの初期設定
hello_vue.jsimport Vue from 'vue' import App from '../app.vue' document.addEventListener('DOMContentLoaded', () => { const app = new Vue({ render: h => h(App) }).$mount() document.body.appendChild(app.$el) console.log(app) })app.vueが単一ファイルコンポーネントであり、
hello_vue.jsにオブジェクトとして渡される。
それをindex.html.erbに表示させるよう設定する。index.html.erbを以下の通り設定
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> <%= javascript_pack_tag 'hello_vue.js' %> <%= stylesheet_pack_tag 'hello_vue.js' %>Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Vueとの連動が完了!!
Githubののファイルの説明
Whiro0501/Docker_Rails6_Vue
まず上記リンクのGithubの状態から説明する
端的に説明すると以下2つを設定した後の状態となる
従ってRails6とVueとPostgresが使用できる環境を整えることができるという理屈である。VScodedocker-compose run web rails new . --force --database=postgresql --webpack=vue加えて上記の状態だとPostgresがうまくRailsと連動できないため以下のように設定する。
こちらも公式ドキュメントを参考とした。database.ymldefault: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5 development: <<: *default database: myapp_development test: <<: *default database: myapp_test production: <<: *default database: myapp_production username: myapp password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>Dockerfile
公式ドキュメントのベストプラクティスを参照にした。
DockerはFROM, RUN, COPY毎にレイヤーが作成されるため
RUNやCOPYはできるだけまとめると少ないレイヤーで収めることができるとのこと。DockerfileFROM ruby:2.6 # `apt-get install yarn`とするとエラーになる # プロジェクトに必要なツールをインストール # &&で繋げてコマンドを実行することによりレイヤーを1つとする #apt-get update と apt-get installは同一RUN上で行う(分けると最新版を使用できない) #RUNはイメージの作成次に実行(CMDはコンテナ起動時に実行) RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update -qq && apt-get install -y nodejs postgresql-client vim && \ apt-get install -y yarn # ディレクトリの作成 RUN mkdir /myapp # 作業ディレクトリの指定 #RUN , COPY, ADD 命令のみレイヤを作成するためWORKDIRは気にしなくて良い # 絶対パスとする WORKDIR /myapp # Gemfileが更新された時のみ、レイヤを再構築 #先にプロジェクト全体をコピーしないのはレイヤーを分けるため COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock # ライブラリの依存関係をインストール RUN bundle install # プロジェクト全体をコピー(Gemfile/Gemfile.lockはコピーされない) COPY . /myapp #コンテナを起動する毎に実行されるスクリプトを追加 COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] #コンテナの公開ポート番号の指定 EXPOSE 3000 #指定しなければコンテナ起動時にデフォルトで実行する処理 #Dockerfile では CMD 命令を 1 つしか記述できない #ENTRYPOINT 命令に対するデフォルト引数としてCMDを使用可能 CMD ["rails", "server", "-b", "0.0.0.0"]docker-compose
docker-compose.ymlもDocker公式ドキュメントを参考にした。
docker-compose.ymlversion: '3' services: db: # DBにpostgresを使用 image: postgres # ホストの./tmp/dbと/var/lib/postgresql/dataを同期させる volumes: - ./tmp/db:/var/lib/postgresql/data # 環境変数の指定 environment: POSTGRES_PASSWORD: password web: build: . # コンテナ起動時にserver.pidを削除し、rails sを実行する command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" # ホストのカレントディレクトリをコンテナの/myappと同期させる volumes: - .:/myapp # ホストとコンテナ間をポートフォワードする ports: - '3000:3000' # サービス間の依存関係 depends_on: - db # Docker環境でByebugを使用 stdin_open: true tty: trueGemfile
Gemfileに関してはデフォルトで入っているもの主となる。
追加したパッケージはコメントしているため不要であれば削除して構わないGemfilesource 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.6' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.0.3', '>= 6.0.3.3' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 4.1' # Use SCSS for stylesheets gem 'sass-rails', '>= 6' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] #デバックツールの導入 gem 'pry-rails' gem 'pry-byebug' end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' #自動補完用ツールの導入 gem 'solargraph' #静的コード解析ツールの導入 gem 'rubocop' gem 'rubocop-rails' #erbのフォーマットツールの導入 gem 'htmlbeautifier' end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]package.json
package.jsonについてはvue-routerとvuexを使いたいため追加している
Vuetify等、UIフレームワークを使用したいようであれば追加する。package.json{ "name": "myapp", "private": true, "dependencies": { "@rails/actioncable": "^6.0.0", "@rails/activestorage": "^6.0.0", "@rails/ujs": "^6.0.0", "@rails/webpacker": "4.3.0", "turbolinks": "^5.2.0", "vue": "^2.6.12", "vue-loader": "^15.9.3", "vue-template-compiler": "^2.6.12", "vue-router": "^3.0.1", "vuex": "^3.0.1" }, "version": "0.1.0", "devDependencies": { "webpack-dev-server": "^3.11.0" } }Railsでデバッグする
VScode上のターミナルを開く
以下をターミナルで実行VScodedocker-compose exec web rails consolepry が起動
VScode[1] pry(main)>postコントローラーを作成
docker-compose exec web rails g controller post indexpost_controller.rbを修正
post_controller.rbclass PostController < ApplicationController def index @post = Post.all end endpostのモデルを作成
VScodedocker-compose exec web rails g model post name:string age:integerDBにモデルを反映させる
VScodedocker-compose exec web rails db:migrateindex.html.erbを以下に書き換え
index.html.erb<%= @post.name %> <%= @post.age %>routes.rbを以下に修正
routes.rbRails.application.routes.draw do root to: 'post#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endpryでPostモデルのインスタンスを作成
VScode@post = Post.new => #<Post:0x00005589bc4beb78 id: nil, name: nil, age: nil, created_at: nil, updated_at: nil> #まだnameやageにはデータを入れていない #DBに保存もされていない Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [] #DBにインスタンスを保存する @post.save (0.7ms) BEGIN Post Create (5.9ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2020-09-23 13:06:47.962085"], ["updated_at", "2020-09-23 13:06:47.962085"]] (3.1ms) COMMIT => true #もう一度Post.allをしてデータをDBから取得すると保存したインスタンスが呼び出される Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [#<Post:0x00005589bceec5f0 id: 1, name: nil, age: nil, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00>] #@postインスタンスにデータを入れてみる @post.name = "Hiro" => "Hiro" @post.age = "29" => "29" #再び保存 @post.save Post Update (4.0ms) UPDATE "posts" SET "name" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["name", "Hiro"], ["updated_at", "2020-09-23 13:10:26.486888"], ["id", 1]] Post Update (2.0ms) UPDATE "posts" SET "age" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["age", 29], ["updated_at", "2020-09-23 13:10:56.785029"], ["id", 1]] (1.0ms) COMMIT => true #データが保存されている Post.all => Post Load (1.4ms) SELECT "posts".* FROM "posts" [#<Post:0x00007f1ddc7a77a8 id: 1, name: "Hiro", age: 29, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:10:56 UTC +00:00>]Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000以下のようにDBからデータを取得できればOK
Binding.pryを試してみる
post_controller.rbを修正
class PostController < ApplicationController def index binding.pry @post = Post.all end endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000pryのターミナルに戻る
pry(main)>以上で、pryでデバッグする環境が整った
参考
以下のサイトを参考にさせていただきました。
Docker ドキュメント日本語化プロジェクト
クィックスタート: Compose と Rails
Dockerfile のベストプラクティス
Webpacker の基本的な仕組み
Dockerを使って「Rails / PostgreSQL」の開発環境を作ろう!
- 投稿日:2020-09-23T21:30:54+09:00
Rails6 Vue Postgres開発環境をDocker-Composeを使って構築する方法
はじめに
Dockerを用いてRails,Vue,Posgre環境下で開発したいなと思った時に、
Rails,Vueの環境作りに手こずりましたので自分のメモとして保存します。この記事で分かること
・Rails6とVueとPostgresのDocker環境が構築できる
・RailsとVueの連動ができる
・PryにてインスタンスとDBの操作ができる環境
MacOS Mojave
Ruby 2.6.4
Rails 6.0.3.3
Vue 2.6.12
Webpack 4.44.2
yarn 1.22.5
Docker 2.3.0.5
VScodeGithubのリンク
僕のGithubのDocker-Start-Kitです。よろしければご活用ください。
Whiro0501/Docker_Rails6_VueDocker環境をMacに構築
ターミナルを開く
mkdirで任意の名前のディレクトリを作成
cdで作成したディレクトリに移動
code.でVScodeを開くterminalmkdir qiita cd qiita code .
VScodeが起動
VScode上のターミナルで作業していくので
ターミナルが起動していなければ⬆︎+Control+@でターミナルを開くVScodeのターミナル上で以下コマンドを入力してリモートリポジトリのファイルをローカルにコピー
VScodegit clone https://github.com/Whiro0501/Docker_Rails6_Vue.gitcdでDocker_Rails6_Vue/ディレクトリに移動
VScodecd Docker_Rails6_Vue/以下コマンドを実行してDockerイメージをビルド
VScodedocker-compose build以下を実行して、必要なノードモジュールを取得
VScodedocker-compose run web yarn install --check-files以下を実行して DB(Postgres)を作成
VScodedocker-compose run web rake db:create別のターミナルを開く
以下を実行してレールズアプリケーションを起動VScode#別ターミナルが億劫なら、docker-compose up -dでも良い docker-compose upさらに別のターミナルを開く
Viewを更新するたび毎回コンパイルが発生し、時間がかかるため以下を実行VScodedocker-compose exec web ./bin/webpack-dev-serverWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Railsアプリケーションが起動することを確認
VueとRailsの連動ってどうやるの?
初期構築時点ではRailsとVueが連動されておりませんので連動させていく。
以下でhomeコントローラを作成する(コントローラー名はなんでも良い)。
VScodedocker-compose exec web rails g controller home indexindex.html.erbが作成
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p>以下ファイルに"root to: 'home#index'"を追加
routes.rbRails.application.routes.draw do root to: 'home#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000まずはindex.html.erbに記述されている内容が表示
Rails側で下地ができたので、次にVueとの連動の設定
app.vueの初期設定app.vue<template> <div id="app"> <p>{{ message }}</p> </div> </template> <script> export default { data: function () { return { message: "Hello Vue!" } } } </script> <style scoped> p { font-size: 2em; text-align: center; } </style>hello_vue.jsの初期設定
hello_vue.jsimport Vue from 'vue' import App from '../app.vue' document.addEventListener('DOMContentLoaded', () => { const app = new Vue({ render: h => h(App) }).$mount() document.body.appendChild(app.$el) console.log(app) })app.vueが単一ファイルコンポーネントであり、
hello_vue.jsにオブジェクトとして渡される。
それをindex.html.erbに表示させるよう設定する。index.html.erbを以下の通り設定
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> <%= javascript_pack_tag 'hello_vue.js' %> <%= stylesheet_pack_tag 'hello_vue.js' %>Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Vueとの連動が完了!!
Githubののファイルの説明
Whiro0501/Docker_Rails6_Vue
まず上記リンクのGithubの状態から説明する
端的に説明すると以下2つを設定した後の状態となる
従ってRails6とVueとPostgresが使用できる環境を整えることができるという理屈である。VScodedocker-compose run web rails new . --force --database=postgresql --webpack=vue加えて上記の状態だとPostgresがうまくRailsと連動できないため以下のように設定する。
こちらも公式ドキュメントを参考とした。database.ymldefault: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5 development: <<: *default database: myapp_development test: <<: *default database: myapp_test production: <<: *default database: myapp_production username: myapp password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>Dockerfile
公式ドキュメントのベストプラクティスを参照にした。
DockerはFROM, RUN, COPY毎にレイヤーが作成されるため
RUNやCOPYはできるだけまとめると少ないレイヤーで収めることができるとのこと。DockerfileFROM ruby:2.6 # `apt-get install yarn`とするとエラーになる # プロジェクトに必要なツールをインストール # &&で繋げてコマンドを実行することによりレイヤーを1つとする #apt-get update と apt-get installは同一RUN上で行う(分けると最新版を使用できない) #RUNはイメージの作成次に実行(CMDはコンテナ起動時に実行) RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update -qq && apt-get install -y nodejs postgresql-client vim && \ apt-get install -y yarn # ディレクトリの作成 RUN mkdir /myapp # 作業ディレクトリの指定 #RUN , COPY, ADD 命令のみレイヤを作成するためWORKDIRは気にしなくて良い # 絶対パスとする WORKDIR /myapp # Gemfileが更新された時のみ、レイヤを再構築 #先にプロジェクト全体をコピーしないのはレイヤーを分けるため COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock # ライブラリの依存関係をインストール RUN bundle install # プロジェクト全体をコピー(Gemfile/Gemfile.lockはコピーされない) COPY . /myapp #コンテナを起動する毎に実行されるスクリプトを追加 COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] #コンテナの公開ポート番号の指定 EXPOSE 3000 #指定しなければコンテナ起動時にデフォルトで実行する処理 #Dockerfile では CMD 命令を 1 つしか記述できない #ENTRYPOINT 命令に対するデフォルト引数としてCMDを使用可能 CMD ["rails", "server", "-b", "0.0.0.0"]docker-compose
docker-compose.ymlもDocker公式ドキュメントを参考にした。
docker-compose.ymlversion: '3' services: db: # DBにpostgresを使用 image: postgres # ホストの./tmp/dbと/var/lib/postgresql/dataを同期させる volumes: - ./tmp/db:/var/lib/postgresql/data # 環境変数の指定 environment: POSTGRES_PASSWORD: password web: build: . # コンテナ起動時にserver.pidを削除し、rails sを実行する command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" # ホストのカレントディレクトリをコンテナの/myappと同期させる volumes: - .:/myapp # ホストとコンテナ間をポートフォワードする ports: - '3000:3000' # サービス間の依存関係 depends_on: - db # Docker環境でByebugを使用 stdin_open: true tty: trueGemfile
Gemfileに関してはデフォルトで入っているもの主となる。
追加したパッケージはコメントしているため不要であれば削除して構わないGemfilesource 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.6' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.0.3', '>= 6.0.3.3' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 4.1' # Use SCSS for stylesheets gem 'sass-rails', '>= 6' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] #デバックツールの導入 gem 'pry-rails' gem 'pry-byebug' end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' #自動補完用ツールの導入 gem 'solargraph' #静的コード解析ツールの導入 gem 'rubocop' gem 'rubocop-rails' #erbのフォーマットツールの導入 gem 'htmlbeautifier' end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]package.json
package.jsonについてはvue-routerとvuexを使いたいため追加している
Vuetify等、UIフレームワークを使用したいようであれば追加する。package.json{ "name": "myapp", "private": true, "dependencies": { "@rails/actioncable": "^6.0.0", "@rails/activestorage": "^6.0.0", "@rails/ujs": "^6.0.0", "@rails/webpacker": "4.3.0", "turbolinks": "^5.2.0", "vue": "^2.6.12", "vue-loader": "^15.9.3", "vue-template-compiler": "^2.6.12", "vue-router": "^3.0.1", "vuex": "^3.0.1" }, "version": "0.1.0", "devDependencies": { "webpack-dev-server": "^3.11.0" } }Railsでデバッグする
VScode上のターミナルを開く
以下をターミナルで実行VScodedocker-compose exec web rails consolepry が起動
VScode[1] pry(main)>postコントローラーを作成
docker-compose exec web rails g controller post indexpost_controller.rbを修正
post_controller.rbclass PostController < ApplicationController def index @post = Post.all end endpostのモデルを作成
VScodedocker-compose exec web rails g model post name:string age:integerDBにモデルを反映させる
VScodedocker-compose exec web rails db:migrateindex.html.erbを以下に書き換え
index.html.erb<%= @post.name %> <%= @post.age %>routes.rbを以下に修正
routes.rbRails.application.routes.draw do root to: 'post#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endpryでPostモデルのインスタンスを作成
VScode@post = Post.new => #<Post:0x00005589bc4beb78 id: nil, name: nil, age: nil, created_at: nil, updated_at: nil> #まだnameやageにはデータを入れていない #DBに保存もされていない Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [] #DBにインスタンスを保存する @post.save (0.7ms) BEGIN Post Create (5.9ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2020-09-23 13:06:47.962085"], ["updated_at", "2020-09-23 13:06:47.962085"]] (3.1ms) COMMIT => true #もう一度Post.allをしてデータをDBから取得すると保存したインスタンスが呼び出される Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [#<Post:0x00005589bceec5f0 id: 1, name: nil, age: nil, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00>] #@postインスタンスにデータを入れてみる @post.name = "Hiro" => "Hiro" @post.age = "29" => "29" #再び保存 @post.save Post Update (4.0ms) UPDATE "posts" SET "name" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["name", "Hiro"], ["updated_at", "2020-09-23 13:10:26.486888"], ["id", 1]] Post Update (2.0ms) UPDATE "posts" SET "age" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["age", 29], ["updated_at", "2020-09-23 13:10:56.785029"], ["id", 1]] (1.0ms) COMMIT => true #データが保存されている Post.all => Post Load (1.4ms) SELECT "posts".* FROM "posts" [#<Post:0x00007f1ddc7a77a8 id: 1, name: "Hiro", age: 29, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:10:56 UTC +00:00>]Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000以下のようにDBからデータを取得できればOK
Binding.pryを試してみる
post_controller.rbを修正
class PostController < ApplicationController def index binding.pry @post = Post.all end endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000pryのターミナルに戻る
pry(main)>以上で、pryでデバッグする環境が整った
参考
以下のサイトを参考にさせていただきました。
Docker ドキュメント日本語化プロジェクト
クィックスタート: Compose と Rails
Dockerfile のベストプラクティス
Webpacker の基本的な仕組み
Dockerを使って「Rails / PostgreSQL」の開発環境を作ろう!
- 投稿日:2020-09-23T21:30:54+09:00
Rails6 Vueの開発環境の構築
はじめに
Dockerを用いてRails,Vue,Posgre環境下で開発したいなと思った時に、
Rails,Vueの環境作りに手こずりましたので自分のメモとして保存します。この記事で分かること
・Rails6とVueとPostgresのDocker環境が構築できる
・RailsとVueの連動ができる
・PryにてインスタンスとDBの操作ができる環境
MacOS Mojave
Ruby 2.6.4
Rails 6.0.3.3
Vue 2.6.12
Webpack 4.44.2
yarn 1.22.5
Docker 2.3.0.5
VScodeGithubのリンク
僕のGithubのDocker-Start-Kitです。よろしければご活用ください。
Whiro0501/Docker_Rails6_VueDocker環境をMacに構築
ターミナルを開く
mkdirで任意の名前のディレクトリを作成
cdで作成したディレクトリに移動
code.でVScodeを開くterminalmkdir qiita cd qiita code .
VScodeが起動
VScode上のターミナルで作業していくので
ターミナルが起動していなければ⬆︎+Control+@でターミナルを開くVScodeのターミナル上で以下コマンドを入力してリモートリポジトリのファイルをローカルにコピー
VScodegit clone https://github.com/Whiro0501/Docker_Rails6_Vue.gitcdでDocker_Rails6_Vue/ディレクトリに移動
VScodecd Docker_Rails6_Vue/以下コマンドを実行してDockerイメージをビルド
VScodedocker-compose build以下を実行して、必要なノードモジュールを取得
VScodedocker-compose run web yarn install --check-files以下を実行して DB(Postgres)を作成
VScodedocker-compose run web rake db:create別のターミナルを開く
以下を実行してレールズアプリケーションを起動VScode#別ターミナルが億劫なら、docker-compose up -dでも良い docker-compose upさらに別のターミナルを開く
Viewを更新するたび毎回コンパイルが発生し、時間がかかるため以下を実行VScodedocker-compose exec web ./bin/webpack-dev-serverWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Railsアプリケーションが起動することを確認
VueとRailsの連動ってどうやるの?
初期構築時点ではRailsとVueが連動されておりませんので連動させていく。
以下でhomeコントローラを作成する(コントローラー名はなんでも良い)。
VScodedocker-compose exec web rails g controller home indexindex.html.erbが作成
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p>以下ファイルに"root to: 'home#index'"を追加
routes.rbRails.application.routes.draw do root to: 'home#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000まずはindex.html.erbに記述されている内容が表示
Rails側で下地ができたので、次にVueとの連動の設定
app.vueの初期設定app.vue<template> <div id="app"> <p>{{ message }}</p> </div> </template> <script> export default { data: function () { return { message: "Hello Vue!" } } } </script> <style scoped> p { font-size: 2em; text-align: center; } </style>hello_vue.jsの初期設定
hello_vue.jsimport Vue from 'vue' import App from '../app.vue' document.addEventListener('DOMContentLoaded', () => { const app = new Vue({ render: h => h(App) }).$mount() document.body.appendChild(app.$el) console.log(app) })app.vueが単一ファイルコンポーネントであり、
hello_vue.jsにオブジェクトとして渡される。
それをindex.html.erbに表示させるよう設定する。index.html.erbを以下の通り設定
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> <%= javascript_pack_tag 'hello_vue.js' %> <%= stylesheet_pack_tag 'hello_vue.js' %>Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Vueとの連動が完了!!
Githubののファイルの説明
Whiro0501/Docker_Rails6_Vue
まず上記リンクのGithubの状態から説明する
端的に説明すると以下2つを設定した後の状態となる
従ってRails6とVueとPostgresが使用できる環境を整えることができるという理屈である。VScodedocker-compose run web rails new . --force --database=postgresql --webpack=vue加えて上記の状態だとPostgresがうまくRailsと連動できないため以下のように設定する。
こちらも公式ドキュメントを参考とした。database.ymldefault: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5 development: <<: *default database: myapp_development test: <<: *default database: myapp_test production: <<: *default database: myapp_production username: myapp password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>Dockerfile
公式ドキュメントのベストプラクティスを参照にした。
DockerはFROM, RUN, COPY毎にレイヤーが作成されるため
RUNやCOPYはできるだけまとめると少ないレイヤーで収めることができるとのこと。DockerfileFROM ruby:2.6 # `apt-get install yarn`とするとエラーになる # プロジェクトに必要なツールをインストール # &&で繋げてコマンドを実行することによりレイヤーを1つとする #apt-get update と apt-get installは同一RUN上で行う(分けると最新版を使用できない) #RUNはイメージの作成次に実行(CMDはコンテナ起動時に実行) RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update -qq && apt-get install -y nodejs postgresql-client vim && \ apt-get install -y yarn # ディレクトリの作成 RUN mkdir /myapp # 作業ディレクトリの指定 #RUN , COPY, ADD 命令のみレイヤを作成するためWORKDIRは気にしなくて良い # 絶対パスとする WORKDIR /myapp # Gemfileが更新された時のみ、レイヤを再構築 #先にプロジェクト全体をコピーしないのはレイヤーを分けるため COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock # ライブラリの依存関係をインストール RUN bundle install # プロジェクト全体をコピー(Gemfile/Gemfile.lockはコピーされない) COPY . /myapp #コンテナを起動する毎に実行されるスクリプトを追加 COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] #コンテナの公開ポート番号の指定 EXPOSE 3000 #指定しなければコンテナ起動時にデフォルトで実行する処理 #Dockerfile では CMD 命令を 1 つしか記述できない #ENTRYPOINT 命令に対するデフォルト引数としてCMDを使用可能 CMD ["rails", "server", "-b", "0.0.0.0"]docker-compose
docker-compose.ymlもDocker公式ドキュメントを参考にした。
docker-compose.ymlversion: '3' services: db: # DBにpostgresを使用 image: postgres # ホストの./tmp/dbと/var/lib/postgresql/dataを同期させる volumes: - ./tmp/db:/var/lib/postgresql/data # 環境変数の指定 environment: POSTGRES_PASSWORD: password web: build: . # コンテナ起動時にserver.pidを削除し、rails sを実行する command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" # ホストのカレントディレクトリをコンテナの/myappと同期させる volumes: - .:/myapp # ホストとコンテナ間をポートフォワードする ports: - '3000:3000' # サービス間の依存関係 depends_on: - db # Docker環境でByebugを使用 stdin_open: true tty: trueGemfile
Gemfileに関してはデフォルトで入っているもの主となる。
追加したパッケージはコメントしているため不要であれば削除して構わないGemfilesource 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.6' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.0.3', '>= 6.0.3.3' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 4.1' # Use SCSS for stylesheets gem 'sass-rails', '>= 6' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] #デバックツールの導入 gem 'pry-rails' gem 'pry-byebug' end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' #自動補完用ツールの導入 gem 'solargraph' #静的コード解析ツールの導入 gem 'rubocop' gem 'rubocop-rails' #erbのフォーマットツールの導入 gem 'htmlbeautifier' end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]package.json
package.jsonについてはvue-routerとvuexを使いたいため追加している
Vuetify等、UIフレームワークを使用したいようであれば追加する。package.json{ "name": "myapp", "private": true, "dependencies": { "@rails/actioncable": "^6.0.0", "@rails/activestorage": "^6.0.0", "@rails/ujs": "^6.0.0", "@rails/webpacker": "4.3.0", "turbolinks": "^5.2.0", "vue": "^2.6.12", "vue-loader": "^15.9.3", "vue-template-compiler": "^2.6.12", "vue-router": "^3.0.1", "vuex": "^3.0.1" }, "version": "0.1.0", "devDependencies": { "webpack-dev-server": "^3.11.0" } }Railsでデバッグする
VScode上のターミナルを開く
以下をターミナルで実行VScodedocker-compose exec web rails consolepry が起動
VScode[1] pry(main)>postコントローラーを作成
docker-compose exec web rails g controller post indexpost_controller.rbを修正
post_controller.rbclass PostController < ApplicationController def index @post = Post.all end endpostのモデルを作成
VScodedocker-compose exec web rails g model post name:string age:integerDBにモデルを反映させる
VScodedocker-compose exec web rails db:migrateindex.html.erbを以下に書き換え
index.html.erb<%= @post.name %> <%= @post.age %>routes.rbを以下に修正
routes.rbRails.application.routes.draw do root to: 'post#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endpryでPostモデルのインスタンスを作成
VScode@post = Post.new => #<Post:0x00005589bc4beb78 id: nil, name: nil, age: nil, created_at: nil, updated_at: nil> #まだnameやageにはデータを入れていない #DBに保存もされていない Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [] #DBにインスタンスを保存する @post.save (0.7ms) BEGIN Post Create (5.9ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2020-09-23 13:06:47.962085"], ["updated_at", "2020-09-23 13:06:47.962085"]] (3.1ms) COMMIT => true #もう一度Post.allをしてデータをDBから取得すると保存したインスタンスが呼び出される Post.all => Post Load (2.2ms) SELECT "posts".* FROM "posts" [#<Post:0x00005589bceec5f0 id: 1, name: nil, age: nil, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00>] #@postインスタンスにデータを入れてみる @post.name = "Hiro" => "Hiro" @post.age = "29" => "29" #再び保存 @post.save Post Update (4.0ms) UPDATE "posts" SET "name" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["name", "Hiro"], ["updated_at", "2020-09-23 13:10:26.486888"], ["id", 1]] Post Update (2.0ms) UPDATE "posts" SET "age" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["age", 29], ["updated_at", "2020-09-23 13:10:56.785029"], ["id", 1]] (1.0ms) COMMIT => true #データが保存されている Post.all => Post Load (1.4ms) SELECT "posts".* FROM "posts" [#<Post:0x00007f1ddc7a77a8 id: 1, name: "Hiro", age: 29, created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00, updated_at: Wed, 23 Sep 2020 13:10:56 UTC +00:00>]Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000以下のようにDBからデータを取得できればOK
Binding.pryを試してみる
post_controller.rbを修正
class PostController < ApplicationController def index binding.pry @post = Post.all end endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000pryのターミナルに戻る
pry(main)>以上で、pryでデバッグする環境が整った
参考
以下のサイトを参考にさせていただきました。
Docker ドキュメント日本語化プロジェクト
クィックスタート: Compose と Rails
Dockerfile のベストプラクティス
Webpacker の基本的な仕組み
Dockerを使って「Rails / PostgreSQL」の開発環境を作ろう!
- 投稿日:2020-09-23T21:30:54+09:00
[初心者]Rails6-Vue-Postgres開発環境をDocker-Composeを使って構築する方法
はじめに
Dockerを用いてRails,Vue,Posgre環境下で開発したいなと思った時に、
Rails,Vueの環境作りに手こずりましたので自分のメモとして保存します。環境
MacOS Mojave
Ruby 2.6.4
Rails 6.0.3.3
Vue 2.6.12
Webpack 4.44.2
yarn 1.22.5
Docker 2.3.0.5
VScodeGithubのリンク
僕のGithubのDocker-Start-Kitです。よろしければご活用ください。
Whiro0501/Docker_Rails6_VueDocker環境をMacに構築
ターミナルを開く
mkdirで任意の名前のディレクトリを作成
cdで作成したディレクトリに移動
code.でVScodeを開くterminalmkdir qiita cd qiita code .
VScodeが起動
VScode上のターミナルで作業していくので
ターミナルが起動していなければ⬆︎+Control+@でターミナルを開くVScodeのターミナル上で以下コマンドを入力してリモートリポジトリのファイルをローカルにコピー
VScodegit clone https://github.com/Whiro0501/Docker_Rails6_Vue.gitcdでDocker_Rails6_Vue/ディレクトリに移動
VScodecd Docker_Rails6_Vue/以下コマンドを実行してDockerイメージをビルド
VScodedocker-compose build以下を実行して、必要なノードモジュールを取得
VScodedocker-compose run web yarn install --check-files以下を実行して DB(Postgres)を作成
VScodedocker-compose run web rake db:create別のターミナルを開く
以下を実行してレールズアプリケーションを起動VScode#別ターミナルが億劫なら、docker-compose up -dでも良い docker-compose upさらに別のターミナルを開く
Viewを更新するたび毎回コンパイルが発生し、時間がかかるため以下を実行VScodedocker-compose exec web ./bin/webpack-dev-serverWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Railsアプリケーションが起動することを確認
VueとRailsの連動ってどうやるの?
初期構築時点ではRailsとVueが連動されておりませんので連動させていく。
以下でhomeコントローラを作成する(コントローラー名はなんでも良い)。
VScodedocker-compose exec web rails g controller home indexindex.html.erbが作成
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p>以下ファイルに"root to: 'home#index'"を追加
routes.rbRails.application.routes.draw do root to: 'home#index' # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html endWebブラウザで以下にアクセス
Webブラウザhttp://localhost:3000まずはindex.html.erbに記述されている内容が表示
Rails側で下地ができたので、次にVueとの連動の設定
app.vueの初期設定app.vue<template> <div id="app"> <p>{{ message }}</p> </div> </template> <script> export default { data: function () { return { message: "Hello Vue!" } } } </script> <style scoped> p { font-size: 2em; text-align: center; } </style>hello_vue.jsの初期設定
hello_vue.jsimport Vue from 'vue' import App from '../app.vue' document.addEventListener('DOMContentLoaded', () => { const app = new Vue({ render: h => h(App) }).$mount() document.body.appendChild(app.$el) console.log(app) })app.vueが単一ファイルコンポーネントであり、
hello_vue.jsにオブジェクトとして渡される。
それをindex.html.erbに表示させるよう設定する。index.html.erbを以下の通り設定
index.html.erb<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> <%= javascript_pack_tag 'hello_vue.js' %> <%= stylesheet_pack_tag 'hello_vue.js' %>Webブラウザで以下にアクセス
Webブラウザhttp://localhost:3000Vueとの連動が完了!!
Githubののファイルの説明
Whiro0501/Docker_Rails6_Vue
まず上記リンクのGithubの状態から説明する
端的に説明すると以下2つを設定した後の状態となる
従ってRails6とVueとPostgresが使用できる環境を整えることができるという理屈である。VScodedocker-compose run web rails new . --force --database=postgresql --webpack=vue加えて上記の状態だとPostgresがうまくRailsと連動できないため以下のように設定する。
こちらも公式ドキュメントを参考とした。database.ymldefault: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5 development: <<: *default database: myapp_development test: <<: *default database: myapp_test production: <<: *default database: myapp_production username: myapp password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>Dockerfile
公式ドキュメントのベストプラクティスを参照にした。
DockerはFROM, RUN, COPY毎にレイヤーが作成されるため
RUNやCOPYはできるだけまとめると少ないレイヤーで収めることができるとのこと。DockerfileFROM ruby:2.6 # `apt-get install yarn`とするとエラーになる # プロジェクトに必要なツールをインストール # &&で繋げてコマンドを実行することによりレイヤーを1つとする #apt-get update と apt-get installは同一RUN上で行う(分けると最新版を使用できない) #RUNはイメージの作成次に実行(CMDはコンテナ起動時に実行) RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update -qq && apt-get install -y nodejs postgresql-client vim && \ apt-get install -y yarn # ディレクトリの作成 RUN mkdir /myapp # 作業ディレクトリの指定 #RUN , COPY, ADD 命令のみレイヤを作成するためWORKDIRは気にしなくて良い # 絶対パスとする WORKDIR /myapp # Gemfileが更新された時のみ、レイヤを再構築 #先にプロジェクト全体をコピーしないのはレイヤーを分けるため COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock # ライブラリの依存関係をインストール RUN bundle install # プロジェクト全体をコピー(Gemfile/Gemfile.lockはコピーされない) COPY . /myapp #コンテナを起動する毎に実行されるスクリプトを追加 COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] #コンテナの公開ポート番号の指定 EXPOSE 3000 #指定しなければコンテナ起動時にデフォルトで実行する処理 #Dockerfile では CMD 命令を 1 つしか記述できない #ENTRYPOINT 命令に対するデフォルト引数としてCMDを使用可能 CMD ["rails", "server", "-b", "0.0.0.0"]docker-compose
docker-compose.ymlもDocker公式ドキュメントを参考にした。
docker-compose.ymlversion: '3' services: db: # DBにpostgresを使用 image: postgres # ホストの./tmp/dbと/var/lib/postgresql/dataを同期させる volumes: - ./tmp/db:/var/lib/postgresql/data # 環境変数の指定 environment: POSTGRES_PASSWORD: password web: build: . # コンテナ起動時にserver.pidを削除し、rails sを実行する command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" # ホストのカレントディレクトリをコンテナの/myappと同期させる volumes: - .:/myapp # ホストとコンテナ間をポートフォワードする ports: - '3000:3000' # サービス間の依存関係 depends_on: - db # Docker環境でByebugを使用 stdin_open: true tty: trueGemfile
Gemfileに関してはデフォルトで入っているもの主となる。
追加したパッケージはコメントしているため不要であれば削除して構わないGemfilesource 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.6' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.0.3', '>= 6.0.3.3' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 4.1' # Use SCSS for stylesheets gem 'sass-rails', '>= 6' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] #デバックツールの導入 gem 'pry-rails' gem 'pry-byebug' end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' #自動補完用ツールの導入 gem 'solargraph' #静的コード解析ツールの導入 gem 'rubocop' gem 'rubocop-rails' #erbのフォーマットツールの導入 gem 'htmlbeautifier' end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]package.json
package.jsonについてはvue-routerとvuexを使いたいため追加している
Vuetify等、UIフレームワークを使用したいようであれば追加する。package.json{ "name": "myapp", "private": true, "dependencies": { "@rails/actioncable": "^6.0.0", "@rails/activestorage": "^6.0.0", "@rails/ujs": "^6.0.0", "@rails/webpacker": "4.3.0", "turbolinks": "^5.2.0", "vue": "^2.6.12", "vue-loader": "^15.9.3", "vue-template-compiler": "^2.6.12", "vue-router": "^3.0.1", "vuex": "^3.0.1" }, "version": "0.1.0", "devDependencies": { "webpack-dev-server": "^3.11.0" } }参考
以下のサイトを参考にさせていただきました。
Docker ドキュメント日本語化プロジェクト
クィックスタート: Compose と Rails
Dockerfile のベストプラクティス
Webpacker の基本的な仕組み
Dockerを使って「Rails / PostgreSQL」の開発環境を作ろう!
- 投稿日:2020-09-23T20:12:57+09:00
Vueで著作権ページを表示したいときどうするか
前提
- 以下記載のコードはそのままコピペしても動作は保証していません
環境
- macOS 10.15.6
- OnsenUI
検討
- nodeライブラリを使用しているということで、すべての著作権はnode_modules配下にある
- そこからライセンスを抜き出し表示すれば良い
手順
jsonファイルを作成する
- このシェルを使用し、jsonファイルを作成する
- ※生成されたjsonファイルは完璧ではございません
- 生成されたjsonファイルから以下を行う
- 一番下の
,
を削除する- 外枠の
{}
を追加する- 改行を全て削除する
generateJson.sh#!/bin/bash for i in `ls node_modules/*/LICENSE node_modules/*/LICENCE`; do license_name=$(echo $i|sed 's/node_modules\///g'|sed 's/\/LICENSE//g'|sed 's/\/LICENCE//g'); license_text=$(cat ${i}|sed -e 's/\"/\\\"/g'); json=$(printf ' "%s": { "license_name": "%s", "license_text": "%s" },' "${license_name}" "${license_name}" "${license_text}") echo ${json} done > ./licenses.json著作権をリストで表示するページを作成する
- 上記で作成したjsonファイルをimportし、ライセンスの名前をリストで表示する
Copyright.vue<template> <v-ons-page> <v-ons-list class="scroll_erea"> <v-ons-list-item v-for="(license, key) in licenses" :key="key" class="copyright__item" @click="onLicenseClick(license, key)"> <div class="copyright__item__title"> {{ key }} </div> </v-ons-list-item> </v-ons-list> </v-ons-page> </template> <script> import CopyrightDetail from '@/components/pages/CopyrightDetail' import licensesJson from '@licenses' export default { name: 'Copyright', data () { return { licenses: licensesJson { methods: { onLicenseClick (license, key) { const props = { licenseName: license.license_name, licenseText: license.license_text } // ここにCopyrightDetailページにpropsを渡して遷移する処理を入れてください } } } </script> <style lang="scss" scoped> .scroll_erea { position: absolute; margin: 0 auto; width: 100%; height: 100%; overflow-y: scroll; } </style>著作権の詳細を表示するページを作成する
- propsで受け取った著作権の詳細テキストを表示する
CopyrightDetail.vue<template> <v-ons-page> {{ licenseText }} </v-ons-page> </template> <script> import { mapMutations } from 'vuex' export default { name: 'CopyrightDetail', props: { licenseName: { type: String, required: true }, licenseText: { type: String, required: true } } } </script>こうなったらいいのにと思うこと
- シェル一髪で著作権のjsonファイルを作成できる
- nodeのライブラリが多すぎるとDOMレンダリングのforループでかなり時間がかかるため、そこを短縮する処理を入れる
おわりに
- こうすればnodeライブラリの著作権情報をVueで簡単に表示できるよ、などあれば教えてください
- 投稿日:2020-09-23T18:00:56+09:00
【Vue.js】Vue.jsの基礎知識
Vue.js とは
- javascriptのフレームワークの一つ。
- JQueryよりも記述が簡単。
- ディレクティブ機能により、HTMLとjavascriptの間でデータ連携を行う役割を果たす。
- Raectが単方向のデータバインディングであるのに対し、Vue.jsは双方向のデータバインディングが可能(※)。
- React、Angularに並び人気があるフレームワーク。
- ECMAScript 5 準拠のブラウザに対応。IE8以前のバージョンはサポートされていないため注意。 (詳しくはこちらを参照)
※双方向データバインディング:
UI、データのいずれか一方が更新されれば、もう一方も更新される仕組みのこと。(=データとUIが常に同期される)Vue.jsの読み込み(インストール)
事前にお使いのブラウザにVue Devtoolsをインストールしておくことをお勧めします。
筆者はchromeを使うので拡張機能vuejs-devtoolsを入れました。Vue.jsの読み込み方法
- CDN ←プロトタイピングや学習を目的とする場合はこちらがオススメ
- NPM
- 直接組み込み
今回は学習用なので、CDNを読み込みました。
下記コードをbody終了タグの直前に挿入すれば完了。
html<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script> or <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>(例1)html内にスクリプトを記述する場合
html<body> <!-- html --> <div> <span>TEST</span> </div> <!-- js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> // js記述部分 </script> </body>(例2)jsファイルを別途作成する場合
html<body> <!-- html --> <div> <span>TEST</span> </div> <!-- js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="js/test.js"></script> // vue.jsの下で読み込むこと </body>Vue.jsの基礎
目次
1.マスタッシュ構文(単方向データバインディング)
2.ディレクティブ
2-1.v-bind
2-2.v-if
2-3.v-show
2-4.v-for
2-5.v-on
2-6.v-model(双方向データバインディング)
3.コンポーネント1.マスタッシュ構文(単方向データバインディング)
マスタッシュ構文とは?
{{ }}
で囲った構文のこと。({{ }}
がマスタッシュ=口ひげに見えるからこのような名前になったとか)
マスタッシュ構文を使用することで、Vueインスタンス内に作ったdataオブジェクトのプロパティを反映させることができます。まずは「Hello World」
まずはhtml内に次のように書いてみましょう。
main.html<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="css/common.css"> <link rel="stylesheet" href="css/main.css"> <title>Main</title> </head> <body> <div id="app"> {{ message }} </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="js/main.js"></script> </body> </html>
<div>
タグにapp
というidを付与し、その中にマスタッシュ構文で{{ message }}
と記述しました。- この時点でhtmlを開いても、
{{ message }}
がテキストとして表示されるのみです。次にjsファイルに次のように記述。
main.jsvar app = new Vue({ el: '#app', data: { message: 'Hello World!' } })
var 変数名 = new Vue({ ... })
で新規のVueインスタンスが作成できます。el:
(elementの略)に#app
と指定することで、<div id="app">
内にのみ有効なVueインスタンスとすることが出来ます。 (id名の先頭に#
を付けるところはCSSでの指定方式と同じです。)data: {}
内にmessage: 'Hello World!'
と記述します。結果
js側で宣言したmessageの内容がDOMに反映されていることが分かります。2.ディレクティブ
ディレクティブとは?
v-
から始まるデータバインディング(HTMLとjavascriptを紐づける)を行うための機能。2-1.v-bind
v-bind
で要素属性のバインディングを行うことが出来ます。main.html<div id="app-2"> <span v-bind:title="message"> 今何時? </span> </div>main.jsvar app2 = new Vue({ el: '#app-2', data: { message: '現在時刻は ' + new Date().toLocaleString() } })【html】
v-bind:[属性名]=""
で要素属性にdataオブジェクト内のプロパティをバインディングします。【js】
- マスタッシュ構文の時と同様、Vueインスタンスを作成し、
el:
に<div>
タグのidを記述します。- dataオブジェクト内には
message: '現在時刻は ' + new Date().toLocaleString()
と記述します。 (new Date().toLocaleString()
で、ローカル言語に合わせた書式の日時を取得できます。)結果
「今何時?」にカーソルを合わせると、title属性にバインディングされた現在日時が表示されました。注意点
タグの属性内にマスタッシュ構文を使うことは出来ません。
属性に適用したい場合は上記の手順でv-bind
を使用した書き方にしてください。main.html<div id="app-2"> <span title={{ message }}> ←このような記述は出来ません! 今何時? </span> </div>2-2.v-if
v-if
で要素の表示/非表示を切り替えることが出来ます。main.html<div id="app-3"> <span v-if="seen"> 見えるかな? </span> </div>main.jsvar app3 = new Vue({ el: '#app-3', data: { seen: true } })
- js側で
seen
プロパティを作成します。- html側で表示/非表示を切り替えたい要素内に
v-if="seen"
と記述します。結果
seen: true
のため、「見えるかな?」というテキストが表示されました。試しに[F12]でデベロッパーツールを起動し、コンソールから
app3.seen = false
と打ってみましょう。
2-3.v-show
v-show
でもv-if
と同じように、要素の表示/非表示を切り替えることが出来ます。main.html<div id="app-3"> <span v-show="seen"> 見えるかな? </span> </div>main.jsvar app3 = new Vue({ el: '#app-3', data: { seen: true } })v-ifとv-showの違い
v-if
でfalse指定した際には要素内がコメントアウトになったのに対し、
v-show
の場合はdisplay: none;
が付与されます。(cssのdisplayプロパティと同じはたらき)
v-if
より軽いため、頻繁に表示/非表示を変える場合はv-show
がおすすめです。
2-4.v-for
v-for
を使って、配列内のデータを反映させることが出来ます。main.html<div id="app-4"> <ol> <li v-for="todo in todos"> {{ todo.text }} </li> </ol> </div>main.jsvar app4 = new Vue({ el: '#app-4', data: { todos: [ { text: 'りんご' }, { text: 'みかん' }, { text: 'ぶどう' } ] } })
- dataオブジェクト内に
todos
という配列を作成します。v-for="[変数] in [配列名]"
で配列の内容を取得するループ処理を作成出来ます。- マスタッシュ構文内で[変数]を使用することが出来ます。
結果
dataオブジェクト内に作った配列をDOMに反映させることができました。2-5.v-on
v-on
でmethods内の処理を実行させることが出来ます。main.html<div id="app-5"> <p>{{ message }}</p> <button v-on:click="reverseMessage">メッセージをひっくり返すよ</button> </div>main.jsvar app5 = new Vue ({ el: '#app-5', data: { message: 'stressed' }, methods: { reverseMessage: function() { this.message = this.message.split('').reverse().join('') } } })
- dataオブジェクトに加えて
mothods
オブジェクトを作成します。methods
オブジェクト内にreverseMessage
というfunctionを作成します。- function内にmessageの文字列を逆にする処理を記述します。(
this
はVueインスタンス(app5)自身を指しています。)- html側には、messageのマスタッシュ構文とその下に
<button>
タグを記述します。<button>
タグ内にv-on:[イベント]="[処理名]"
の形で記載すると、Vueインスタンスのmethods内の処理が呼び出されます。- 今回はクリック時に
reverseMessage
を実行したいので、v-on:click="reverseMessage"
と記述します。結果
2-6.v-model(双方向データバインディング)
【双方向データバインディングの特徴】
・jsのdata側とテンプレート側の両方で変更可能。
・テンプレートの値を変更すると、dataオブジェクトのプロパティも変更される。main.html<div id="app-6"> <p>{{ message }}</p> <input v-model="message"> </div>main.jsvar app6 = new Vue({ el: '#app-6', data: { message: 'こんにちは!' } })
<p>
タグの中にマスタッシュ構文を使いmessage
の内容(こんにちは!)を出力するようにしました。- 直後の
<input>
タグでv-model="[オブジェクト名]"
と指定することで、<p>
タグ同様message
の内容を適用しています。結果
テキスト、テキストボックスの両方にmessage
の内容が出力されました。
試しに下のテキストボックスの文字列を変更すると、上のテキストもそれに連動して書き換えられます。3.コンポーネント
コンポーネントとは?
必要なパーツ(template(HTMLタグ)、methods等)を「コンポーネント」としてパッケージ化できる機能。
一度コンポーネントとして登録すれば再利用が可能なため、同じ組み合わせのタグを繰り返し使う時などに便利。本項はコチラの動画の記述を参考にいたしました。
Vue.js入門 #08:コンポーネントで再利用可能なパーツを作ろうmain.html<div id="app-7"> <alert-box>IDが未入力です。</alert-box> </div>main.jsVue.component('alert-box',{ template: ` <div class="alert"> <strong>Error!</strong> <slot></slot> </div> ` }) var app7 = new Vue({ el: '#app-7' })main.css.alert{ background-color: #fcc; padding: 10px; border: 1px solid #f33; }
Vue.component('[コンポーネント名]',{template: [HTMLタグ]})
で、コンポーネントを登録します。template:
内には、コンポーネント化したいHTMLタグを記述します。<slot>
タグは、コンポーネントを使用時にタグ中に記述したテキスト(「IDが未入力です。」)を反映させるための独自タグです。- あわせて、Vueインスタンスの作成も忘れず行ってください。
- コンポーネント化したタグに
alert
というクラスを付与し、cssにてスタイル編集を行っています。<[コンポーネント名]>
で、登録したコンポーネントを使用することが出来ます。結果
<alert-box>
タグで囲った箇所が、コンポーネントとして登録したHTMLタグ(<div class="alert">...
)に置き換わっています。<alert-box>
タグ内に記述したテキスト(「IDが未入力です。」)が、<slot>
タグによって文字列として適用されています。コンポーネントの再利用
次のように、
<alert-box>
を繰り返し使うと・・・main.html<div id="app-7"> <alert-box>IDが未入力です。</alert-box> <alert-box>IDが未入力です。</alert-box> <alert-box>IDが未入力です。</alert-box> <alert-box>IDが未入力です。</alert-box> </div>その分だけコンポーネントが適用されます。
このように、一度登録したコンポーネントは再利用可能なことが分かります。
mothodsの追加
コンポーネント内にはHTMLタグだけでなく、処理も記述することが出来ます。
main.jsVue.component('alert-box',{ template: ` <div class="alert" v-on:click="caution"> <strong>Error!</strong> <slot></slot> </div> `, methods: { caution: function(){ alert('クリックされました。'); } } }) var app7 = new Vue({ el: '#app-7' })
template:
内の<div>
タグに、v-on:click="caution"
を追記しました。methods:
を追記し、画面上に「クリックされました。」というアラートを表示させるcaution
処理を追記しました。[Error!]をクリックすると、アラートが表示されました。
さいごに
本記事で紹介したものは基礎知識となります。
ディレクティブ機能などの独自の記述が多いですが、慣れればシンプルで非常に書きやすいフレームワークだと感じました。
学習目的であればCDNで読み込みも簡単なので、ご興味のある方は是非お試しいただければと思います。Vue.js学習に役に立ったサイトまとめ
公式サイト(ガイド)
公式サイト(Vueオプションオブジェクト一覧)
基礎から学ぶVue.js
【Vue.js】vue.jsの基礎(yuta-38さん)
【Vue.js】Vue.jsの基礎(smkhkcさん)
Vue.js入門(動画)
- 投稿日:2020-09-23T16:26:43+09:00
V-forでsliceを 使ってlist array を制限する
comment.vue上に <v-for="comment in comments" :key"comment.id"> {{id}} {{name}} </div> <button :disabled="currentPage == 1" @click="prevPage">少なく表示する</button> <button :disabled="currentPage == totalPages" @click="nextPage"> もっと見る </button>Scriptのところに下記を入れる
comment.vuecurrentPage: number = 1 //コメントをsliceを使ってページごとに5個ずつ出す get comments() { return this.visaCommentResponse.slice(0, this.currentPage * 5) } //ページの数をわかる get totalPages() { return Math.ceil(this.commentCount / 5) } //もっと見るボタン nextPage() { if (this.currentPage < this.totalPages) this.currentPage++ } //少なく表示するボタン prevPage() { this.currentPage = this.currentPage - 1 || 1 }EDIT* もう少し簡単にできた。
script のところに
comment.vuecommentsShown?: number = 10 get comments() { return this.visaCommentResponse?.slice(0, this.commentsShown) } loadMore() { this.commentsShown += 10 } loadLess() { this.commentsShown -= 10 }ボタンは
comment.vue<button v-if=" visaCommentResponse.length > 10 && commentsShown < visaCommentResponse.length " @click="loadMore" > Load More </button> <button v-if="commentsShown > 10" @click="loadLess"> Load less </button>
- 投稿日:2020-09-23T15:21:30+09:00
Vue.jsでSassを使用する方法
Vue.jsでScssを使用したらエラーが出たので解決方法をまとめておきます。
複数の方法があるらしいですが、以下が簡単と感じました。
参考:プロジェクト作成時に設定する方法、プロジェクト作成後に反映する方法(今回)以下のようにstyleへScssの指定を追加して下さい。
<style lang="scss"> //この部分に追記 </style>これだけだと次のようなエラーが出ますので、
Failed to resolve loader: sass-loader You may need to install it.
ターミナルで以下を実行します。npm install sass-loader node-sass --save-devあとはいつものようにScssを記述していけば、自動でコンパイルしてくれます。
<style lang="scss"> .nav { ul { li { list-style-type: none; } } } </style>簡単ですね!
- 投稿日:2020-09-23T10:07:05+09:00
Vue3で公開された実験的機能の紹介
はじめに
9/18 に v3.0.0 One Piece が公開されました。
その中にExperimental Features
として以下の 2 つが挙げられていたため、簡単に紹介してみようと思います。
※既に Vue v3.0.0 で利用できます。
※記事作成時の仕様となります。今後変わる場合もあります。(原文)
We have proposed two new features for Singe-File Components (SFC, aka .vue files):
- <script setup>: syntactic sugar for using Composition API inside SFCs
- <style vars>: state-driven CSS variables inside SFCs
These features are already implemented and available in Vue 3.0, but are provided only for the purpose of gathering feedback. They will remain experimental until the RFCs are merged.
1. <script setup>: syntactic sugar for using Composition API inside SFCs
概要
詳細はこちらを参照してください。
Composition API の setup 関数のシンタックスシュガーになります。
具体的には、<script> import { ref } from "vue"; export default { setup() { const count = ref(0); const inc = () => count.value++; return { count, inc, }; }, }; </script>これが、
<script setup> import { ref } from "vue"; export const count = ref(0); export const inc = () => count.value++; </script>これになります。
setup 関数の定型文が大幅に省略できることが分かります。
また、逐次export
できるため、最後にまとめてreturn
する必要がなくなります。Component の export
こちらもシンプルに書けます。
<template> <Foo /> <Bar /> <component :is="ok ? Foo : Bar" /> </template> <script setup> export { default as Foo } from "./Foo.vue"; export { default as Bar } from "./Bar.vue"; export const ok = Math.random(); </script>props の宣言と他のオプションの使い方
setup 関数以外の option を利用するためには、
export default
を使用します。
また、setup 関数の中で props を使用する場合は、<script setup="props">
のように記述します。<script setup="props"> import { computed } from "vue"; export default { props: { msg: String, }, inheritAttrs: false, }; export const computedMsg = computed(() => props.msg + "!!!"); </script>※Compile の都合上、
export default
内でこの外で宣言された値(ex.computedMsg
)を使用できません。Typescript のサポート
<script setup>
のほとんどが Typescript で動作します。
props
やemit
等の setup 関数の引数を使用する場合はdeclare
で宣言します。<script setup="props, context" lang="ts"> import { computed, SetupContext } from "vue"; // declare props using TypeScript syntax // this will be auto compiled into runtime equivalent! declare const props: { msg: string; }; declare const context: SetupContext; export const computedMsg = computed(() => props.msg + "!!!"); export const onClick = () => context.emit("click", "sample"); </script>※しかし、この方法で
props
の型を定義する場合、props
のdefault
やrequired
を指定できませんでした。
export default
で定義しても、declare
の設定で上書きしてしまうようです。
もし指定方法を知っている方がいらっしゃいましたら、コメントいただけると嬉しいです。Typescript 使用時、Component を import(re-exporting) する際に気をつけること
通常、
<script setup>
を使用する際はexport default
は記述する必要はありません。
しかし、その Component を import する側が Typescript を使用している場合、export default
を使っていないと Vetur がエラーを吐きます。
そのため、export default {}
と空の Object を return しましょう。<!--子--> <script setup></script> <!--親--> <script setup> // Module '"../components/Child.vue"' has no exported member 'default'.Vetur(2305) export { default as Child } from "@/components/Child.vue"; </script>通常の<script>との併用
<script setup>
を使用した場合、内部の Script は全て setup 関数でラップされてしまいます。
そのため、他のファイルから import できる値の宣言や、一度しか実行したくない関数の実行をしたい場合は、<script>
と<script setup>
を併用します。<script> performGlobalSideEffect(); // this can be imported as `import { named } from './*.vue'` export const named = 1; </script> <script setup> import { ref } from "vue"; export const count = ref(0); </script>2. <style vars>: state-driven CSS variables inside SFCs
後ほど追記します。
詳細はこちらを参照してください。