20201023のRubyに関する記事は25件です。

Railsに動画を挿入する方法

railsに動画を挿入する方法

結論

index.html.erb
<%= video_tag "earth.mov", class: "landing_video", loop: true, autoplay: true, muted: true %>

earth.movの箇所はそれぞれご自身で好きな動画をこちらに当てはめてください。

基本的にmp4でもmovでも形式は問われないと思いますが、UIを考えたときにあまり容量の大きすぎるものだと使い勝手が悪くなってしまうと思うのでその辺りはお気をつけて!

現場からは以上です!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

お名前ドットコムで取得したドメインが急に使用出来なくなった時

デプロイで使用しているのは、RDS、EC2、route53です。
今回、ターミナルでコマンド dig 取得したドメインでstatusを確認したら
status: NXDOMAINが見つかり、これを解決するために一日かかりました。

急に使えなくなった場合の解決策は、
①IPアドレスでアクセスできるか確認する。

IPアドレスでアクセスできた場合、下記の内容確認。
①お名前ドットコムにログインし重要なお知らせが来ていないか確認する。
②メールに重要メールが届いていないか確認する。

私の場合は、メールに
20xx年xx月xx日12:00までに登録情報の修正をお願いします。と届いていたのですが
それに気づかずに指定の日付を超えてしまった為、ドメインが使用できなくなっていました。
登録情報を修正したら、3日後ぐらいにドメインが使用できるようになりました。
お名前ドットコムからのメール多い....

digコマンドの説明

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby の Gem で CSRF を検索してみた

はじめに

気が向いたので、やってみた

 検索結果

gem last
angular_rails_csrf 4.5.0 - September 21, 2020
omniauth-rails_csrf_protection 0.1.2 - June 04, 2019
unified_csrf_prevention 1.0.0 - July 03, 2018
rack_csrf 2.6.0 - December 31, 2016
angular_csrf 0.1.6 - September 18, 2016
faraday_csrf 0.1.0 - October 29, 2015
artirix-cacheable-csrf-token-rails 0.3.1 - July 31, 2015
rack-csrf-detector 0.2.1 - July 07, 2015
rack-simple_csrf 1.3.0 - June 17, 2015
rails3_csrf_patcher 0.0.1 - March 23, 2015
cuba-csrf 0.0.3 - February 07, 2015
baldowl-rack_csrf 1.1.0 - August 11, 2014
angular-csrf-cookie-rails 0.1.0 - June 02, 2014
ng-rails-csrf 0.1.0 - June 18, 2013
csrf_token_caching 0.0.1 - May 22, 2013
cacheable-csrf-token-rails 0.2.0 - March 21, 2013
padrino-csrf 0.1.1 - February 18, 2012

まとめ

  • sinatraで使用しているrack_csrfは新しい方だった

参照したサイト
RubyGems.
Sinatraで家族用todoリストを作る

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Tutorial 第2章学習編

Rails Tutorial 第2章で(。´・ω・)ん?って思ったところ

演習
CSSを知っている読者へ: 新しいユーザーを作成し、ブラウザのHTMLインスペクター機能を使って「User was successfully created.」の箇所を調べてみてください。ブラウザをリロードすると、その箇所はどうなるでしょうか?

Google Chrome Shift+Ctrl+I or (F12) or 右クリックした中にある検証をクリック
image.png
HTML・CSSコードが見れます、
この機能を使って「User was successfully created.」を調べろって事だと思います('ω')ノ
もう少し詳しく知りたい方は⇒こちらをどうぞ

簡単な内容のおさらい。

ユーザー登録機能を作る
魔法のコマンド 『 Rails g scaffold 』( scaffoldは日本語で足場という意味 )  

$ rails generate scaffold User name:string email:string
$ rails db:migrate

このたった2つコマンドを叩くだけでこんなページが出来上がる。
ユーザー登録が出来る・・・もはや魔法の領域。
image.png

Scaffoldの欠点

  • データ検証がない。(空欄・でたらめなアドレスでも登録できちゃう)
  • ユーザー認証がない。(ログイン・ログアウト機能はない。誰でもユーザーページにアクセスできちゃう)
  • レイアウトやスタイルが整っていない。
  • テストが書かれていない。
  • 理解が困難。

投稿機能を作る

$ rails generate scaffold Micropost content:text user_id:integer
$ rails db:migrate

先ほどと同じく2つコマンドを叩くだけとはいかない。
※ルーティングを追加する必要がある。

ruby config/routes.rb
Rails.application.routes.draw do
  resources :microposts # ←これを追加するとurl/micropostで投稿ページにアクセスできる
  resources :users
  root 'users#index'
end

models/micropost.rbにvalidatesを追加する事で検証機能を実装できる

ruby app/models/micropost.rb
class Micropost < ApplicationRecord
  validates :name, length: { maximum: 140 } #入力できる文字列は140文字まで
                   presence: true #文字列が入力されている事を確認する
end

異なるデータモデル同士の関連付ける

ruby app/models/user.rb
class User < ApplicationRecord
#ユーザーはマイクロポストを沢山持ってるのでhas many :micropostを追加
  has_many :microposts
end
ruby app/models/micropost.rb
class Micropost < ApplicationRecord
#マイクロポストはユーザーに紐づいているのでbelongs_to :userを追加
  belongs_to :user
  validates :content, length: { maximum: 140 }
end

これでRDBの関連付けが完了する。わ~い簡単( *´艸`)

Rails Console (Railsアプリを対話的に操作できる便利ツール)

# Rails コンソール
$ rails c
>> #ここにRubyコード記述をすると実行してくれる

>> first_user = User.first # Userテーブルからidが1のユーザーを変数first_userに格納

コマンドの処理内容
User.first
↓ (自動的にデータベースを操作するSQLコマンドに変換される。)
User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC
  LIMIT ?  [["LIMIT", 1]]
↓ SQLの実行結果
 => #<User id: 1, name: "Michael Hartl", email: "michael@example.org",
 created_at: "2020-10-23 00:39:14", updated_at: "2020-10-23 00:41:24">
↓ 
SQLの実行結果をfirst_userに格納

>> first_user.microposts #先ほどのユーザーが投稿したmicropostを全部取り出す。
Micropost Load (3.2ms)  SELECT "microposts".* FROM "microposts" WHERE
  "microposts"."user_id" = ? LIMIT ?  [["user_id", 1], ["LIMIT", 11]]
 => #<ActiveRecord::Associations::CollectionProxy [#<Micropost id: 1, content:
 "First micropost!", user_id: 1, created_at: "2020-10-23 02:04:13", updated_at:
 "2020-10-23 02:04:13">, #<Micropost id: 2, content: "Second micropost",
 user_id: 1, created_at: "2020-10-23 02:04:30", updated_at: "2020-10-23
 02:04:30">]>

>> micropost = first_user.microposts.first #first_userの1番目の投稿を変数micropostに格納

感想

この章はあまり躓かなかったです。('ω')ノ
git&herokuの便利さに惚れ惚れしてきました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby] 二次元配列の取り出し

この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。

二次元配列とは

  • 配列の中に配列が入っている形です。
  • items_priceのハッシュの中にそれぞれのアイテムが配列として格納されています。
  • さらに、1つ1つのアイテムの中にも名前と値段の配列が入っています。
items_price = [["pen", [100, 200, 120]], ["book", [120, 150, 220]], ["pen_case", [1000, 1500]]]

二次元配列を取り出すには

  • each文を使ってハッシュを取り出します。
  • 今回は二次元なので2回each文を使っているのですね。
items_price = [["pen", [100, 200, 120]], ["book", [120, 150, 220]], ["pen_case", [1000, 1500]]]

items_price.each do |item|
  sum = 0
  item[1].each do |price|
    sum += price
  end
  puts "#{item[0]}の値段は#{sum}円です。"
end

では、penを例に取って一つずつみていきます。

1回目のeach(2行目)

items_price.each do |item| ~ end
# => items_price配列の中の["pen", [100, 200, 120]]を取り出し、ブロック変数itemに代入

2回目のeach(4行目)

item[1].each do |price| ~ end
# => item配列の中の[100, 200, 120]を取り出し、ブロック変数priceに代入
  • ちなみに、item[1]はprice配列の要素の数、つまりここでは3回繰り返すことになります。

出力する

puts "#{item[0]}の値段は#{sum}円です。"
  • item[0]はitem配列の添字が0、["pen", [100, 200, 120]]の"pen"の部分になります。

結果

penの値段は420円です。
bookの値段は490円です。
pen_caseの値段は2500円です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FizzBuzzプログラム(2種類)

要件1

・正の整数(自然数)の入力を求める。
・与えられた数字が15の倍数の場合は、"FizzBuzz"と出力
・3の倍数の場合は、"Fizz"と出力
・5の倍数の場合は、"Buzz"と出力
・それ以外の倍は、そのまま数字を出力

コード例

num = gets.to_i

def fizzbuzz(num)
  if num % 15 == 0
    puts "FizzBuzz"
  elsif num % 3 == 0
    puts "Fizz"
  elsif num % 5 == 0
    puts "Buzz"
  else
    puts num
  end
end

fizzbuzz(num)

要件2(さきほどのコードの改良版)

・自然数の入力を求める。
・1からその数まで、"Fizz","Buzz","FizzBuzz","数字"のいずれかを出力する。
例)入力値が9 → 1,2,Fizz,4,Buzz,Fizz,7,8,Fizz
・0や文字列を与えられた場合は、再度入力を求めることができる。

コード例

puts "0以外の数字を入力してください"

input_number = gets.to_i
num = 1

def fizzbuzz(input_number,num)
  input_number.times do
      if num % 15 == 0
        puts "FizzBuzz"
      elsif num % 3 == 0
        puts "Fizz"
      elsif num % 5 == 0
        puts "Buzz"
      else
        puts num
      end
        num += 1
  end

  if input_number == 0
      puts "0または文字列が入力されました。もう一度入力してください。"
      input_number = gets.to_i
      fizzbuzz(input_number,num)
  end

end

fizzbuzz(input_number,num)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails6 Vue.js】axiosを使ってCSVインポート処理を実装する

Vue.jsとRailsAPIを使って複数のCSVファイルをそれぞれのテーブルにインポートする必要があったので記録しておきます。

ご留意ください

Rails,Vue.js学習中の初学者が備忘録を兼ねて書いています。
内容に誤りを含む可能性・さらに良い手法がある可能性が多分にありますので、参考にする際はその点ご留意ください。
何かお気付きの点がございましたら、お気軽にコメントいただけると幸いです。

実現したいこと

inputボックスを用意し、選択したCSVファイル(2種類)をそれぞれ用意したテーブルにaxiosを使ってPOSTしたい。

csv1 ⇨ code_listsテーブル
csv2 ⇨ financialsテーブル
テーブルの定義は下記の通りです。

code_listsテーブル
  create_table "code_lists", force: :cascade do |t|
    t.string "edinet"
    t.string "securities"
    t.string "company"
    t.string "sector"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["company"], name: "index_code_lists_on_company"
    t.index ["edinet"], name: "index_code_lists_on_edinet", unique: true
    t.index ["securities"], name: "index_code_lists_on_securities"
  end
financialsテーブル
  create_table "financials", force: :cascade do |t|
    t.string "edinet"
    t.date "rec_date"
    t.string "account_name"
    t.float "value"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["account_name"], name: "index_financials_on_account_name"
    t.index ["edinet", "rec_date", "account_name"], name: "index_financials_on_edinet_and_rec_date_and_account_name", unique: true
    t.index ["edinet"], name: "index_financials_on_edinet"
  end

下準備

事前にライブラリを追加します。

config/application.rb
require 'csv' #追記

Gemのrooを追加してbundle installします

Gemfile
gem 'roo'

axios-post 時にcsrfトークン対策が必要な為、別途プラグインを設定します。
pluginsフォルダを新たに作成してください。

app/javascript/packs/plugins/vue-axios.js
const VueAxiosPlugin = {}
export default VueAxiosPlugin.install = function(Vue, { axios }) {
  const csrf_token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
  axios.defaults.headers.common = {
    "X-Requested-With": "XMLHttpRequest",
    "X-CSRF-Token": csrf_token
  }

  Vue.axios = axios
  Object.defineProperties(Vue.prototype, {
    axios: {
      get () {
        return axios
      }
    }
  })
}

エントリーファイルにプラグインをimportします

hello_vue.js
import Vue from "vue/dist/vue.esm";
import axios from "axios"; // 追加
import VueAxiosPlugin from "./plugins/vue-axios";  // 追加
import App from "./components/App.vue";

Vue.use(VueAxiosPlugin, { axios: axios }) // 追加

new Vue({
  el: "#app",
  render: h => h(App),
})

ルーティング

ルーティングは次のように設定しました。
必要な箇所のみ記載しています。
それぞれRailsAPIのルーティング設定にしています。
code_listsテーブル用のcsvファイルはapi/code_lists/importへ
financialsテーブル用のcsvファイルはapi/financials/importへPOSTします。

config/routes.rb
Rails.application.routes.draw do
  (上記省略)
  namespace :api, format: 'json' do
    resources :code_lists do
      post :import, on: :collection
    end
  end

  namespace :api, format: 'json' do
    resources :financials do
      post :import, on: :collection
    end
  end
  (以下省略)
end

View

ビューは次のようにしました。

Import.vue
<template>
  <div>
    <div class="import-form">
      <input @change="selectedFile" type="file" name="file">
    </div>
    <div class="import-form">
      <button @click="upload('/api/code_lists/import')" type="submit">コードリストのアップロード</button>
    </div>
    <div class="import-form">
      <button @click="upload('/api/financials/import')" type="submit">財務データのアップロード</button>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  data: function(){
    return {
      uploadFile: null
    };
  },
  methods: {
    selectedFile: function(e) {
      // 選択された File の情報を保存しておく
      e.preventDefault();
      let files = e.target.files;
      this.uploadFile = files[0];
    },
    upload: function(url) {
      // FormData を利用して File を POST する
      let formData = new FormData();
      formData.append('file', this.uploadFile);
      // let config = {
      //     headers: {
      //         'content-type': 'multipart/form-data'
      //     }
      // };
      axios
          .post(url, formData)
          .then(function(response) {
              // response 処理
          })
          .catch(function(error) {
              // error 処理
          })
    }
  }
}
</script>

inputボックスのファイル選択後にselectedFileメソッドでファイルをuploadFileに保存します。そして、buttonのクリックイベントでuploadメソッドが実行されます。uploadメソッドの引数のurl(先ほどroutesで設定した2つのurl)へファイルをPOSTします。POSTする際に事前に保存したuploadFileをFormDataオブジェクトに渡している事がポイントです。
今回はconfigは使用しなかった為コメントアウトしました。

サーバサイド

今回は2つのcsvファイルをそれぞれのテーブルにImportする実装となり、それぞれのモデル毎に実装が必要となりますが、ほぼ同じ内容となる為Financial Modelの実装のみ記載しておきます。
まずコントローラについて。

app/controllers/api/financials_controller.rb
class Api::FinancialsController < ApplicationController
  def import
    Financial.import(params[:file])
  end
end

コントローラはFinancial Classのクラスメソッドを呼び出すだけとなります。

続いて、financialモデルの記述は以下の通りです。

app/models/financial.rb
class Financial < ApplicationRecord
  validates :edinet, presence: true
  validates :rec_date, presence: true
  validates :account_name, presence: true
  validates :value, presence: true
  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
      # IDが見つかれば、レコードを呼び出し、見つかれなければ、新しく作成
      financial = find_by(edinet: row["edinet"], rec_date: row["rec_date"], account_name: row["account_name"]) || new
      # CSVからデータを取得し、設定する
      financial.attributes = row.to_hash.slice(*updatable_attributes)
      # 保存する
      financial.save
    end
  end
  def self.updatable_attributes
    ["edinet", "rec_date", "account_name", "value"]
  end
end

インポートしたいCSVのカラム名をupdatable_attributesに入力。
またfind_byで既に取り込み済みのレコードかどうかを確認しており、取り込み済みの場合は上書きされます。

最後に

現何かお気付きの点がございましたら、お気軽にコメントいただけると幸いです。
上場企業の財務データを活用したアプリケーションを開発中です。フロントエンドをVue.js、バックエンドはRailsAPIを使って開発を進めています。引き続き、得られた知見は記事にしてまとめていきたいと思います。
ここまでお付き合いいただきありがとうございました!

参考にさせていただいた記事:
csrf対策:【Vue】axiosで、デフォルトでCSRFトークンを設定できるようにする
フロントエンド実装:Vue.js でファイルをポストしたいとき
バックエンド実装:【Ruby on Rails】CSVインポート

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails6+Vue.js】axiosを使ってCSVインポート処理を実装する

Vue.jsとRailsAPIを使って複数のCSVファイルをそれぞれのテーブルにインポートする必要があったので記録しておきます。

ご留意ください

Rails,Vue.js学習中の初学者が備忘録を兼ねて書いています。
内容に誤りを含む可能性・さらに良い手法がある可能性が多分にありますので、参考にする際はその点ご留意ください。
何かお気付きの点がございましたら、お気軽にコメントいただけると幸いです。

実現したいこと

inputボックスを用意し、選択したCSVファイル(2種類)をそれぞれ用意したテーブルにaxiosを使ってPOSTしたい。

csv1 ⇨ code_listsテーブル
csv2 ⇨ financialsテーブル
テーブルの定義は下記の通りです。

code_listsテーブル
  create_table "code_lists", force: :cascade do |t|
    t.string "edinet"
    t.string "securities"
    t.string "company"
    t.string "sector"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["company"], name: "index_code_lists_on_company"
    t.index ["edinet"], name: "index_code_lists_on_edinet", unique: true
    t.index ["securities"], name: "index_code_lists_on_securities"
  end
financialsテーブル
  create_table "financials", force: :cascade do |t|
    t.string "edinet"
    t.date "rec_date"
    t.string "account_name"
    t.float "value"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["account_name"], name: "index_financials_on_account_name"
    t.index ["edinet", "rec_date", "account_name"], name: "index_financials_on_edinet_and_rec_date_and_account_name", unique: true
    t.index ["edinet"], name: "index_financials_on_edinet"
  end

下準備

事前にライブラリを追加します。

config/application.rb
require 'csv' #追記

Gemのrooを追加してbundle installします

Gemfile
gem 'roo'

axios-post 時にcsrfトークン対策が必要な為、別途プラグインを設定します。
pluginsフォルダを新たに作成してください。

app/javascript/packs/plugins/vue-axios.js
const VueAxiosPlugin = {}
export default VueAxiosPlugin.install = function(Vue, { axios }) {
  const csrf_token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
  axios.defaults.headers.common = {
    "X-Requested-With": "XMLHttpRequest",
    "X-CSRF-Token": csrf_token
  }

  Vue.axios = axios
  Object.defineProperties(Vue.prototype, {
    axios: {
      get () {
        return axios
      }
    }
  })
}

エントリーファイルにプラグインをimportします

hello_vue.js
import Vue from "vue/dist/vue.esm";
import axios from "axios"; // 追加
import VueAxiosPlugin from "./plugins/vue-axios";  // 追加
import App from "./components/App.vue";

Vue.use(VueAxiosPlugin, { axios: axios }) // 追加

new Vue({
  el: "#app",
  render: h => h(App),
})

ルーティング

ルーティングは次のように設定しました。
必要な箇所のみ記載しています。
それぞれRailsAPIのルーティング設定にしています。
code_listsテーブル用のcsvファイルはapi/code_lists/importへ
financialsテーブル用のcsvファイルはapi/financials/importへPOSTします。

config/routes.rb
Rails.application.routes.draw do
  (上記省略)
  namespace :api, format: 'json' do
    resources :code_lists do
      post :import, on: :collection
    end
  end

  namespace :api, format: 'json' do
    resources :financials do
      post :import, on: :collection
    end
  end
  (以下省略)
end

View

ビューは次のようにしました。

Import.vue
<template>
  <div>
    <div class="import-form">
      <input @change="selectedFile" type="file" name="file">
    </div>
    <div class="import-form">
      <button @click="upload('/api/code_lists/import')" type="submit">コードリストのアップロード</button>
    </div>
    <div class="import-form">
      <button @click="upload('/api/financials/import')" type="submit">財務データのアップロード</button>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  data: function(){
    return {
      uploadFile: null
    };
  },
  methods: {
    selectedFile: function(e) {
      // 選択された File の情報を保存しておく
      e.preventDefault();
      let files = e.target.files;
      this.uploadFile = files[0];
    },
    upload: function(url) {
      // FormData を利用して File を POST する
      let formData = new FormData();
      formData.append('file', this.uploadFile);
      // let config = {
      //     headers: {
      //         'content-type': 'multipart/form-data'
      //     }
      // };
      axios
          .post(url, formData)
          .then(function(response) {
              // response 処理
          })
          .catch(function(error) {
              // error 処理
          })
    }
  }
}
</script>

inputボックスのファイル選択後にselectedFileメソッドでファイルをuploadFileに保存します。そして、buttonのクリックイベントでuploadメソッドが実行されます。uploadメソッドの引数のurl(先ほどroutesで設定した2つのurl)へファイルをPOSTします。POSTする際に事前に保存したuploadFileをFormDataオブジェクトに渡している事がポイントです。
今回はconfigは使用しなかった為コメントアウトしました。

コントローラーとモデル

今回は2つのcsvファイルをそれぞれのテーブルにImportする実装となり、それぞれのモデル毎に実装が必要となりますが、ほぼ同じ内容となる為Financial Modelの実装のみ記載しておきます。
まずコントローラについて。

app/controllers/api/financials_controller.rb
class Api::FinancialsController < ApplicationController
  def import
    Financial.import(params[:file])
  end
end

コントローラはFinancial Classのクラスメソッドを呼び出すだけとなります。

続いて、financialモデルの記述は以下の通りです。

app/models/financial.rb
class Financial < ApplicationRecord
  validates :edinet, presence: true
  validates :rec_date, presence: true
  validates :account_name, presence: true
  validates :value, presence: true
  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
      # IDが見つかれば、レコードを呼び出し、見つかれなければ、新しく作成
      financial = find_by(edinet: row["edinet"], rec_date: row["rec_date"], account_name: row["account_name"]) || new
      # CSVからデータを取得し、設定する
      financial.attributes = row.to_hash.slice(*updatable_attributes)
      # 保存する
      financial.save
    end
  end
  def self.updatable_attributes
    ["edinet", "rec_date", "account_name", "value"]
  end
end

インポートしたいCSVのカラム名をupdatable_attributesに入力。
またfind_byで既に取り込み済みのレコードかどうかを確認しており、取り込み済みの場合は上書きされます。

最後に

現何かお気付きの点がございましたら、お気軽にコメントいただけると幸いです。
上場企業の財務データを活用したアプリケーションを開発中です。フロントエンドをVue.js、バックエンドはRailsAPIを使って開発を進めています。引き続き、得られた知見は記事にしてまとめていきたいと思います。
ここまでお付き合いいただきありがとうございました!

参考にさせていただいた記事:
csrf対策:【Vue】axiosで、デフォルトでCSRFトークンを設定できるようにする
フロントエンド実装:Vue.js でファイルをポストしたいとき
バックエンド実装:【Ruby on Rails】CSVインポート

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsのAPIモードをCookie(session)認証に対応させる

Vue.js + RailsのAPIモードの認証方式をauth_tokenからsession(cookie)に変更した時の変更点をまとめる

これを始めた理由

既存のauth_token認証がWebアプリにとってセキュアでない。

代理ログインの要件がある

  • 普通のwebアプリで実装する予定の管理画面でログインしたユーザーとSPAで作られた管理画面にシームレスにログインさせるには
    • OAuthサーバーを作るか
    • Cookie(Session)の従来の認証に変える必要がある。

今回は納期優先でsession認証に変更

Cookie認証に必要だったもの

config/application.rb

    # Only loads a smaller set of middleware suitable for API only apps.
    # Middleware like session, flash, cookies can be added back manually.
    # Skip views, helpers and assets when generating a new resource.
    config.api_only = false # <- true を false に変更

session storeをcookieにする場合は config.api_only = true にした上で必要なmiddle wearを読み込む方法で行けたが、それはそれで

  • Deviseと相性が悪い
  • session storeにredisを使いたい

という理由でredis storeを使う時は、この方法以外に手段がなかった。

application_controller.rb (全ての基底のcontroller)

class ApplicationController < ActionController::API
  include ActionController::Cookies #<- これを追加

ActionController::API を継承して作る場合はこの設定も必要

axios(ajaxライブラリ)

  axios.create({
    // credential = cookie
    withCredentials: true,
    //...
  })

ajax側にCORS対応としてCookieを送る機能を利用する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#Rails Tutorial 第1章学習編

Rails Tutorial 第一章で(。´・ω・)ん?って思ったところ

 Cloud9のユーザー登録

Cloud9は現在Amazon Web Services (AWS) に統合されたため、Cloud9を使うためにはAWSアカウントが必要になります。AWSアカウントを既にお持ちの場合は、AWSにログインしてください。AWSコンソールに行き、検索ボックスから “Cloud9” と入力すると、Cloud9の開発環境を作成するためのページに行けます。
Amazon Web Services (AWS) アカウントを持っていない場合は、AWS Cloud9のユーザー登録をします。悪用防止のためクレジットカード情報の入力が必須になりましたが、Railsチュートリアルのワークスペースは1年間無料なのでご安心ください。アカウントが有効になるまで最大で24時間かかりますが、著者の場合は約10分ほどで完了しました。
Cloud9の管理ページ (図 1.4) に無事たどり着いたら “Create environment” をクリックし、図 1.5のような画面になるまで進めてください。情報を適宜入力して、確認ボタンを押して進めていくと、最終的にCloud9の開発環境を手に入れることができます (図 1.6)。このとき “root” ユーザーであるという警告メッセージが表示されるときがありますが、こちらの対処方法は後ほど説明します (IAMという機能を使った対応方法について13.4.4で説明します)。
引用:https://railstutorial.jp/chapters/beginning?version=5.1#sec-development_environment

これじゃわかんねーよって感じだったのでYoutube上にあったcloud9の登録方法説明動画を参考にしました。

  コマンドでどうやってファイル開けばいいの? を解決

#Rails tutorialには便利なc9をインストール('ω')ノ
#c9 <ファイル名> でファイルを開けるよ。
npm install -g c9

  このコマンド何してるの? その1

Rubyのインストールで無駄な時間を使わないようにするために追記
$ echo "gem: --no-document" >> ~/.gemrc

UNIXコマンドの処理内容
echo "gem: --no-document" ("gem: --no-documentを)
>> (末尾に追記してね。)
~/.gemrcファイル (ホームディレクトリの下にある~/.gemrcというファイルに)

このコマンド何してるの? その2

JavaScriptソフトウェアの依存関係を管理するYarnをインストール
$ source <(curl -sL https://cdn.learnenough.com/yarn_install)

UNIXコマンドの処理内容
source ファイルに書かれたコマンドを現在のシェルで実行するコマンド
<() : プロセス置換(コマンドの出力結果をファイルとして扱う機能)

curl -sL https://cdn.learnenough.com/yarn_install
curl [http://対象のURL]  HTTPリクエストを実施し結果を標準出力へ
-s -- 余計な出力をしない
-L -- リダイレクトがあったらリダイレクト先の情報を取る

yarn_installファイルの中身です。
#!/bin/bash

# Installs YARN on AWS Cloud9 Ubuntu Server.
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get -y update && sudo apt-get -y install yarn

やっと全貌が見えました! 以下のコマンドを実行してるんですね・・・!
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get -y update && sudo apt-get -y install yarn

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get -y update && sudo apt-get -y install yarn

これって・・・なんでしょう?
自分のプラットフォームに合ったYarnインストール手順(英語)
image.png

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get -y update && sudo apt-get -y install yarn

JavaScriptソフトウェアの依存関係を管理するYarnをインストールする為のコマンドって事だった。

このコマンド何してるの? その3

sudo ln -sf `which nano` /usr/bin

UNIXコマンドの処理内容
sudo 管理者で実行
ln -sf シンボリックリンク(ショートカット)を作成

/usr/binという場所に飛ぶwhich nanoという名前のショートカットを作成?

クラウドIDEを使う場合は、次にGitで使うデフォルトのエディタを設定します(編集や、“amend”でプロジェクトを変更するのに使われます)。ここでは、比較的使いやすくクラウドIDEのデフォルトエディタでもあるnanoエディタを使うことにしましょう。この設定を書き込んでもログアウト時にデフォルトエディタはログアウトしてしまいますし、パスも正しくないので、を実行してシンボリックリンク(symlinkとも呼ばれます)を作成してnanoの実行ファイルを正しく指すようにしましょう (初心者には少々難しいので、今読んで理解できなくても心配は不要です)。

(。´・ω・)ん? でどうすりゃいいの? まぁ飛ばすか( ^ω^)・・・。

Rails Tutorialで使用するデータベースソフト(SQL)について

cloud9(開発環境)ではsqliteを使用。
HerokuではPostgreSQLを使用。
開発環境と本番環境は同じSQLを使う事が推奨。

なんで違うの使っているだろう学習の為なのかな?(´-ω-`)分からない。

Amazon RDS での AWS 無料利用枠
DB インスタンスを各月で連続して実行するのに十分な、MySQL、MariaDB、PostgreSQL、Oracle BYOL、または SQL Server (SQL Server Express Edition) などを使う Amazon RDS の Single-AZ db.t2.micro インスタンスのための、750 時間という使用時間
Oracle BYOL db.t3.micro Single-AZ インスタンスの使用は、Amazon RDS の無料利用枠に含まれています。Oracle BYOL の上で、db.t2.micro Single-AZ と db.t3.micro Single-AZ のインスタンスを両方実行する場合、その使用量はインスタンスクラス全体で合計されます。
20 GB の汎用 (SSD) DB ストレージ*
自動データベースバックアップとユーザーによる任意の DB スナップショットに使用できる 20 GB のバックアップストレージ*

PostgreSQL使えるのに・・・なんでだろう。。。

Railsインストール関連

Railsをインストール RubyGemsが提供するgemコマンドを使う。
gem install rails -v 6.0.3
gem install [アプリ] -v [バージョン指定]
#Railsで空のテンプレート作成コマンド
rails _6.0.3_ new hello_app
rails _[version]_ new [アプリ名]
Gemfile.はインストールするライブラリ(部品)を記述するファイル
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.3'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.4'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5'
# 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]
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.0.5', '< 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'
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]
#Gemfileの中に記載されてるライブラリを一括インストールするコマンド
bundle install

#インストールしたライブラリに依存関係で問題が発生した場合に使うコマンド
bundle update
#Railsサーバーの立ち上げコマンド
rails server
rails s #(省略形) ← こっちの方がよく使う
rb config/environments/development.rb
Rails.application.configure do
  .
  .
  .
  # Cloud9 への接続を許可する
  config.hosts.clear ←これ追記しないとRailsサーバーへのアクセスで弾かれる
end

Git関連

Gitはソースコードを管理する便利なアプリ
Githubはインターネット上にソースコードを保管する場所を提供してくれるサービス

# Gitで使う名前の設定とメールアドレス設定
# ※Gitに設定する名前やメールアドレスは、今後リポジトリ上で一般に公開されるので注意

$ git config --global user.name "名前"
$ git config --global user.email メールアドレス

# checkoutコマンドをcoに省略できるようにする。
$ git config --global alias.co checkout

# git pushする時にパスワード要求される時間を変える 毎回パスワード打つのめんどさを軽減
$ git config --global credential.helper "cache --timeout=86400"

# リポジトリ(保存箱)を作るコマンド
$ git init

# 一時保存箱にファイルを入れるコマンド -A は変更(新規・追加・削除)があったファイルを全て追加という意味
$ git add -A

# 一時保存箱にメモを付けて保存箱へ移すコマンド -m "メッセージ" でメモを書ける
$ git commit -m "Initialize repository"

# インターネット上にある自分のソースコード置き場をoriginという名前で登録
$ git remote add origin https://github.com/<あなたのGitHubアカウント名>/hello_app.git

# 自分のアップロード
$ git push -u origin master

# 変更があるかを確認できる
$ git status

# 過去にcommitした内容を確認
$ git log

Heroku関連

Herokuはインターネット上でアプリを公開させてくれるサービス(5個まで無料)
ソースコードのバージョン管理にGitを使っていれば、Railsアプリケーションを簡単に公開できる

開発環境と本番環境で環境が違うのでそれに合わせてインストールするライブラリを変更する必要がある。
cloud9(開発・テスト環境) = sqlite3 Heroku(本番環境) = PostgreSQL

ruby.Gemfile
source 'https://rubygems.org' 
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem 'rails',      '6.0.3'
gem 'puma',       '4.3.4'
gem 'sass-rails', '5.1.0'
gem 'webpacker',  '4.0.7'
gem 'turbolinks', '5.2.0'
gem 'jbuilder',   '2.9.1'
gem 'bootsnap',   '1.4.5', require: false

#ここから上は全て共通でインストールするんだと思う('ω')ノ

#開発環境とテスト環境のみインストール
group :development, :test do 
  gem 'sqlite3', '1.4.1'
  gem 'byebug',  '11.0.1', platforms: [:mri, :mingw, :x64_mingw]
end

#開発環境のみインストール
group :development do 
  gem 'web-console',           '4.0.1'
  gem 'listen',                '3.1.5'
  gem 'spring',                '2.1.0'
  gem 'spring-watcher-listen', '2.0.1'
end

#テスト環境のみインストール
group :test do 
  gem 'capybara',           '3.28.0'
  gem 'selenium-webdriver', '3.142.4'
  gem 'webdrivers',         '4.1.2'
end

#本番環境のみインストール
group :production do 
  gem 'pg', '1.1.4' 
end

# Windows ではタイムゾーン情報用の tzinfo-data gem を含める必要があります
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
#本番用以外のgemをインストールする
$ bundle install --without production

pg gemを追加したことやRubyバージョンを指定したことをGemfile.lockに反映させないと、
本番環境へのデプロイで失敗してしまうためです。

#herokuコマンドのインストール
source <(curl -sL https://cdn.learnenough.com/heroku_install)

実行してる中身のコマンドはこれ!
curl -OL https://cli-assets.heroku.com/heroku-linux-x64.tar.gz
tar zxf heroku-linux-x64.tar.gz && rm -f heroku-linux-x64.tar.gz
sudo mv heroku /usr/local
echo 'PATH=/usr/local/heroku/bin:$PATH' >> $HOME/.profile
source $HOME/.profile > /dev/null
# herokuにログインする (--interactiveオプションを使うとブラウザをかずにログインできる)
$ heroku login --interactive

# Herokuに新しいアプリケーションを作成する (gitのソースコードを解析して適切なサーバーを用意)
$ heroku create 

# ソースコードをアップロードする これでネット上に自分の作ったサービスが公開される。 
$ git push heroku master

感想

Cloud9・Git・Herokuを使ってHello Worldだけど公開サービスができた!
アプリ開発だけで終わる本が多い中でサービスを公開まで1章で紹介されているのは本当にすごいと思う。
アウトプットする事でUNIXコマンドで躓いた部分を調べて謎が解けた。
UNIXコマンド・・・(゜-゜) 事前学習読んだんだけどな
source 、(プロセス置換) <()、curl、 In こんなん書いてあったっけ・・・。 

さぁ 2章も張り切って頑張るぞー( `ー´)ノ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Tutorial 第1章学習編

Rails Tutorial 第一章で(。´・ω・)ん?って思ったところ

 Cloud9のユーザー登録

Cloud9は現在Amazon Web Services (AWS) に統合されたため、Cloud9を使うためにはAWSアカウントが必要になります。AWSアカウントを既にお持ちの場合は、AWSにログインしてください。AWSコンソールに行き、検索ボックスから “Cloud9” と入力すると、Cloud9の開発環境を作成するためのページに行けます。
Amazon Web Services (AWS) アカウントを持っていない場合は、AWS Cloud9のユーザー登録をします。悪用防止のためクレジットカード情報の入力が必須になりましたが、Railsチュートリアルのワークスペースは1年間無料なのでご安心ください。アカウントが有効になるまで最大で24時間かかりますが、著者の場合は約10分ほどで完了しました。
Cloud9の管理ページ (図 1.4) に無事たどり着いたら “Create environment” をクリックし、図 1.5のような画面になるまで進めてください。情報を適宜入力して、確認ボタンを押して進めていくと、最終的にCloud9の開発環境を手に入れることができます (図 1.6)。このとき “root” ユーザーであるという警告メッセージが表示されるときがありますが、こちらの対処方法は後ほど説明します (IAMという機能を使った対応方法について13.4.4で説明します)。
引用:https://railstutorial.jp/chapters/beginning?version=5.1#sec-development_environment

これじゃわかんねーよって感じだったのでYoutube上にあったcloud9の登録方法説明動画を参考にしました。

AWS Cloud9の登録にはクレジットカードが必須
あんまりいないと思うけどクレカ作れない人向け(´-ω-`)
住信SBIネット銀行で口座開設すれば貰えるデビットカードで代用できます('ω')ノ

  コマンドでどうやってファイル開けばいいの? を解決

#Rails tutorialには便利なc9をインストール('ω')ノ
#c9 <ファイル名> でファイルを開けるよ。
npm install -g c9

  このコマンド何してるの? その1

Rubyのインストールで無駄な時間を使わないようにするために追記
$ echo "gem: --no-document" >> ~/.gemrc

UNIXコマンドの処理内容
echo "gem: --no-document" ("gem: --no-documentを)
>> (末尾に追記してね。)
~/.gemrcファイル (ホームディレクトリの下にある~/.gemrcというファイルに)

このコマンド何してるの? その2

JavaScriptソフトウェアの依存関係を管理するYarnをインストール
$ source <(curl -sL https://cdn.learnenough.com/yarn_install)

UNIXコマンドの処理内容
source ファイルに書かれたコマンドを現在のシェルで実行するコマンド
<() : プロセス置換(コマンドの出力結果をファイルとして扱う機能)

curl -sL https://cdn.learnenough.com/yarn_install
curl [http://対象のURL]  HTTPリクエストを実施し結果を標準出力へ
-s -- 余計な出力をしない
-L -- リダイレクトがあったらリダイレクト先の情報を取る

yarn_installファイルの中身です。
#!/bin/bash

# Installs YARN on AWS Cloud9 Ubuntu Server.
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get -y update && sudo apt-get -y install yarn

やっと全貌が見えました! 以下のコマンドを実行してるんですね・・・!
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get -y update && sudo apt-get -y install yarn

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get -y update && sudo apt-get -y install yarn

これって・・・なんでしょう?
自分のプラットフォームに合ったYarnインストール手順(英語)
image.png

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get -y update && sudo apt-get -y install yarn

JavaScriptソフトウェアの依存関係を管理するYarnをインストールする為のコマンドって事だった。

このコマンド何してるの? その3

sudo ln -sf `which nano` /usr/bin

UNIXコマンドの処理内容
sudo 管理者で実行
ln -sf シンボリックリンク(ショートカット)を作成

/usr/binという場所に飛ぶwhich nanoという名前のショートカットを作成?

クラウドIDEを使う場合は、次にGitで使うデフォルトのエディタを設定します(編集や、“amend”でプロジェクトを変更するのに使われます)。ここでは、比較的使いやすくクラウドIDEのデフォルトエディタでもあるnanoエディタを使うことにしましょう。この設定を書き込んでもログアウト時にデフォルトエディタはログアウトしてしまいますし、パスも正しくないので、を実行してシンボリックリンク(symlinkとも呼ばれます)を作成してnanoの実行ファイルを正しく指すようにしましょう (初心者には少々難しいので、今読んで理解できなくても心配は不要です)。

(。´・ω・)ん? でどうすりゃいいの? まぁ飛ばすか( ^ω^)・・・。

Rails Tutorialで使用するデータベースソフト(SQL)について

cloud9(開発環境)ではsqliteを使用。
HerokuではPostgreSQLを使用。
開発環境と本番環境は同じSQLを使う事が推奨。

なんで違うの使っているだろう学習の為なのかな?(´-ω-`)分からない。

Amazon RDS での AWS 無料利用枠
DB インスタンスを各月で連続して実行するのに十分な、MySQL、MariaDB、PostgreSQL、Oracle BYOL、または SQL Server (SQL Server Express Edition) などを使う Amazon RDS の Single-AZ db.t2.micro インスタンスのための、750 時間という使用時間
Oracle BYOL db.t3.micro Single-AZ インスタンスの使用は、Amazon RDS の無料利用枠に含まれています。Oracle BYOL の上で、db.t2.micro Single-AZ と db.t3.micro Single-AZ のインスタンスを両方実行する場合、その使用量はインスタンスクラス全体で合計されます。
20 GB の汎用 (SSD) DB ストレージ*
自動データベースバックアップとユーザーによる任意の DB スナップショットに使用できる 20 GB のバックアップストレージ*

PostgreSQL使えるのに・・・なんでだろう。。。

Railsインストール関連

Railsをインストール RubyGemsが提供するgemコマンドを使う。
gem install rails -v 6.0.3
gem install [アプリ] -v [バージョン指定]
#Railsで空のテンプレート作成コマンド
rails _6.0.3_ new hello_app
rails _[version]_ new [アプリ名]
Gemfile.はインストールするライブラリ(部品)を記述するファイル
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.3'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.4'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5'
# 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]
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.0.5', '< 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'
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]
#Gemfileの中に記載されてるライブラリを一括インストールするコマンド
bundle install

#インストールしたライブラリに依存関係で問題が発生した場合に使うコマンド
bundle update
#Railsサーバーの立ち上げコマンド
rails server
rails s #(省略形) ← こっちの方がよく使う
rb config/environments/development.rb
Rails.application.configure do
  .
  .
  .
  # Cloud9 への接続を許可する
  config.hosts.clear ←これ追記しないとRailsサーバーへのアクセスで弾かれる
end

Git関連

Gitはソースコードを管理する便利なアプリ
Githubはインターネット上にソースコードを保管する場所を提供してくれるサービス

# Gitで使う名前の設定とメールアドレス設定
# ※Gitに設定する名前やメールアドレスは、今後リポジトリ上で一般に公開されるので注意

$ git config --global user.name "名前"
$ git config --global user.email メールアドレス

# checkoutコマンドをcoに省略できるようにする。
$ git config --global alias.co checkout

# git pushする時にパスワード要求される時間を変える 毎回パスワード打つのめんどさを軽減
$ git config --global credential.helper "cache --timeout=86400"

# リポジトリ(保存箱)を作るコマンド
$ git init

# 一時保存箱にファイルを入れるコマンド -A は変更(新規・追加・削除)があったファイルを全て追加という意味
$ git add -A

# 一時保存箱にメモを付けて保存箱へ移すコマンド -m "メッセージ" でメモを書ける
$ git commit -m "Initialize repository"

# インターネット上にある自分のソースコード置き場をoriginという名前で登録
$ git remote add origin https://github.com/<あなたのGitHubアカウント名>/hello_app.git

# 自分のアップロード
$ git push -u origin master

# 変更があるかを確認できる
$ git status

# 過去にcommitした内容を確認
$ git log

Heroku関連

Herokuはインターネット上でアプリを公開させてくれるサービス(5個まで無料)
ソースコードのバージョン管理にGitを使っていれば、Railsアプリケーションを簡単に公開できる

開発環境と本番環境で環境が違うのでそれに合わせてインストールするライブラリを変更する必要がある。
cloud9(開発・テスト環境) = sqlite3 Heroku(本番環境) = PostgreSQL

ruby.Gemfile
source 'https://rubygems.org' 
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem 'rails',      '6.0.3'
gem 'puma',       '4.3.4'
gem 'sass-rails', '5.1.0'
gem 'webpacker',  '4.0.7'
gem 'turbolinks', '5.2.0'
gem 'jbuilder',   '2.9.1'
gem 'bootsnap',   '1.4.5', require: false

#ここから上は全て共通でインストールするんだと思う('ω')ノ

#開発環境とテスト環境のみインストール
group :development, :test do 
  gem 'sqlite3', '1.4.1'
  gem 'byebug',  '11.0.1', platforms: [:mri, :mingw, :x64_mingw]
end

#開発環境のみインストール
group :development do 
  gem 'web-console',           '4.0.1'
  gem 'listen',                '3.1.5'
  gem 'spring',                '2.1.0'
  gem 'spring-watcher-listen', '2.0.1'
end

#テスト環境のみインストール
group :test do 
  gem 'capybara',           '3.28.0'
  gem 'selenium-webdriver', '3.142.4'
  gem 'webdrivers',         '4.1.2'
end

#本番環境のみインストール
group :production do 
  gem 'pg', '1.1.4' 
end

# Windows ではタイムゾーン情報用の tzinfo-data gem を含める必要があります
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
#本番用以外のgemをインストールする
$ bundle install --without production

pg gemを追加したことやRubyバージョンを指定したことをGemfile.lockに反映させないと、
本番環境へのデプロイで失敗してしまうためです。

#herokuコマンドのインストール
source <(curl -sL https://cdn.learnenough.com/heroku_install)

実行してる中身のコマンドはこれ!
curl -OL https://cli-assets.heroku.com/heroku-linux-x64.tar.gz
tar zxf heroku-linux-x64.tar.gz && rm -f heroku-linux-x64.tar.gz
sudo mv heroku /usr/local
echo 'PATH=/usr/local/heroku/bin:$PATH' >> $HOME/.profile
source $HOME/.profile > /dev/null
# herokuにログインする (--interactiveオプションを使うとブラウザをかずにログインできる)
$ heroku login --interactive

# Herokuに新しいアプリケーションを作成する (gitのソースコードを解析して適切なサーバーを用意)
$ heroku create 

# ソースコードをアップロードする これでネット上に自分の作ったサービスが公開される。 
$ git push heroku master

感想

Cloud9・Git・Herokuを使ってHello Worldだけど公開サービスができた!
アプリ開発だけで終わる本が多い中でサービスを公開まで1章で出来るって本当にすごいと思う。
今回のアウトプットでUNIXコマンドで躓いていただなぁっと調べて少し謎が解けた。
UNIXコマンド・・・(゜-゜) 事前学習読んだんだけどな
source 、(プロセス置換) <()、curl、 In こんなん書いてあったっけ・・・。 

まぁいいや、さぁ 2章も張り切って頑張るぞー( `ー´)ノ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Amazon Linuxでrbenvをインストール

依存ライブラリーをインストール

sudo yum -y install gcc
sudo yum -y install make
sudo yum -y install openssl
sudo yum -y install openssl-devel
sudo yum -y install gcc-c++
sudo yum install -y mysql-devel
sudo yum install -y readline-devel
sudo yum install -y libxml2-devel
sudo yum install -y libxslt-devel
sudo yum install -y bzip2

gitをインストール

$ sudo yum -y install git

rbenvをインストール

$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l

しかしこのままだとrbenv istallが出来ない。

$ rbenv install -v 2.6.2
rbenv: no such command `install'

helpを見てみると、installコマンドが無いのが分かる。

$ rbenv -h
Usage: rbenv <command> [<args>]

Some useful rbenv commands are:
   commands    List all available rbenv commands
   local       Set or show the local application-specific Ruby version
   global      Set or show the global Ruby version
   shell       Set or show the shell-specific Ruby version
   rehash      Rehash rbenv shims (run this after installing executables)
   version     Show the current Ruby version and its origin
   versions    List installed Ruby versions
   which       Display the full path to an executable
   whence      List all Ruby versions that contain the given executable

解決方法

install するには ruby-build プラグインが必要となるのでインストールする。

$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

helpを見るとinstall(とuninstall)が追加されたのが分かる。

$ rbenv -h
Usage: rbenv <command> [<args>]

Some useful rbenv commands are:
   commands    List all available rbenv commands
   local       Set or show the local application-specific Ruby version
   global      Set or show the global Ruby version
   shell       Set or show the shell-specific Ruby version
   install     Install a Ruby version using ruby-build
   uninstall   Uninstall a specific Ruby version
   rehash      Rehash rbenv shims (run this after installing executables)
   version     Show the current Ruby version and its origin
   versions    List installed Ruby versions
   which       Display the full path to an executable
   whence      List all Ruby versions that contain the given executable

See `rbenv help <command>' for information on a specific command.
For full documentation, see: https://github.com/rbenv/rbenv#readme

rbenv install -v 2.6.2 するとインストールが始まる。
インストール終了後、rbenv versionsで確認できる。

$ rbenv versions
* system
  2.6.2

インストールLog

インストール時のlogファイルはruby-build.xxxxxxxxxxxxxxx.logというファイル名で
/tmp/配下に格納されている。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

項目内容の情報を保存する 〜Active_Hash〜

情報の登録フォーマットを実装する際に避けて通れないのが、選択した項目(collectionなど)をDBに保存すること。
フリマなどのアプリでは都道府県、商品の状態、配送日数などの登録が必要です。アンケートを想定するなら性別、生年月日など様々な場面でみられますね。
項目内容を予めseed.rbなどで用意してテーブルを作るということを想定する方も多くいると思いますが、これは無駄なテーブルを作っていると言っても過言ではありません。

無駄なテーブル?

DB設計などでもよく扱われる内容が「正規化」です。ざっくり言ってしまうとデータの構造を効率的でシンプルにすることです。しかしこの正規化を徹底的に行ってしまうと、小さなテーブルが増えてしまいこれも処理の負荷の要因につながります。そのため項目専用テーブルを作ることは極力避けなければなりません。

そんな際に役立つのがActive_hashです

Active_hashとは?

専用モデルを作り、その中に予め項目内容の値を用意することでDBを介さずとも項目を用意することができます。言うなれば「モデル内に項目テーブル」を作ることになります。こうすることで小さなテーブルをDB側に用意する必要がなくなるため負荷が軽くなるのです。

導入手順

今回はcollection_selectを使った商品アンケートを想定して実装していこうと思います。
保存・管理したい内容は以下の4つです。
・年代
・性別
・商品を知った経緯
・商品を使ってみての感想

DB負荷などを考えてテーブルは1つにしたいです。
設計としては
1.年代は10代〜90代
2.性別は男性・女性
3.商品を知った経緯は広告、知人、家族、インターネット
4.商品を使ってみての感想は手入力
としていきます。

この中で項目(collection_select)として使用したいのは1~3番の内容です。
ではこれを想定してアンケートを実装していきましょう。
今回の解説はactive_hashの実装のみに留めますのでそれ以外の行程は割愛しますのでご了承ください。

Step:1 Gemfileにactive_hashを追加しインストールを実行

gem 'active_hash'

ターミナル

% bundle install

Step:2 モデル&マイグレーションファイルの用意

gコマンドでモデルを生成 ※モデル名はお好みで

% rails g model model question

・マイグレーションファイルの準備

active_hashを使う場合項目内容はintegerカラムで管理します。このintegerカラムがidとして動いてくれるのです。そのためカラム名は必ず"_id"をつけることを忘れないようにしましょう。
手入力欄についてはいつものtextカラムで実装します。

00000000000000_create_questions.rb

class CreateQuestions < ActiveRecord::Migration[6.0]
  def change
    create_table :questions do |t|
      t.integer :age_id,         null: false
      t.integer :sexuality_id,   null: false
      t.integer :find_item_id,   null: false
      t.text    :comment,        null: false
      t.timestamps
    end
  end
end

その後いつものようにテーブルを作成して、マイグレーションファイルを実行します。

% rails db:create
% rails db:migrate

・項目ごとのモデルファイルを作成する
active_hashを実装するモデルを項目の3つ分を用意します。
マイグレーションファイルは必要ないのでオプションをつけてスキップさせます。

% rails g model age --skip-migration
% rails g model sexuality --skip-migration
% rails g model find_item --skip-migration

では各項目用に準備したモデルの中身を書いていきましょう

生成したモデルの内部はおそらく初期はこのような形になっていると思います

class Age < ApplicationRecord
end

これをactive_hash専用モデルにするため、以下のように編集を加えます。

class Age < ActiveHash::Base
end

これにより、このモデル内で擬似的な項目テーブルを作れるようになりました。
項目をこの中に入れる際はクラスメソッドとハッシュを使って実装していきます。
可読性をあげるポイントは1つめのキーをidに、「もう1つのキーには項目として扱いたい名前をつけること。

class クラス名 < ActiveHash::Base
  self.data = [
  { id: 0, hoge: fuga }]
end

これに沿って以下のようになります。

class Age < ActiveHash::Base
  self.data = [
      { id: 0, name: '---' },
      { id: 1, name: '10代' },
      { id: 2, name: '20代' },
      { id: 3, name: '30代' },
      { id: 4, name: '40代' },
      { id: 5, name: '50代' },
      { id: 6, name: '60代' },
      { id: 7, name: '70代' },
      { id: 8, name: '80代' },
      { id: 9, name: '90代' }
  ]
class FindItem < ActiveHash::Base
  self.data = [
    { id: 0, example: '---' },
    { id: 1, example: '広告で知った' },
    { id: 2, example: '知人の紹介で知った' },
    { id: 3, example: '家族の紹介で知った' },
    { id: 4, example: 'インターネットで知った' }
  ]
end
class Sexuality < ActiveHash::Base
  self.data = [
    { id: 0, name: '---' },
    { id: 1, name: '男性' },
    { id: 2, name: '女性' }
  ]
end

これでactive_hashを使って擬似テーブルの作成は完了。
あとは大元となる一番最初に作ったquestionモデルに連携させる記述を施します。

class Question < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to_active_hash :age
  belongs_to_active_hash :sexuality
  belongs_to_active_hash :find_item
end

Step:3 ビューファイルの記述

<h1>当社の商品についてアンケートにご協力ください</h1>

<div class="wrapper">
  <div class="form">
    <%= form_with model: @question, local: true do |f| %>
      <div class="form-box">
        <h3>年代をお選びください</h3>
        <%= f.collection_select(:age_id, Age.all, :id, :name) %>
      </div>
      <div class="form-box">
        <h3>性別をお選びください</h3>
        <%= f.collection_select(:sexuality_id, Sexuality.all, :id, :name)%>
      </div>
      <div class="form-box">
        <h3>当社の商品をどこでお知りになりましたか?</h3>
        <%= f.collection_select(:find_item_id, FindItem.all, :id, :example)%>
      </div>
      <div class="form-text">
        <h3>当社の商品をお使頂いてみての感想を簡単にで構わないのでご記入ください</h3>
        <%= f.text_area :comment %>
      </div>
      <%= f.submit "送信する" %>
    <% end %>
  </div>
</div>

ポイントはcollection_selectの引数です。
第一引数はparamsに渡す値(カラム名)、 第二引数には表示させたい項目(モデル名)。

Step:4 コントローラの記述

class QuestionsController < ApplicationController
  def index
    @question = Question.new
  end

  def create
    # binding.pry
    @question = Question.new(question_params)
    @question.save
    redirect_to root_path
  end

  private
  def question_params
    params.require(:question).permit(
      :age_id, 
      :sexuality_id, 
      :find_item_id, 
      :comment)
  end
end

ここについては特に言及箇所はありません。

手短に実装を行ってみました

皆さんもぜひactive_hashに挑戦してみてください

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

インスタグラム自動いいねツールを自分で作ってみた【Ruby】

はじめに

インスタグラムのフォロワーを増やしたい。けどそんなに時間を掛けたくない。有料インスタグラムツールは料金が高そうだし、、

という訳で自動的にいいねをつけることができるプログラミングを組んでみました!

対象者

  • 手軽にインスタグラムのフォロワー数を増やしたい人
  • プログラミング学習初心者

僕が開発した時の環境

version 
Ruby 2.6.3
gem 3.0.3
Homebrew 2.5.2 

開発手順

まずはselenium-driverをインストールします。

seleniumとはブラウザのオートメーションツールです。自動でブラウザを操作することができます。Ruby、Pyhonなどで書かれたスクリプトを元に、ブラウザを操作するためのJavaScriptを生成し、対象のページにそのJavaScriptを埋め込んでブラウザを操作するという仕組みです。

参照記事
https://app.codegrid.net/entry/selenium-1

selenium-driverのインストール

gem install selenium-webdriver 

次にchrome-driverをインストールします。
chrome-driverとは、Google Chromeを操作するために必要なドライバ(ソフト)です。ブラウザごとに専用のドライバが用意されています。

chrome-driverのインストール

brew install chrome-driver

次にchrome-driverのパスを通します。

$ echo export PATH=' ●●(:$PATH'  >> ~/ .bash_profile

次に実装します。

全体のソース

insta_auto.rb
require 'selenium-webdriver'
require 'uri'

class InstagramBot
  attr_accessor :driver
  def initialize(username,password)

  end

  def good_hashtag(key_word,number)

  end

  def good_user_post(username,number)

  end

end
username = ""
password = ""
bot = InstagramBot.new(username,password)
key_word = ""
bot.good_hashtag(key_word,15)
# username = ""
# bot.good_user_post(username,15)

ログイン機能

insta_auto.rb
 def initialize(username,password)
    # 略
    ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36'
    puts "aaaaaaaaaaa"
    caps = Selenium::WebDriver::Remote::Capabilities.chrome('chromeOptions' => { args: ["--user-agent=#{ua}", 'window-size=1280x800', '--incognito'] }) # シークレットモード
    puts "vbbbbbbb"
    client = Selenium::WebDriver::Remote::Http::Default.new
    client.read_timeout = 300
    @driver = Selenium::WebDriver.for :chrome, desired_capabilities: caps, http_client: client
    @driver.manage.timeouts.implicit_wait = 30
    @driver.navigate.to'https://www.instagram.com/accounts/login/?source=auth_switcher'
    puts "ddddd"
    @driver.find_element(:name, 'username').send_keys(username)
    @driver.find_element(:name, 'password').send_keys(password)
    sleep 1
    @driver.find_element(:name, 'password').send_keys(:return)
  end

指定のハッシュタグにいいねをつける

insta_auto.rb
def good_hashtag(key_word,number)
    encode_word = URI.encode(key_word)
    sleep 3
    @driver.navigate.to"https://www.instagram.com/explore/tags/#{encode_word}/"
    sleep 2
    @driver.execute_script("document.querySelectorAll('article img')[9].click()")
    sleep 2
    number.times{
      begin
        @driver.execute_script("console.log(document.querySelectorAll('button.wpO6b')[1].click())")
        sleep 2
      rescue
        puts "already good this post"
      end
      sleep 2
      @driver.execute_script("document.querySelector('a.coreSpriteRightPaginationArrow').click()")
      sleep 2
    }
  end

指定のユーザーにハッシュタグをつける

insta_auto.rb
def good_user_post(username,number)
    sleep 3
    @driver.navigate.to"https://www.instagram.com/#{username}/"
    sleep 2
    @driver.execute_script("document.querySelectorAll('article img')[0].click()")
    sleep 2
    number.times{
      begin
        @driver.execute_script("document.querySelectorAll('span.glyphsSpriteHeart__outline__24__grey_9')[1].click()")
      rescue
        puts "already good this post"
      end
      sleep 2
      @driver.execute_script("document.querySelector('a.coreSpriteRightPaginationArrow').click()")
      sleep 2
    }
  end

まとめ

開発環境の構築にかなり時間がかかってしまいました。一方でソースコードの記述に関しては参考になる記事がたくさん出てきたのであまり苦労せず助かりました。
僕の肌感覚ですが、プログラミング初心者は「言語はある程度勉強しているけど環境構築に関しては現場に入って徐々に」という方が多いのではないかと思います。プログラミングスクールを卒業したばかりの僕には環境構築を一からというのはかなり骨が折れました笑
かなり色んな記事を飛び回って試行錯誤しなければいけないので。
なので今回は僕のような方を対象にした「一連の流れを体系化した記事」を作りました!参考になれば幸いです。

また、噂ですがあまりこのインスタ自動いいね機能を使いすぎるとInstagramからアカウントが削除される可能性もあるとのこと。
使う際は自己責任でお願いします!

参照記事:

https://qiita.com/nirs_kd56/items/6979a026497f2f4a59bf
https://qiita.com/FJHoshi/items/c847ad51af388d2dbb4a
https://qiita.com/y-agatsuma/items/ea2c9845ee0a931d5c9c
 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】コントローラー間で共通処理(concerns使用)

はじめに

サイトページが多くなるにつれて、同じコントローラーの記述が増えてくるかと思います。
そのときにconcernsを活用すると記述もスッキリとなり、可読性が上がります。

実際のコード

app/controllers/posts_controller.rb
class PostController < ApplicationController
  before_action :set_posts
  def set_posts
    @posts = Post.all
  end
end
app/controllers/users_controller.rb
class UserController < ApplicationController
  before_action :set_posts
  def set_posts
    @posts = Post.all
  end
end

上記のように同じset_postsという共通処理があります。
ただし、もし変更があった場合は両方を修正する必要があり手間です。
これらを解決する方法がconcernsの利用です。

concernsファイルの作成

app/controllers/concerns配下にファイルを作成します。
今回ファイル名は「postable.rb」にします。

app/controllers/concerns/postable.rb
module Postables
extend ActiveSupport::Concern

  def set_posts
    @posts = Post.all
  end

end

そしれそれぞれのコントローラー呼び出すためには
include Postablesと記述します。

app/controllers/posts_controller.rb
class PostController < ApplicationController
  include Postables
  before_action :set_posts
end
app/controllers/users_controller.rb
class UserController < ApplicationController
  include Postables
  before_action :set_posts
end

これでOKです。

まとめ

これらを行うことで修正があったとしても一箇所の修正で済み、エラー時にも早急に対応できます。
記述の少なさは保守性にもつながりますので、使用することをおすすめします。

またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら https://twitter.com/japwork

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Tutorial 0章:事前基礎知識学習5

事前基礎知識学習:Ruby

Rails Tutorialの内でオススメされているPROGATE
image.png

Railsチュートリアルでは、初心者向けプログラミング学習サービス「Progate」と提携し、日本語でWebの基礎知識を学べるコースも用意しました。
同サービスは環境構築不要かつブラウザ上でコーディング体験ができるため、特にプログラミング未経験者にうってつけです。
このまま本チュートリアルを読み進めてももちろん大丈夫ですが、
もし読んでいて「難しい」と感じたら、本文中の「関連」で示されているコースで基礎知識を学んでみることをおすすめします。
特にプログラミングの経験がほとんどない場合は、Railsチュートリアルを読み進める前に、Progateの「Web開発パス(Ruby on Rails)」から始めてみることをオススメしています。
引用 : Rails Tutorial 第1章

Progateは『説明スライドを読む』⇒『コードを書く』の繰り返しです。
私も使った事ありますが、非常に分かりやすくて手軽にチャレンジできます。
月額980円の価値は確実にありますね。

ただ個人的には、まずは4章迄は進めてみる事をオススメします。

自分に学習経験があるからかもしれませんが、
今まで学んだ内容の中でRails Tutorialの第四章 Rails風味のRubyが一番分かりやすかったです。
Progateでもそうだったんですが、
オブジェクト指向という概念が出てくるあたりから(。´・ω・)ん?って感じになるんです。
どうしてこんな書き方するの?って疑問を抱えながら取り合えずコードを覚えて不完全燃焼です。
今回、Rails Tutorialをやってオブジェクト指向的な書き方をする理由がやっとなんとなく分かりました。

Ruby基礎

#STEP1: 文字列の表示 |文字列は必ず""(ダブルクォーテーション)または''(シングルクォーテーション)で囲む|
puts ("Hello World") :Putsは自動で改行される(こっちの方がよく使う)
print ("Hello World") :Printは改行されない。
#STEP2: 変数の理解1 |変数は一時的に保管する箱|
a = "Hello World"
print(a) 
-> Hello World

#STEP3: 変数の理解2 |もちろん数字も入る|
a = 3

#STEP4: 変数の理解3 |1個しか保管できない&最後に入れたデータが保管される|
a = "Hello World"
a = "Hello Japan"
puts(a) 
-> Hello Japan

#STEP5: 文字列操作 | + を使った文字列の結合|
a = "Hello"
b = "Japan"
puts(a + b) 
-> HelloJapan

puts(a +" "+ b) 
-> Hello Japan
#STEP6: 配列1 |モノを複数入れたい場合は配列を使う|
a = ["Hello World", "Hello Asia", "Hello Japan"]
puts(a) 
-> ["Hello World", "Hello Asia", "Hello Japan"]

puts(a[0]) 
-> Hello World 

puts(a[1]) 
-> Hello Asia 

puts(a[2]) 
-> Hello Japan 

#STEP7: 配列2 |配列にモノを追加していく|
a = [] #これで空の配列を作る
a.append("Hello World")
a.append("Hello Asia", "Hello Japan")
puts(a[0]) 
-> Hello World 

puts(a[1]) 
-> Hello Asia 

puts(a[2]) 
-> Hello Japan
#STEP8: ハッシュ |名前付き配列|
user = { "name"=>"Michael Hartl","email"=>"michaelhartl@example.com" }
puts(user)
-> { :name=>"Michael Hartl", :email=>"michaelhartl@example.com" }

puts(user["name"]) 
-> "Michael Hartl"

puts(user["email"]) 
-> "michaelhartl@example.com"

#STEP9: ハッシュ2 |記述法は1個だけじゃない・・・|
user = { name:"Michael Hartl", email:"michaelhartl@example.com" }

puts(user[:name]) 
-> "Michael Hartl"

puts(user[:email]) 
-> "michaelhartl@example.com"

#STEP10: ハッシュと配列の複合技| マトリョーシカみたいにしてよく使う |
user_data = []
user = { name:"Michael Hartl", email:"michaelhartl@example.com" }

user_data.append(user)
puts(user_data) 
-> [{:name=>"Michael Hartl", :email=>"michaelhartl@example.com"}]

user = { name:"Michael Jacson", email:"michaeljacson@example.com" }
user_data.append(user)
puts(user_data) 
-> [{:name=>"Michael Hartl", :email=>"michaelhartl@example.com"}
{:name=>"Michael Hartl", :email=>"michaelhartl@example.com"}]

puts(user_data[0][:name]) 
-> "Michael Hartl" #0番目の配列にある"name"を取り出す
#STEP11 lengthメソッド |文字数・配列の中身の個数を返す|
a = "length"
puts(a.length)
-> 6 #文字の個数を返す

user_data = [{ name:"Michael Hartl", email:"michaelhartl@example.com" },
{ name:"Michael Hart", email:"michaelhart@example.com" },
{ name:"Michael Har", email:"michaelhar@example.com" },
{ name:"Michael Ha", email:"michaelha@example.com" }]

puts(user_data.length)
-> 4 #配列の中に入っているハッシュ数を返す
#STEP: ループ処理|eachをよくつかう|
user_data = [{ name:"Michael Hartl", email:"michaelhartl@example.com" },
{ name:"Michael Hart", email:"michaelhart@example.com" },
{ name:"Michael Har", email:"michaelhar@example.com" },
{ name:"Michael Ha", email:"michaelha@example.com" }]

user_data.each do |user| 
  puts("お名前: " user[:name] + " メールアドレス: " + user[:email])
-> お名前: Micheal Hartl メールアドレス: michealhartl@example.com
-> お名前: Micheal Hart メールアドレス: michealhart@example.com
-> お名前: Micheal Har メールアドレス: michealhar@example.com
-> お名前: Micheal Ha メールアドレス: michealha@example.com

#処理の内容を理解しよう(^_-)-☆
1 user_dataの一行目を |user|で定義した変数userに格納する
  #user = { name:"Michael Hartl", email:"michaelhartl@example.com" } が入る。
2 puts("お名前: " user[:name] + " メールアドレス: " + user[:email]) 形を整えて表示
  #お名前: Micheal Hartl メールアドレス: michealhartl@example.com
3 .eachは配列がなくなる迄繰り返せというメソッド

for文・・・? while文・・・? あんまりお目に掛からないです。
誰かがfor文などを使ってeachメソッドを作ってくれているんですよね。
学生時にプログラミングを学んだ時はfor文を使って一個づつ取り出す処理を記述をしてました。
eachメソッドのおかげで便利になっているけど実際の処理内容は見えないですよね
これがもや~っとする原因なんだと思います。
一方で複雑な処理を理解できるかというと( ^ω^)・・・。
処理が複雑化しているので便利メソッドでさくっと利用できるのは本当にありがたいですね。

余談 : 数年前にProgateもチャレンジしたよ。

Progateは『説明スライドを読む』⇒『コードを書く』の繰り返しです。
非常に分かりやすいので月額980円の価値は非常にあると思いました。
私がProgateで学習したのはHTML/CSS/Python/JavaScript/jQueryです。

Progateで勉強すると、コードの書き方は分かるようになるんです。
静的なウェブサイト・少し動きの付いたウェブサイトを作れるレベルに到達します。

デザインの参考になるステキなシングルページサイト1
本当に頑張ったら、素敵な静的ウェブサイトを作れると思います。

それでもやっぱりProgateだけだと知識的に足りない部分が出てきます。

  • ウェブサイトをインターネットにどうてって公開するの?
  • qiita.comみたいな独自ドメインってどう取得する?
  • Google Mapをどうやってウェブサイトに埋め込む?
  • データベースと連携したWEBアプリ作りたいどうすればいいの?

いざ何かを作ろうとしたときにやっぱり知識が足りない・・・。
情報が溢れているのでカオス化してどうすりゃいいの?ってなるんですよね。
自分が作りたいモノを詳しい方に聞きながら作れる環境がベストなんだろうなと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

画像をクリックすると詳細画面に遷移する方法

環境

この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。

目的

レポート一覧画面において、投稿されたレポートの画像をクリックすると詳細が見れるようにする。

結論: ネストを使用

画像をクリックした際に、詳細画面に遷移させるには、link_toメソッドにネストを用いることで解決できます。do〜endで囲む。

index.html.erb
    <%= link_to report_path(report.id) do %>
      <div class="content_post">
        <%= image_tag report.image if report.image.attached? %>
        <p>顧客名:<%= report.name %></p>
        <span class="name">
          <%= report.date %>
        </span>
      </div>
    <% end %>

まとめ

ネストは、ルーティングの設定の際にもどのレポートにコメントを行うのかの指定を出来、非常に役に立つ機能であると思います!
同じような悩みや壁にぶつかっている人の役に立てれば幸いです!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

lengthメソッドについて

lengthメソッド

文字列が持つメソッドです。
length(レングス)メソッドは文字列の文字数を数えてくれるメソッドです。
文字間の空白も数えられます。

メソッドの使用は、
以下のように値に対してメソッド名「length」をドット.で繋ぎ実行します。

【例】irb
# 文字列の文字数を出す
irb(main):001:0> "Hello World".length
=> 11

"Hello World".lengthは、1つの式として見ることもできますね。
上の例で=>の後に表示されているのは、「Hello World」の文字数「11」です。
文字自体は、「10」文字ですが、「 」空白も入れての「11」文字になります。

irbで以下のコードを実行してみましょう

では、実際にlengthメソッドを試してみましょう。

irb
# lengthメソッドで文字数を出す
irb(main):001:0> "good morning".length

# 続けてこのように表示されれば成功
=> 12

まとめ

メソッドとは、プログラミングにおける何らかの処理をまとめたもの。
lengthメソッドとは、文字列の文字数を数えるメソッドのこと。
⚠︎空白(スペース)も数えられます。

以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails6のjs.erb内でJQueryを使う方法

ちょっとはまったのでメモ

概要

Rails6のビューのremote:trueなフォームを受けとったコントローラで、js.erb を呼び出した時、JQuery $('#hoge')が動作しなかった。
※webpacker配下では正しく動作済み。

発生したJSエラー: Uncaught ReferenceError: $ is not defined

解決方法

app/javascript/packs/application.js内に以下の一行を追記する

app/javascript/packs/application.js
...
require("bootstrap")
require("admin-lte")

window.$ = jQuery; // ここ!
hogehoge.js.erb
$('.modal_area').html('<%= j(render "modal") %>');
$('#modal').modal('show');

config/webpack/environment.js で同じような定義をしてたけど、js.erb ファイル内から使うにはこの記述が必要だった。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

NameError: uninitialized constantを解決する【ActionMailer】

概要

製作中のアプリケーションにAction Mailerを導入して実装しようとしたら序盤で沼にハマったので備忘録として記録します。

参考にした記事

上記の記事の4 メールを送信してみようでエラーが発生

NameError: uninitialized constant InquiryMailer

最初はクラス名やファイル名の単純なエラーかと思ったが一向に解決しない。

結論

以下の記事にたどり着き、どうやらspringが悪さをしているらしい。
試しに止めてみたら上手くいきました。

spring stop

参考にした記事
springについて

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails 画像をスライドさせる 【Swiper】

やりたい事

よくあるホームページで、画像が自動でスライドしていくのがあると思います。
あれを今回「Swiper」を使い簡単に実装しようと思います。
SwiperはダウンロードとCDNがあるので今回はCDNの方で実装を行います。

実装

こちらからコピーして読み込む。https://cdnjs.com/libraries/Swiper

https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/js/swiper.min.js
https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/css/swiper.css

CDNで読み込む例

<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/css/swiper.min.css">
</head>
<body>
〜中略〜
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/js/swiper.min.js"></script>
</body>

SwiperのHTMLの基本の記述

<div class="swiper-container"> 
   <!-- メイン表示部分 --> 
   <div class="swiper-wrapper"> 
     <!-- 各スライド -->
     <div class="swiper-slide"><img src="/assets/01.jpg" alt style="width: 100%; height: 100%;"></div>
     <div class="swiper-slide"><img src="/assets/02.jpg" alt style="width: 100%; height: 100%;"></div>
     <div class="swiper-slide"><img src="/assets/03.jpg" alt style="width: 100%; height: 100%;"></div>
   </div>
   <!-- ナビケーション -->
   <div class="swiper-button-prev"></div>
   <div class="swiper-button-next"></div>
   <div class="swiper-pagination"></div>
</div>

CSSでサイズ調整

全体を囲う<div class="swiper-container">にCSSで調整する事で、スライダーをサイズを設定する。

.swiper-container{
   width: 1000px;
   height: 400px;
}

Swiperの基本設定のJavaScript記述

<script>
    var mySwiper = new Swiper('.swiper-container');
</script>

これで一応、最低限の機能で動くスライダーの完成です。
ただし、本当に最低限の機能「イメージを左右にマウスなどでドラックすれば動く」という状態であり、左右の矢印ナビゲーションや、自動再生などは機能しない状態。

Swiperのオプションを追加

オプションを追加していきます。オプション色々ありますが今回はこれでやります。

<script>
    var mySwiper = new Swiper ('.swiper-container', {
      loop: true,         //画像のループ
      effect: 'slide',    //切り替わるときのアニメーション
      speed: 3000,        //画像の切替スピード
      autoplay: {         //自動で動かす
        delay: 3000,
        disableOnInteraction: true
      },
      pagination: {        //ページネーション
        el: '.swiper-pagination',
      },
      navigation: {        //ナビケーション
        nextEl: '.swiper-button-next',
        prevEl: '.swiper-button-prev',
      },
    });
</script>

実装完了

最終的に下記の様になります。

<!DOCTYPE html>
<html>
  <head>
    <title>Mailers</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application' %>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/css/swiper.min.css">
  </head>
  <body>
    <div class="swiper-container">
    <!-- メイン表示部分 -->
      <div class="swiper-wrapper">
      <!-- 各スライド -->
        <div class="swiper-slide"><img src="/assets/01.jpg" alt style="width: 100%; height: 100%;"></div>
        <div class="swiper-slide"><img src="/assets/02.jpg" alt style="width: 100%; height: 100%;"></div>
        <div class="swiper-slide"><img src="/assets/03.jpg" alt style="width: 100%; height: 100%;"></div>
      </div>
      <div class="swiper-button-prev"></div>
      <div class="swiper-button-next"></div>
      <div class="swiper-pagination"></div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/js/swiper.min.js"></script>
    <script>
        var mySwiper = new Swiper ('.swiper-container', {
          loop: true,        //画像のループ
          effect: 'slide',   //切り替わるときのアニメーション
          speed: 3000,       //画像の切替スピード
          autoplay: {        //自動で動かす
            delay: 3000,
            disableOnInteraction: true
          },
          pagination: {      //ページネーション
            el: '.swiper-pagination',
          },
          navigation: {      //ナビケーション
            nextEl: '.swiper-button-next',
            prevEl: '.swiper-button-prev',
          },
        });
    </script>
  </body>
</html>

おわり

お疲れ様でした。Railsであれば実装完了をコピペすれば動くはずです。
参考リンクにオプションの細かな内容が記載されていますので参考にしてみて下さい。
https://garigaricode.com/swiper/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails 画像を自動でスライドさせる 【Swiper】

やりたい事

よくあるホームページで、画像が自動でスライドしていくのがあると思います。
あれを今回「Swiper」を使い簡単に実装しようと思います。
SwiperはダウンロードとCDNがあるので今回はCDNの方で実装を行います。

実装

こちらからコピーして読み込む。https://cdnjs.com/libraries/Swiper

https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/js/swiper.min.js
https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/css/swiper.css

CDNで読み込む例

<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/css/swiper.min.css">
</head>
<body>
〜中略〜
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/js/swiper.min.js"></script>
</body>

SwiperのHTMLの基本の記述

<div class="swiper-container"> 
   <!-- メイン表示部分 --> 
   <div class="swiper-wrapper"> 
     <!-- 各スライド -->
     <div class="swiper-slide"><img src="/assets/01.jpg" alt style="width: 100%; height: 100%;"></div>
     <div class="swiper-slide"><img src="/assets/02.jpg" alt style="width: 100%; height: 100%;"></div>
     <div class="swiper-slide"><img src="/assets/03.jpg" alt style="width: 100%; height: 100%;"></div>
   </div>
   <!-- ナビケーション -->
   <div class="swiper-button-prev"></div>
   <div class="swiper-button-next"></div>
   <div class="swiper-pagination"></div>
</div>

CSSでサイズ調整

全体を囲う<div class="swiper-container">にCSSで調整する事で、スライダーをサイズを設定する。

.swiper-container{
   width: 1000px;
   height: 400px;
}

Swiperの基本設定のJavaScript記述

<script>
    var mySwiper = new Swiper('.swiper-container');
</script>

これで一応、最低限の機能で動くスライダーの完成です。
ただし、本当に最低限の機能「イメージを左右にマウスなどでドラックすれば動く」という状態であり、左右の矢印ナビゲーションや、自動再生などは機能しない状態。

Swiperのオプションを追加

オプションを追加していきます。オプション色々ありますが今回はこれでやります。

<script>
    var mySwiper = new Swiper ('.swiper-container', {
      loop: true,         //画像のループ
      effect: 'slide',    //切り替わるときのアニメーション
      speed: 3000,        //画像の切替スピード
      autoplay: {         //自動で動かす
        delay: 3000,
        disableOnInteraction: true
      },
      pagination: {        //ページネーション
        el: '.swiper-pagination',
        type: 'bullets',
        clickable: true
      },
      navigation: {        //ナビケーション
        nextEl: '.swiper-button-next',
        prevEl: '.swiper-button-prev',
      },
    });
</script>

実装完了

最終的に下記の様になります。

<!DOCTYPE html>
<html>
  <head>
    <title>Mailers</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application' %>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/css/swiper.min.css">
  </head>
  <body>
    <div class="swiper-container">
    <!-- メイン表示部分 -->
      <div class="swiper-wrapper">
      <!-- 各スライド -->
        <div class="swiper-slide"><img src="/assets/01.jpg" alt style="width: 100%; height: 100%;"></div>
        <div class="swiper-slide"><img src="/assets/02.jpg" alt style="width: 100%; height: 100%;"></div>
        <div class="swiper-slide"><img src="/assets/03.jpg" alt style="width: 100%; height: 100%;"></div>
      </div>
      <div class="swiper-button-prev"></div>
      <div class="swiper-button-next"></div>
      <div class="swiper-pagination"></div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.3.7/js/swiper.min.js"></script>
    <script>
        var mySwiper = new Swiper ('.swiper-container', {
          loop: true,        //画像のループ
          effect: 'slide',   //切り替わるときのアニメーション
          speed: 3000,       //画像の切替スピード
          autoplay: {        //自動で動かす
            delay: 3000,
            disableOnInteraction: true
          },
          pagination: {      //ページネーション
            el: '.swiper-pagination',
            type: 'bullets',
            clickable: true
          },
          navigation: {      //ナビケーション
            nextEl: '.swiper-button-next',
            prevEl: '.swiper-button-prev',
          },
        });
    </script>
  </body>
</html>

おわり

お疲れ様でした。Railsであれば実装完了をコピペすれば動くはずです。
参考リンクにオプションの細かな内容が記載されていますので参考にしてみて下さい。
https://garigaricode.com/swiper/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

誤った情報をpushしてしまった時の対処法

この記事で分かること

  • 誤った情報をpushしてしまった
  • 誤った情報をcommitしてしまった

誤った情報をpushしてしまった

pushした情報をローカルリポジトリに戻すことはできません。したがって、pushする前に作業をしているブランチは正しいのかどうか、必ず確認するようにしましょう。
それでも間違ってpushしてしまうことがあります。ローカルリポジトリにその情報は戻せないものの、リモートリポジトリにある誤ったcommit情報は取り消すことができます

commitを取り消す方法

cbe00f28b88d5f18b9c71024034afe3d.png

commitを取り消すためには、revertと呼ばれる技術を用います
間違ってpushしたcommitを取り消すことができます。commitを削除するのではなく、「指定するcommitを取り消すためのcommit」を追加で行います。
revertはcommitされた変更と逆になる変更を追加することで、commitを取り消します

誤った情報をcommitしてしまった

83c821f4a185cf767e80dcde53e109da.png

現場からは以上です!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails] find と find_by の違い

この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。
findとfind_byについて曖昧なところがあったので、自分なりにまとめてみました。

find

  • 引数にはid(主キー)を指定します。
  • 指定したidのレコードを取得するというイメージです。
  • idが見つからない時は例外(RecordNotFound)が返って来ます。赤いエラーページが発生してしまうのですね。
  • 引数を複数指定することも可能です。
モデル名.find(idデータ)
  • 具体的には以下のように使います。
Item.find(1) # => idが1のレコードを返す
Item.find(1,3,5) # => 指定したidを配列で返す

find_by

  • データは1番最初に合致した1件のみ取得できます。
  • id以外のカラム名なども検索条件にできます。
  • 条件に合致するものがないとnilを返します。取得データがなくてもfind_byの記述以降も処理を続けたい時に便利ですね。
  • 条件は複数指定可能です。
モデル名.find_by(条件)
  • 具体的には以下のように使います。
Article.find_by(title: 'hoge') 
# => titleが'hoge'で最初に合致したデータを返す

Fruit.find_by(name: 'apple', color: 'red') 
# => nameが'apple'でcolorが'red'のデータを返す

2つ条件を指定して1つだけ合致しなかった場合

Fruit.find_by(name: 'apple', color: 'blue') #=> nilを返す
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

find と find_by の違い

この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。
findとfind_byについて曖昧なところがあったので、自分なりにまとめてみました。

find

  • 引数にはid(主キー)を指定します。
  • 指定したidのレコードを取得するというイメージです。
  • idが見つからない時は例外(RecordNotFound)が返って来ます。赤いエラーページが発生してしまうのですね。
  • 引数を複数指定することも可能です。
モデル名.find(idデータ)
  • 具体的には以下のように使います。
Item.find(1) # => idが1のレコードを返す
Item.find(1,3,5) # => 指定したidを配列で返す

find_by

  • データは1番最初に合致した1件のみ取得できます。
  • id以外のカラム名なども検索条件にできます。
  • 条件に合致するものがないとnilを返します。取得データがなくてもfind_byの記述以降も処理を続けたい時に便利ですね。
  • 条件は複数指定可能です。
モデル名.find_by(条件)
  • 具体的には以下のように使います。
Article.find_by(title: 'hoge') 
# => titleが'hoge'で最初に合致したデータを返す

Fruit.find_by(name: 'apple', color: 'red') 
# => nameが'apple'でcolorが'red'のデータを返す

2つ条件を指定して1つだけ合致しなかった場合

Fruit.find_by(name: 'apple', color: 'blue') #=> nilを返す
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む