Tanaka on Rails

行動・努力・俯瞰

オリジナルなルーティングを作る方法 〜 collectionとmemberの違い

collectionとは?memberとは?

resources以外で独自アクションを定義したい場合はcollectionmemberを使用します。
違いは:idをつける時はmember、付けない時はcollectionということ。

collectionを使う

config.routes.rb

resources :tasks do
  collection do
    get 'set'
  end
end

に設定して$ rails routesしてみると...

set_task GET  /tasks/set(.:format) tasks#set

となりtasks#setアクションが使えるようになります。

memberを使う

resources :tasks do
  member do
    patch 'reset'
  end
end

に設定して$ rails routesしてみると...

reset_task PATCH  /tasks/:id/reset(.:format) tasks#reset

となりtasks#resetアクションが使えるようになります。

参考

qiita.com

Vue.jsでデータ情報が無い時(空配列)に「No Data」と表示するように設定する

v-ifを使う

taskというデータの入れ物がある状態でからの場合は「No Data」を表示し、axiosなどで情報を取得したときにはそのデータをそのまま表示をしたいケースを想定してみます。

<template>
  <div>
    <div v-if="task.length===0">
      <h1>No Data</h1>
    </div>
    <div v-else">
      <h1>{{ task }}</h1>
    </div>
  </div>
</template>

export default {
  data() {
    return {
      task: {}
  }
}

v-if="task.length===0"と配列の長さを確認することでデータの有無を確認できます。

参考

qumeru.com

2つの配列をindexを基準に合成する方法

単純に配列の後ろに追加する場合

例えば...

array_a = [ "a", "b", "c", "d" ]
array_b = [ 1, 2, 3, 4 ]

という2つの配列があるとします。

単純に後ろに繋ぎたい場合は...

array_a.push(array_b)
=>  [ "a", "b", "c", "d", [ 1, 2, 3, 4 ] ]
#pushだけだと連想配列になるので注意
  
array_a.flatten!
p array_a
=> [ "a", "b", "c", "d", 1, 2, 3, 4 ]

とすればOKです。

2つの配列をindexを基準に合成する場合

上記のケースでいった場合は

[ [ "a", 1 ], [ "b", 2 ], [ "c", 3 ], ["d", 4 ] ]

という感じで配列ごとのindexを基準に新しい配列を作成したい場合はどうすればいいのでしょうか?

そんな時はzipを使えば良いです!

array_a.zip(array_b)
=> [ [ "a", 1 ], [ "b", 2 ], [ "c", 3 ], ["d", 4 ] ]

あまり使用することのないケースだと思いますが覚えておくと便利かも?

参考

qiita.com

qiita.com

json形式で送られたデータから新たに配列を作り直す方法

json形式でデータを受け取る

私はRuby on railsをバックエンドでVue.jsをフロントエンドとしてアプリケーション開発を行なっています。
Vueファイルの中でaxiosを使用してRailsでデータを呼び出すという形式を取っています。
Rails内で処理されたデータはjson形式で返されるのですが

[ { "id": 1, "name": "tanaka", "created_at": "2022-01-02T02:00:00.000Z", "updated_at": "2022-01-26T21:15:33.013Z"},
 { "id": 2, "name": "yamada", "created_at": "2022-01-05T05:00:00.000Z", "updated_at": "2022-01-26T21:15:33.016Z"}, 
 { "id": 3, "name": "kato", "created_at": "2022-01-11T03:00:00.000Z", "updated_at": "2022-01-26T21:15:33.021Z"},
 { "id": 4, "name": "sato", "created_at": "2022-01-26T21:17:00.738Z", "updated_at": "2022-01-26T21:17:06.158Z" }, 
 { "id": 5, "name": "saito", "created_at": "2022-02-02T07:34:31.000Z", "updated_at": "2022-02-02T07:34:31.000Z" }]

というように配列の中に配列が入っているというケースもあります。

上記のケースは2022年の1月2日〜1月26日に作成されたデータ(created_at)です。 それぞれに名前(name)というカラムがあります。
このケースでcreated_atの期間を指定して、該当する期間に作成されたnameを取り出したいという時はどうすればいいのかかなり迷いました。

json形式のデータから新たに配列を作成する方法

ソリューションとしてfilterを使用します。

var fromDate = moment('2022-01-01').startOf('month').toISOString();  #moment.jsを使用
var endDate = moment('2022-01-01').endOf('month').toISOString();  #toISOString()でcreated_atの形式に合わせる
var all_users = this.user;  #userはjsonで受け取ったデータ
  
var january_users = all_users.filter(function(item, index){
  if ( item.created_at >= endDate && item.created_at >= fromDate ) return true;
});  #filterによってall_usersからif()内の日付の範囲(1/1~1/31)のデータを絞り込み
  
for( var i = 0; i < january_users.length; i++ ){
  console.log(january_users[i].name);
}  #january_usersのnameを一つづつ配列にしていきコンソールで表示

非常に荒いコードな気がするがとりあえずこれで1月に作成したUserの名前を取得することができます。

参考

www.yoheim.net

www.servernote.net

hagure-m.hateblo.jp

本番環境でのVue.jsにおけるaxiosの書き方

axiosとは?

まず前提としてaxiosはVueファイルからRailsなどのバックエンドでの処理を呼び出す際に使用します。
例えば config/routes.rb

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :tasks do
    end
  end    
end

というルーティングを設定しているときにVueファイルにて

this.$axios.post("http://localhost:3000/api/v1/tasks", task)

とするとapp/controllers/api/v1/tasks_controller.rbのindexアクションを呼び出すことができます。

baseURLで省略可能だが...

上のhttp://localhost:3000/api/v1の部分はaxiosを使用する際に共通となるのでbaseURLとして以下のように設定できます。
app/javascript/plugins/axios.js

const axiosInstance = axios.create({
  baseURL: 'api/v1'
})

このように書いておけばVueファイルにおいて

this.$axios.post("tasks", task)

こんな感じで省略ができコードの簡略化につながります。
さらにこのように設定しておくだけで本番環境でも対応できます!

ただ上記のbaseURLは何故かparamsを使用するようなshow・update・destroyのようなアクションには対応できないようです。 (私の調べ不足かもしれませんが) なので私は開発環境ではそのままURLを書いて開発をしていました↓

this.$axios.get( `http://localhost:3000/api/v1/tasks/${this.$route.params.id}`)

ただこれでは本番環境に対応できないという問題が生じます。

URLを環境変数で設定する

そうした問題に対応するために以下のようなコードに変更をしました↓

this.$axios.get( `${process.env.VUE_BASE_API}/tasks/${this.$route.params.id}`)

VUE_BASE_API環境変数です。

開発環境ではgem 'dotenv-rails'を使用して以下のファイルを作成すると環境変数が使用できます↓
.env

VUE_BASE_API='http://localhost:3000/api/v1'

そして本番環境でももちろん環境変数を設定しなければなりません。
私はHerokuを使用してデプロイをしています。
Herokuで環境変数を設定する方法としてはターミナルにて

$ heroku config:set 環境変数名=値

とすればOKです。
またHerokuのWebページにて設定する方法もあります。 詳しくは以下のURLにて記述がありました↓

qiita.com

Herokuデプロイに向けてのフロントエンド設定(Vue.js・Tailwindcss)

久しくブログでのアウトプットを怠っていました。 気持ちを改めて本日からまたできるだけ毎日投稿していこうと思います!

Herokuデプロイで生じた問題

アプリケーション開発で躓いた部分としてHerokuにてデプロイする際に何故かフロントエンドがうまく機能しないという問題が生じました。
その問題が尾を引いてイライラ原因となりましたのでここでアウトプットをしておき、今後はイライラをなくしていきたいと思います。

なぜフロントエンドが機能しないのか?

Yarnで追加したパッケージのバージョンの問題かと考えて、yarn remove 〇〇yarn add 〇〇ばかりやっていたがこれはどうやら違うようでした。

いろいろ試してみたのですがconfig/webpacker.ymlに問題があるようでした。
私のポートフォリオではWebpackerを使用しているため、全てapp/javascript以下にVueやCSSを読み込むJSファイルなどを配置していました。
そういったJavascriptからCSSを読み込む際にはconfig/webpacker.yml内を以下のように変更する↓
config/webpacker.yml

production:
  <<: *default
~
  extract_css: false
~

※初期設定ではtrueになっている。

zenn.dev

そして以下のコードを追加するとひとまずVueと通常のCSSは起動します。
config/webpack/environment.js

const customConfig = {
  resolve: {
    fallback: {
      dgram: false,
      fs: false,
      net: false,
      tls: false,
      child_process: false
    }
  }
};

environment.config.delete('node.dgram')
environment.config.delete('node.fs')
environment.config.delete('node.net')
environment.config.delete('node.tls')
environment.config.delete('node.child_process')

environment.config.merge(customConfig);

github.com

Tailwindcssを本番環境で使うにはさらに設定が必要

まだここまでではTailwindcssが反映されていないです。 ここでは単純にapp/javascript/packs/tailwind.config.jsに注目します。 app/javascript/packs/tailwind.config.js

module.exports = {
  purge: [
    './app/javascript/pages/*.vue',
    './app/javascript/pages/**/*.vue',
    './app/javascript/pages/**/**/*.vue',
    './app/javascript/pages/*.vue',
    './app/javascript/components/*.vue',,
    './app/javascript/*.vue'
  ],
~

順番はテキトーですがこのようにpurgeの部分でtaiwindcssを反映させたいファイルを指定しないといけません。 このpurgeで指定したファイルのみビルドされるのでここで漏れがあると本番環境でtailwindcssが反映されないので気をつけましょう。

zenn.dev