20200817のRailsに関する記事は21件です。

herokuデプロイ中precompiling assets failedとエラーが出た時

ローカル環境では問題なく動いていたのにherokuでデプロイ中にprecompiling assets failedとエラーが出たので解決方法をまとめます。

logを調べているうちに環境内に問題がありそうだったので
ターミナルでエラー解析をします。

 RAILS_ENV=development bin/rails assets:precompile

こちらを実行することで開発環境ないでエラーがないかを確認することができます。

中身を見てみると、、、

warning Integrity check: Flags don't match                                     
error Integrity check failed                                                   
error Found 1 errors.                                                          


========================================
  Your Yarn packages are out of date!
  Please run `yarn install --check-files` to update.
========================================


To disable this check, please change `check_yarn_integrity`
to `false` in your webpacker config file (config/webpacker.yml).

ローカルでyarnを最新の状態にしているからなのかファイルのバージョンに古いのがあったためupdateする必要があったのかなと思います。

また、

To disable this check, please change `check_yarn_integrity`
to `false` in your webpacker config file (config/webpacker.yml).

このままではチェックと指示があるので下記のように変更します。 

/config/webpacker.yml
check_yarn_integrity: false

この状態でもエラーが出たので下記コマンドで本番環境で問題がないか確認してみます。

RAILS_ENV=production bin/rails assets:precompile

UnitConversionError Incompatible units: 'px' and ‘%’

imcompatibleは相容れないという意味なんおでpxと%を同時に使っている可能性があります。

.main{
  height: (100% - 780px);
  margin: 0 auto;
}

heightの計算にcalcを書いてない!!

.main{
  height: calc(100% - 780px);
  margin: 0 auto;
}

もう一度デプロイするとうまくいきました。

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

Railsでワクワク個人開発  第3回:データの関連付け/ seedデータ投入

関連付けとモデル

 日々の記憶がおぼろげだが、ここに記しておこう。関連づけられたデータを作成してみることにした。DB設計の段階から、ユーザーと彼らがもつ植物は関連付けようと考えていた。一人のUserは複数のPlantを所持する。共有することはしない。

 Userモデルはさきの記事でmigrateした。今回はPlantモデルをつくる。
rails g model plant をターミナルに打ち込むとplantができる。便利だ。 db/migrateフォルダから対応するファイルを開く。こんな感じで書く。

class CreatePlants < ActiveRecord::Migration[6.0]
  def change
    create_table :plants do |t|
      t.integer :user_id, null: false
      t.string :plant_name, null: false
      t.string :img
      t.timestamps
    end
  end
end

 このときにDB設計が生きてくる。場当たり的にこれらを設定するのはうまくいかない。
終了したらmigrateをしよう。

モデルクラスの修正

 関連付けのお約束。モデルクラスの修正をした。

app/model/plant.rb

class Plant < ApplicationRecord
  belongs_to :user
end

app/model/user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  has_many :plants
end

plantはuserに属している、userは多くのplantを持っている。ということを書いた。

seedデータ投入

 ここで、タネを入れる。seedとかいうサンプルデータをあらかじめ入れておく。

db/seed.rb

User.create(email: 'test@example.com', password: 'password')
User.create(email: 'test2@example.com', password: 'password')
Plant.create(user_id:1, plant_name: "flower", img: "flower_img") 
Plant.create(user_id:1, plant_name: "sun_flower", img: "sun_flower_img") 
Plant.create(user_id:2, plant_name: "dia", img: "dia_img") 
Plant.create(user_id:3, plant_name: "rose", img: "rose_img") 

ターミナルで rails db:seed と打つ。これでOK。 終了したらrailsのコンソールからデータを確認しよう。 rails cでできる。

 User.allと打ち込んだらいいぐあいに表示されるだろうか。よし。

次回予告

 いよいよネストされたリソースを使ってCRUD処理を書く。このあたり、途中経過がよくわからなくなっているので、結果だけ書いていく。

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

Slack APIを使ってみよう!【Slack + Rails】

はじめに

この記事では、Slackへメッセージを送るRailsアプリを作成してみます。
動作としてはこんな感じです。

  1. http://localhost:3000/hello にアクセスする
  2. Slackに「こんにちは」とメッセージが送られる

Slack APIとは何か?

Slack用のアプリケーション開発のためにSlackから公開されているAPIです。

事前準備

  1. Slackのワークスペースを作成する
    下記ページを参考に、Slackのワークスペースを作成しておきましょう。

※注意
アプリケーション開発用のワークスペースをすでに作成済みであれば、
新たに作成する必要はありません。
実際の業務などで使用しているワークスペースを流用しないようにしてください。

Slackアプリを作ってみよう

まずは、Slack側でアプリを作ってみます。

アプリの新規作成

  1. 下記ページにアクセス
  2. 「Create New App」ボタンを押してモーダルを開きます。
  3. App Name は 「テストBot」(名前はなんでも良い)、
    Develoment Slack Workspace には作成した開発用のワークスペースを指定します。
  4. 右下の「Create App」ボタンを押すと、アプリが作成されます。 Slackアプリ新規作成Modal.png

アプリのPermission(権限)の設定

  1. 権限設定画面を開く
    アプリ新規作成後、下記のようなアプリの基本情報画面に遷移します。
    Install your app to your workspace というメニューを開くと、
    「最低1つ以上のfeatureか、permission scopeを設定する必要がある」と書いてあります。
    アプリの基本情報画面.png このpermission scopeというリンクを押すと、権限設定画面に移動します。 権限設定画面.png
  2. 必要なスコープの設定 権限設定画面で、必要な権限を設定します。
    今回は、 メッセージの送信をできるようにしたい ので、
    chat:write というスコープを設定します。
    これで、Botとして参加しているチャンネル内でメッセージの送信を行えるようになります。 スクリーンショット 2020-08-16 21.45.52.png
    スコープにはいろいろな種類があり、
    それぞれのアプリに最低限必要なもののみを設定することで、
    セキュリティを保つことができます。

これで権限設定は完了です。

Botを設定する

  1. Botの名前を設定
    左サイドメニューからApp Homeを選択して、アプリケーションのホーム画面を開きます。
    赤枠で囲んだ部分の「Edit」ボタンを押して、アプリの名前を設定します。 Botの設定画面.png 今回は下記のように設定しましたが、好きな名前で設定して問題ないです。 Botの名前設定モーダル.png

これでワークスペースにアプリをインストールできるようになりました。

ワークスペースにアプリをインストールする

  1. インストール画面を開く
    左サイドメニューからInstall Appを選択して、
    ワークスペースへのアプリインストール画面を開きます。 アプリインストール画面.png
  2. インストールの確認画面
    「Install App To Workspace」ボタンを押すと、下記のような画面が開きます。
    (画像では、ワークスペース名などを隠しています。)
    「実行出来る内容」の部分が期待通りであることを確認して、「許可する」ボタンを押しましょう。 インストールの確認画面.png
  3. トークンが発行される 「許可する」ボタン押下後、下記の画面に遷移します。
    この時に表示されるトークンが、
    Slack APIを利用したメッセージの送信時に必要なので、メモしておいてください。
    (このトークンを公開してはいけません。
    トークンを知った人であれば誰でも、先ほど作成したBotとしてワークスペースへメッセージを送ることができるようになってしまいます。) スクリーンショット 2020-08-16 22.12.49.png

ワークスペースのチャンネルにアプリを招待する

任意のチャンネルに、作成したアプリを招待します。
アプリを招待したいチャンネルを開いて、
/invite @アプリのワークスペースでの表示名 を送信します。
(今回は #テスト用チャンネル という名前のチャンネルです。
任意のチャンネルで問題ないです。)

これで、 #テスト用チャンネル 内で作成したアプリがメッセージを送信できるようになりました。
Slack招待.png

以上で、Slack側の準備は完了です。

RailsアプリからSlackへメッセージを送ってみよう

Railsアプリの準備

下記リポジトリに、今回使うRailsアプリを用意しているのでcloneしてください。

README.md の手順にしたがって、環境構築を行ってください。

今回使うgemの説明

下記2つのgemを Gemfile に追加しています。

1. dotenv-rails

開発環境で、
アプリケーションのルートディレクトリに配置した .env ファイル内から
ENV に変数を読み込むためのgemです。

今回は、ワークスペースにアクセスするためのトークンの管理に使用します。

2. slack-ruby-client

RubyでSlackのAPIを利用するためのgemです。

今回は、Slackへメッセージを送信するために使います。

トークンを設定する

Railsアプリケーションに、作成したSlackアプリのトークンを設定します。
(ここで説明するのはレガシーな方法なですが、
今回はいったん手っ取り早くできるこちらの方法を利用します。)

.env ファイルを作成する

アプリケーションのルートディレクトリに、 .env というファイルを作成しましょう。
ファイルの中身は下記です。

.env
BOT_USER_ACCESS_TOKEN=Botのアクセストークン

Botのアクセストークンの部分は、
こちらで作成したトークンに置き換えてください。

トークンの設定

次に、下記のファイルを作成してください。
これで、gem slack-ruby-client を利用したAPIの実行時、
認証用のトークンがパラメータとして送信されるようになります。

config/initializers/slack_ruby_client.rb
Slack.configure do |config|
  config.token = ENV['BOT_USER_ACCESS_TOKEN']
end

hello アクションを作成してみよう

では、slack-ruby-clientを利用してSlackAPIを実行するように、
コントローラーのアクションを作ってみます。

ルーティングの追加

config/routes.rb にルーティングを追加します。
/hello というパスにはapplicationコントローラーhello アクション が対応する」
というルーティングです。

config/routes.rb
Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
+ get "hello", to: 'application#hello'
end

アクションを作成する

hello アクションを作成します。

app/controllers/application_controller.rb
class ApplicationController < ActionController::API
  def hello
    client = Slack::Web::Client.new
    client.chat_postMessage(
      channel: '#テスト用チャンネル',
      text: 'こんにちは'
    )
  end
end

上記のソースについて簡単に説明します。

  • client = Slack::Web::Client.new
    slack-ruby-client では、基本的にこのオブジェクトをレシーバとして、
    様々なSlackAPIに対応したメソッドを呼び出します。

  • client.chat_postMessage
    これは、 chat.postMessage methodというAPIに対応する slack-ruby-client のメソッドです。

    見ただけでわかると思うのですが、
    メソッドの引数で「メッセージを送信するチャンネル」と「テキスト」を指定しています。

メッセージを送る

では、実際にメッセージを送信してみましょう。

bin/railsでサーバーを起動し、
ブラウザで http://localhost:3000/hello にアクセスします。
Slackを確認すると、下記のようにメッセージが送信されていると思います。

スクリーンショット 2020-08-16 23.18.49.png

今回作りたかったアプリケーションはこれで完成です。
今回は一つのAPIしか利用していませんが、
いろいろなAPIを複合的に利用することで目的のアプリを作成できるようになると思います。

Block Kit Builderを使ってメッセージのフォーマットを整えてみよう

実際にアプリを作成した場合、もう少しいい感じにテキストを表示したいと思います。
(箇条書き、文字サイズ、文字色の指定など)

そんな場合は、下記のBlock Kit Builderを使ってみましょう。

これを使うと、簡単にボタンやテキストを配置のプロトタイプを作成することができます。

BlockKitBuilder使用例.png

画面の右側に作成したリッチテキストから生成されたコードが表示されるので、
これをコピーすればすぐにアプリケーションに組み込むことができます。

作成したコード
{
    "blocks": [
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "今日も暑いね:watermelon: 無理せずがんばろう:smile:"
            }
        },
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "何をチェックする?",
                "emoji": true
            }
        },
        {
            "type": "actions",
            "elements": [
                {
                    "type": "button",
                    "text": {
                        "type": "plain_text",
                        "emoji": true,
                        "text": "天気"
                    },
                    "style": "primary",
                    "url": "https://www.jma.go.jp/jp/yoho/"
                },
                {
                    "type": "button",
                    "text": {
                        "type": "plain_text",
                        "emoji": true,
                        "text": "カレンダー"
                    },
                    "style": "danger",
                    "url": "https://calendar.google.com/"
                },
                {
                    "type": "button",
                    "text": {
                        "type": "plain_text",
                        "emoji": true,
                        "text": "ニュース"
                    },
                    "url": "https://news.google.co.jp/"
                }
            ]
        }
    ]
}

hello アクションを更新してみよう

試しに、先ほど作成した hello アクションを更新して、
作成したブロックをメッセージとして送信できるようにしてみましょう。

chat_postMessageの引数に、 blocks を追加しています。
(ソースコードが長いので折りたたんでいます。)

hello アクションを更新
app/controllers/application_controller.rb
  def hello
    client = Slack::Web::Client.new
    client.chat_postMessage(
      channel: '#テスト用チャンネル',
      text: 'こんにちは',
      blocks: [
        {
          "type": "section",
          "text": {
            "type": "mrkdwn",
            "text": "今日も暑いね:watermelon: 無理せずがんばろう:smile:"
          }
        },
        {
          "type": "header",
          "text": {
            "type": "plain_text",
            "text": "何をチェックする?",
            "emoji": true
          }
        },
        {
          "type": "actions",
          "elements": [
            {
              "type": "button",
              "text": {
                "type": "plain_text",
                "emoji": true,
                "text": "天気"
              },
              "style": "primary",
              "url": "https://www.jma.go.jp/jp/yoho/" # 気象庁HP
            },
            {
              "type": "button",
              "text": {
                "type": "plain_text",
                "emoji": true,
                "text": "カレンダー"
              },
              "style": "danger",
              "url": "https://calendar.google.com/" # Googleカレンダー
            },
            {
              "type": "button",
              "text": {
                "type": "plain_text",
                "emoji": true,
                "text": "ニュース"
              },
              "url": "https://news.google.co.jp/" # Googleニュース
            }
          ]
        }
      ]
    )
  end

Railsアプリを起動し、 再度 http://localhost:3000/hello にアクセスします。
すると、Slackには下記のような通知がくると思います。

Blockを含んだメッセージ.png

Block Kit Builderの紹介は以上です。
Block Kit のチュートリアルについては、こちらも参照してください。

あとがき

実際にRailsアプリをHerokuなどにデプロイすることで、
Slack上でコマンドを実行するとそれに応じてメッセージを返すBotを作成することもできます。

記事ボリュームの都合上入れられなかったので、それについてはまた次回書きます。

Slack APIについてはいくつか日本語翻訳されているページもあるので、
こちら をベースにいろいろ学習できると思います。

参考URL

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

Railsでactive_hashを使って都道府県などのセレクトボックスを作る

はじめに

・某プログラミングスクールのチーム開発で学んだ知識の備忘録として書きます。
・商品がどの都道府県から発送されるのか、という情報のために使用しました。
・間違いなどあれば指摘いただけますと幸いです。

active_hashって何?

ハッシュデータとして定義したデータを、擬似的にActiveRecordのように扱うことができるのがactive_hashというgem。
・都道府県など、項目数がほぼ変わらない静的データはテーブルにせず、active_hashを使うと便利。
・ActiveRecord <=> ActiveHashのリレーションを張ることができる

使い方

順を追って書いていきます。

Gemfile
# ファイルの一番下に記述追加。haml記法で記述するのでhaml-railsも入れます
gem 'active_hash'
gem 'haml-rails'
ターミナル
$ bundle install

これでactive_hashがインストールされました。
ミニアプリを作ってみます。

ターミナル
$ rails g model item name:string prefecture_id:integer

models/items.rb
db/migrate/20200817033056_create_items.rb
が作成されました。

20200817033056_create_items.rb
class CreateItems < ActiveRecord::Migration[6.0]
  def change
    create_table :items do |t|
      t.string :name
      t.integer :prefecture_id

      t.timestamps
    end
  end
end
ターミナル
$ rails db:migrate

これでitemsテーブルができました。

ここ大事です

prefectureモデルを作るのですが、手動で作ります。
rails g modelはしません。

modelsディレクトリにprefecture.rbファイルを直接作成します。
作成したら中身を以下のように記述します。

prefecture.rb
class Prefecture < ActiveHash::Base
  self.data = [
      {id: 1, name: '北海道'}, {id: 2, name: '青森県'}, {id: 3, name: '岩手県'},
      {id: 4, name: '宮城県'}, {id: 5, name: '秋田県'}, {id: 6, name: '山形県'},
      {id: 7, name: '福島県'}, {id: 8, name: '茨城県'}, {id: 9, name: '栃木県'},
      {id: 10, name: '群馬県'}, {id: 11, name: '埼玉県'}, {id: 12, name: '千葉県'},
      {id: 13, name: '東京都'}, {id: 14, name: '神奈川県'}, {id: 15, name: '新潟県'},
      {id: 16, name: '富山県'}, {id: 17, name: '石川県'}, {id: 18, name: '福井県'},
      {id: 19, name: '山梨県'}, {id: 20, name: '長野県'}, {id: 21, name: '岐阜県'},
      {id: 22, name: '静岡県'}, {id: 23, name: '愛知県'}, {id: 24, name: '三重県'},
      {id: 25, name: '滋賀県'}, {id: 26, name: '京都府'}, {id: 27, name: '大阪府'},
      {id: 28, name: '兵庫県'}, {id: 29, name: '奈良県'}, {id: 30, name: '和歌山県'},
      {id: 31, name: '鳥取県'}, {id: 32, name: '島根県'}, {id: 33, name: '岡山県'},
      {id: 34, name: '広島県'}, {id: 35, name: '山口県'}, {id: 36, name: '徳島県'},
      {id: 37, name: '香川県'}, {id: 38, name: '愛媛県'}, {id: 39, name: '高知県'},
      {id: 40, name: '福岡県'}, {id: 41, name: '佐賀県'}, {id: 42, name: '長崎県'},
      {id: 43, name: '熊本県'}, {id: 44, name: '大分県'}, {id: 45, name: '宮崎県'},
      {id: 46, name: '鹿児島県'}, {id: 47, name: '沖縄県'}
  ]
end

itemモデルにも記述を追加します。

item.rb
class Item < ApplicationRecord
  # この2行を追加
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to_active_hash :prefecture

end

準備は以上です。
ちゃんと表示できて、データ送信もできたら完成とします。
コントローラーとビューを作ってルーティングも設定します。

ターミナル
$ rails g controller items new
items_controller.rb
class ItemsController < ApplicationController
  def new
    @item = Item.new
  end
  def create
    @item = Item.new(item_params)
    if @item.save
      redirect_to new_item_path
    else
      render 'new'
    end
  end

  private

  def item_params
    params.require(:item).permit(:name, :prefecture_id)
  end
end
items/new.html.haml
.form
  = form_with model: @item, local: true do |f|
    = f.text_field :name  # 入力フィールドです
    = f.collection_select :prefecture_id, Prefecture.all, :id, :name, {include_blank: "---"}, {class: ""}
    = f.submit "送信"

都道府県はf.collection_selectを使ってセレクトボックス形式で取得します。
= f.collection_select 保存されるカラム名, オブジェクトの配列, カラムに保存される項目, 選択肢に表示されるカラム名, {オプション}, {htmlオプション}

routes.rb
Rails.application.routes.draw do
  resources :items
  root 'items#new'
end

入力フィールドとセレクトボックスを埋めて送信したら入力画面に戻るようにしています。
成功したら入力フィールドが空になります。
sequelproなどのGUIツールでテーブルの中身を見るとデータが保存されているはずです。

都道府県だけじゃなくこんなのにも使えます

・商品の状態

models/item_condition.rb
class ItemCondition < ActiveHash::Base

  self.data = [
    {id: 1, condition: '新品、未使用'}, {id: 2, condition: '未使用に近い'}, {id: 3, condition: '目立った傷や汚れなし'},
    {id: 4, condition: 'やや傷や汚れあり'}, {id: 5, condition: '傷や汚れあり'}, {id: 6, condition: '全体的に状態が悪い'}
  ]

  include ActiveHash::Associations
  has_many :items

end

この場合、f.collection_selectはこんな感じです。

items/new.html.haml
= f.collection_select :item_condition_id, ItemCondition.all, :id, :condition, {include_blank: "選択してください"}, {class: "select"}

第5引数にはデフォルトで表示させたい文字列を、
第6引数にはクラス名やid名を指定します。

まとめ

ミニアプリを作ったので少し長くなりましたが、active_hashを実装するだけなら以下の手順です。
1.gemをインストール
2.カラム作成(itemsテーブルにprefecture_idカラムをinteger型で作成
3.モデルファイル作成してテーブルにあたる記述を追加(prefecture.rb
4.Itemモデル側にアソシエーションを記述。通常とは違うので注意

以上です。
今回active_hashのメソッドとして全部のデータを取得するためにallメソッドを使いましたが、他にも色々あります。
参考サイトを載せるので必要であればそちらから見てください。

参考

【Rails】active_hashを使って疑似モデルを作ろう
https://pikawaka.com/rails/active_hash
active_hashまとめ
https://qiita.com/Toman1223/items/8633142312bfa886d50b

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

【パス指定】ネストしたリソースのパス指定

概要

ネストしたリソースのパス指定方法について、一瞬戸惑ってしまったので備忘録として記録します。

環境

・ruby '2.5.7'
・rails '5.2.3'
・rspec-rails '4.0.0.beta2'

指定方法

結論: rails routesしてルーティングを一覧表示して確認する!

(例) Rspecのリクエストテストでパス指定をする

次のような、ルーティングを宣言していたとします。

routes.rb
  resources :datespots do
    resources :comments, only: [:create, :destroy]
  end

ターミナルでrails routesすると、ルーティングが一覧表示される。

                   Prefix Verb   URI Pattern                                                                              Controller#Action
(省略)
        datespot_comments POST   /datespots/:datespot_id/comments(.:format)                                               comments#create
         datespot_comment DELETE /datespots/:datespot_id/comments/:id(.:format)                                           comments#destroy
(省略)

これを元に、パス指定すればOK!

comments_spec.rb
(省略)
    it "有効な内容のコメントが登録できること" do
      expect {
        post "/datespots/#{datespot.id}/comments", params: {
          datespot_id: datespot.id,
          comment: { content: "オシャレですね!" }
        }
      }.to change(datespot.comments, :count).by(1)
    end
(省略)

参考

Rails ガイド 2.7 ネストしたリソース

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

【CSS】flex box画像の改行がしたい

画像付きボックスの改行ができなくて沼ったのでメモ。冷静に調べたらもっと早く解決できたと思いますが自分の検索力の無さを恨みますw

やりたいこと

この画像の様な画像つきのボックスを
画像①
2415a3dd1f923a6e01572cfe02229740.jpg
こんな感じで幅をも持たせて各行に3個ずつ配置したい。
画像②
e8b94a73a0ec11a4887dbd434183b041.jpg

  • まず前提としてボックスの親要素にdisplay: flex;をかけています。

「ボックスのwidthを親要素の32%に広げたらいけるんじゃね?」と思いましたがダメでした。

ソースコード

posts.scss
///コンテナの親要素
.posts {
  margin: 50px 120px 50px;
  height: auto;
  display: flex;
  justify-content: space-between;
  ///コンテナ
  &__container {
    height: 300px;
    width: 32%;
    background-color: white;
    border-radius: 10px;

このコードの様に書くと画像①の様になってしまいます。widthを指定しても無視されてボックスが画面一杯に一列に収まろうとします。

結果

親要素のpostsflex-wrap: wrap; を追加してあげたら画像②の様に折り返して表示されました ^^

flexboxを使うときはwrapをかけないと折り返され無いんですね。
同じ様な感じで困っている人に見てもらえたらいいなと思います。^^ 僕だけかもしれませんがw

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

プログラムを書くときの注意点:その2

【概要】

1.結論
2.オープン・クローズドの原則とは何か
3.オープン・クローズドの原則どう使うのか
4.なぜオープン・クローズドの原則が必要か
5.ここから学んだこと

1.結論

オープン・クローズドの原則にも従う!

2.オープン・クローズドの原則とは何か

●オープン・クローズドの原則とは、


拡張に対して開いていて、
修正に対して閉じていなければならない



つまり、拡張する分にはOKだけど、
拡張した時の修正範囲は最小限に止めようね。
そうしないと破壊的変更(とてつもない修正)を
しないといけなくなるということです!

3.オープン・クローズドの原則はどう使うのか

言葉だけではイメージがしにくいと思うので
例を挙げてみます!

オープン・クローズドの原則
class A
  class Interface B 

class *** implementsB:interface B

class Interface B
  puts ******
オープン・クローズドの原則ではない
class A
 class B
  puts ******

ただあまりにも抽象化しすぎると、
本当に必要でないクラスができてしまいます。
(上記ではわかりやすくするために簡素化しているので
”オープン・クローズドの原則ではない”方がわかりやすいですし、
class A
puts ****でいいまであります。)

上記は簡単に書いているのでまだ追えていますが、
階層が深くなるとどこにいるのか
わからない(可読性がなくなる)
部分がでてきます。

なので、変更箇所が今後ありそうな箇所を
予測した際に有効で、難しい原則です。

これは”プログラムを書くときの注意点:その4(次々回投稿)”
のインターフェース分離の原則でも関わってきます。


4.なぜオープン・クローズドの原則が必要か

結論としては、プログラミングを書く際の要は以下の
3つに集約されると思っています。

Ⅰ)保守性:修正(エラー発見のしやすさ)・管理のしやすさ
Ⅱ)拡張性:追加機能実装のしやすさ
Ⅲ)可読性:記述のわかりやすさ
が必要だと考えております。

上記3つのことは自分が他の4つの原則を説明する際に同じことを言うので、
5つの原則のうちどれかを読んでいただくと
結論はすべてこの3つに収まります。

つまり、上の3つを叶えるには
オープン/クローズドの原則に”も(他の4つの原則もあるので)”従う!!

5.ここから学んだこと

i)implements,interfaceメソッドを知ることができました!

ii)implements,interfaceメソッドを駆使することで
可読性かつ保守性のあるプログラムをかけますが、あまり不本意に適用
したらいいわけでないと思いました。プロジェクトでお客さまに提案する際や、
今後拡張しそうな箇所を予測した上で使う原則であり、非常に奥深い原則だなと感じました。

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

Railsでデータベースの中身を確認する

プログラミングの勉強日記

2020年8月17日 Progate Lv.226
今まではSQLiteStudioで確認していた。
SQLiteStudioの方が見やすいが、見るのに手間がかかるので、コンソールで確認することができたのでまとめる。

方法

 SQLiteはデータベースサーバを使用しないで、データベースごとに1つのファイルを使うことで管理する。

1. SQLiteコマンドのツールのインストール

 SQLiteの公式サイトにアクセスする。Downloadをクリック。
0817.PNG

 Windows10の環境を利用するので、recompiled Binaries for Windowsのsqlite-tools-win32-x86-3330000.zipをクリックして、ダウンロードする。
0817-1.PNG

 ダウンロードが完了したら、zipファイルを展開する。
 今回はRailsアプリの中のdbフォルダの下に展開した3つのファイルを置いた。

0817-2.PNG

2. コンソールの立ち上げ

 dbフォルダの中に移動して、.\sqlite3 .\development.sqlite3とコマンドを入力するとコンソールが立ち上がる。
 sqlite>が出てくれば成功。

.\sqlite3 .\development.sqlite3
SQLite version 3.33.0 2020-08-14 13:23:32
Enter ".help" for usage hints.

主なコマンド

テーブルの一覧の表示

 .tablesで作成したテーブルの一覧を表示する。

sqlite> .tables
ar_internal_metadata  posts                 schema_migrations   
goods                 reviews               users

カラム名などのテーブルの構造を表示する

 .schema テーブル名で指定したテーブルの構造を表示する。

sqlite> .schema users     
CREATE TABLE IF NOT EXISTS "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "email" varchar, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL, "image_name" varchar, "password_digest" varchar);

テーブルの中身を確認する

 select * from テーブル名;でテーブルの中身を確認できる。*ですべてのテーブルの中身を表示できる。セミコロンを忘れないように。

sqlite> select * from users;
1|aiueo|aiueo|2020-08-09 09:28:46.103511|2020-08-09 09:29:37.184446|1.jpg|$2a$12$eJlR9MsvgcnbXaEY2DpD3.hoQG3fy2vwdtE44buDy6DltamJQ/2Jm

コンソールの終了

 .quitでコンソールを終了できる。

.quit

参考文献

SQLiteインストール
【Rails】データベースの中身を確認する方法【Cloud9】

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

Rails enum 都道府県をプルダウン方式で選択

はじめに

個人開発アプリでGoogle APIと連携して地図情報を取得できる様にしたのですが、

住所を全て手入力するのは面倒なので都道府県をプルダウン方式で選択できるようにしようと思います。

new.html.erb
<%= form_for @ride, method: :post do |f| %>
 <%= f.select :prefecture, ['北海道', '青森県', '秋田県', '岩手県' 以下略], { include_blank: '選択してください' } %>
<% end %>

コードの可読性を無視して実装するならこんな感じで入力していくだけなのですが、

このようにview側に47都道府県全てを入力すると非常に見苦しいと思ったのでスマートにできる方法を探してみました。

enum

enumというものがあるようでこれによってviewではなくmodelに記述することができ、

view側のコードをかなりスッキリさせることができます!

class CreateRides < ActiveRecord::Migration[5.2]
  def change
    create_table :Rides do |t|
      t.integer :ride_area, null: false, default: 0
    end
end

まずはintegerでカラムを作成します。

ride.rb
class Ride < ApplicationRecord
 enum ride_area:{
     "---":0,
     北海道:1,青森県:2,岩手県:3,宮城県:4,秋田県:5,山形県:6,福島県:7,
     茨城県:8,栃木県:9,群馬県:10,埼玉県:11,千葉県:12,東京都:13,神奈川県:14,
     新潟県:15,富山県:16,石川県:17,福井県:18,山梨県:19,長野県:20,
     岐阜県:21,静岡県:22,愛知県:23,三重県:24,
     滋賀県:25,京都府:26,大阪府:27,兵庫県:28,奈良県:29,和歌山県:30,
     鳥取県:31,島根県:32,岡山県:33,広島県:34,山口県:35,
     徳島県:36,香川県:37,愛媛県:38,高知県:39,
     福岡県:40,佐賀県:41,長崎県:42,熊本県:43,大分県:44,宮崎県:45,鹿児島県:46,
     沖縄県:47
   }
end

モデル側にはこんな感じで都道府県を書いておきます。

ハッシュのキーがセレクトボックスに表示されます。

new.html.erb
<%= form_for @ride, method: :post do |f| %>
 <%= f.select :prefecture, Ride.ride_areas.keys, {} %>
<% end %>

冒頭で書いたコードをこのように書き換えてあげましょう。

Ride.ride_areas.keys, {} と書く事でモデルに書いている都道府県全てを順番に処理してくれるのでブラウザ上ではプルダウン方式で都道府県が選択できるようになっています!

以上です。

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

テスト投稿です。

rails tutorial 学習日記
$rails console

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

An error occurred while installing libv8 (3.16.14.19), and Bundler cannot continue

bundle install しようとした時に libv8 でエラー
自分の環境では下記の手順で bundle install が通ったので、メモ。

  • エラー
An error occurred while installing libv8 (3.16.14.19), and Bundler cannot continue.Make sure that `gem install libv8 -v ‘3.16.14.19’ —source
  • rbenvにbundleをインストール

「libv8とtherubyracerが入らない時の対処法」をやっても入らないとき - Qiita

bundleがrbenv内のgemを使っていないとbundle installが通らないので、rbenvにbundleをインストール

  • 下記のコマンドを実行

macOS Mojaveで古いlibv8とtherubyracerが入らない時の対処法 - Qiita

brew install v8-315
bundle config --local build.libv8 --with-system-v8
bundle config --local build.therubyracer --with-v8-dir=$(brew --prefix v8-315)

さらにエラーがでた

An error occurred while installing mysql2 (0.4.10), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.4.10' --source 'https://rubygems.org/'` succeeds before bundling.

LIBRARY_PATH の変更

export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/opt/openssl/lib/

一応これで bundle install が通った。

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

プログラムを書くときの注意点:その1

【概要】

1.結論
2.SOLID原則とは何か
3.単一責任の原則はどう使うのか
4.なぜ単一性の原則が必要か
5.ここから学んだこと

1.結論

単一責任の原則にも従おう!

2.SOLID原則とは何か

●SOLID原則とは、
i)単一責任の原則:1つのclassに1つの役割を
ii)オープン/クローズドの原則:追加機能はOK,ただ修正はせずに
iii)リスコフの置換原則:親クラスは子クラスと同じ動きに
iv)インターフェース分離の原則:利用用途に応じた最小限の動きに
v)逆依存性の原則:破壊的変更をさせるな

の英語名の頭文字を取ったものです!
(ここでは分かり易く書きたいため、英語名は省略しています)

3.単一責任の原則はどう使うのか

あくまで原則なので、基本的な考え方の部分になります。
なので例を交えての紹介になります。

例えばご紹介した、(”3つの値の正誤を確かめる条件式~演算子,論理積~
”)https://qiita.com/taka_no_okapi/items/dd92ab3f74cd28d3b364
のプログラムの”マシーン”に”人がお金を投入する”というプログラムをさせたいとします。

user1.rb
class User1
  def initialize(many_money)
    @money = many_money
  end

  def money
    @money
  end

  def choose_drink
    gets.to_i
  end
end

上記のプログラムをマシーンが書いてあるファイルに一気に書いてもいいですが、それですとマシーンが同じ数字を書く機能を持ちつつ人がお金を投入するシステムまで導入し1つのclassに2つの役割が入ってしまいます。
であれば”class Machine” “class user1”で
マシーン(クラス)は1つの役割、ユーザー(クラス)は1つの役割
にした方が保守性・拡張性・可読性が飛躍的に高まります。

4.なぜ単一責任の原則が必要か

結論としては、プログラミングを書く際の要は以下の
3つに集約されると思っています。

Ⅰ)保守性:修正(エラー発見のしやすさ)・管理のしやすさ
Ⅱ)拡張性:追加機能実装のしやすさ
Ⅲ)可読性:記述のわかりやすさ
が必要だと考えております。

上記3つのことは自分が他の4つの原則を説明する際に
同じことを言うので、5つの原則のうちどれかを読んでいただくと
結論はすべてこの3つに収まります。

つまり、上の3つを叶えるには
単一責任の原則に”も(他の4つの原則もあるので)”従おう!!

5.ここから学んだこと

i)単一性の原則は非常に理解しやすく、すぐに適応できるので
意識するだけでプログラムの考えを受け入れやすかったです!

ii)物体ごと(上記の例ですと、user1とMachine)だけではなく
機能ごと(Machineであれば同じ数字を揃える意外に、景品を選んでくれる機能など)でも分けたほうがプログラムしやすいです!

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

Railsのコントローラーについて

概要

Railsアプリケーションのコントローラーについて解説してみたいと思います。

今回のゴール

『MVCモデルについて知る』『コントローラーの役割について』『実践的な使い方』をついて確認することです。

1. MVCモデルとは

アプリケーションを作成する時に、コードを上手に管理するための考え方のひとつです。
あくまで考え方のひとつなので、絶対的に正しいというものではありません。
Railsアプリケーションは、このMVCフレームワークを取り入れています。

MVCの3要素

『Model』『View』『Controller』になります。
 
Model ・・・ システムの中でビジネスロジックを担当する

View ・・・  表示や入出力といった処理をする

Controller ・・・ ユーザーの入力に基づき,ModelとViewを制御する

RailsにおけるMVCの処理の流れ

  1. クライアントからのリクエストを『Controller』が受け取る

  2. 『Controller』『Model』にデータ処理をお願いする

  3. 『Model』はデータベースからデータを処理し、『Controller』にデータを返す

  4. 『Controller』『View』に受け取ったデータの処理をお願いする

  5. 『View』はクライアントが見るのに適した形(HTML文書)を作成し『Controller』に返す

  6. 『Controller』はクライアントにHTML文章をレスポンスとして返す

1〜6を繰り返すことにより、Webアプリケーションとして成り立っています。

2. コントローラーの役割について

結論
・ルーティングから送られた情報をもとに、指定されたコントローラーのアクションメソッドを実行すること
Model・Viewと連携して、クライアントにレスポンスを返すこと

アクションメソッド

ルーティングから指定されたアクションの具体的な処理内容を記述したメソッドです。

アクションメソッドのイメージ
class SamplesController < ApplicationController
  def index
    # 具体的な処理内容
    ......
    ......
  end
end

今回の例ですと...
ルーティングでsamplesコントローラーのindexアクションが指定された時、実行するアクションメソッドをdef index...endという形で記述します。

Modelとの連携について

目的

モデルを介して、データベースの新規作成や変更や取得をすることです。

方法

モデルが継承しているActiveRecord クラスのメソッドを使い、モデルに指示を出します。
下記はメソッドの一部の例になります。

メソッド 内容
all データベースの全てのデータを取得する
find データベース内の、ある1つのデータを取得する
new データの新規作成を生成する
save データベースにデータを保存する
メソッドのイメージ
  (モデルクラス名).[メソッド]
  Sample.all

Viewとの連携について

目的

モデルから受け取ったデータをビューに渡し、クライアントに返すレスポンスデータを作成することです。

方法

モデルからのデータをインスタンス変数を代入します。

  @samples = Sample.all

これにより、ビューファイルでデータを使えるようになります。

3. 実践的な使い方

コントローラーの設定場所

app/controllersディレクトリ内に
コントローラー名_controller.rbファイルを設定します。

コントローラーの命名規制

基本的に『複数形』にします。
理由は、Railsが使用するファイルなどを名前によって自動的に推測するからです。
仮に単数形にもできますが、開発者自身で明示的にコード記述しなければいけなかったり、予期せぬエラーのもとになってしまいます。

名称 備考
コントローラー名 samples
コントローラークラス名 SamplesController キャメルケース
コントローラーファイル名 samples_controller.rb スネークケース

コントローラーファイルの構造

コントローラーファイルの中身は、このようになっています。

app/controllers/samples_controller.rb
  class SamplesController < ApplicationController
    def index
      # 具体的な処理内容
      ......
      ......
    end
  end

作成したコントローラーファイルは『ApplicationControllerクラス』を継承します。
 

ApplicationControllerクラスとは

app/controllers/application_controller.rb
  class ApplicationController < ActionController::Base
  end

app/controllers/application_controller.rbファイルに定義されたクラスです。
ActionController::Baseクラスを継承しただけの、(ほとんど)空のクラスになります。

原則、各コントローラーは、ApplicationControllerクラス継承しているので
アプリケーション共通の機能(ログイン・ログアウトなど)が必要な場合に使用します。
 

ActionController::Baseクラスとは

コントローラーの基本的な機能を提供するクラスです。
リクエスト/レスポンス処理に関わる基盤部分を担っています。

HTTPリクエストのパラメータの処理

コントローラーでは、クライアントからのHTTPリクエストのパラメータを『paramsメソッド』を経由して取得しています。

paramsメソッド

Railsが暗黙的にリクエストパラメータを処理して、ハッシュ形式でデータをparamsに格納してくれるメソッドです。
GETリクエスト・POSTリクエストによるアクセスでも、データの受け取り方に違いはありません。

GETリクエストによるアクセス

HTTPリクエストのリクエストラインの『リクエストURI』にパラメータを含め、Webサーバにアクセスします。
『URL形式』『クエリ形式』でパラメータを渡すことができます。
 

URL形式

下記のルーティング設定があった時に

  Prefix Verb   URI Pattern               Controller#Action
  user   GET    /users/:id(.:format)      users#show

http://sample.com/users/7というURLでアクセスすると
リクエストの:idのパラメータは7という意味になり
Rails内ではparamsに格納されparams[:id]の値は"7"となります。

app/controllers/users_controller.rb
  class UsersController < ApplicationController
    def show
      params[:id] # "7"
    end
  end

 

クエリ形式

URLの最後に「?」に続けて「パラメータ名=値」を記述します。
複数のパラメータがある場合は「&」でつなげて記述します。
 
上記の例の同じルーティングを利用し
http://sample.com/users/7?keyword=query&num=10というURLでアクセスすると
params[:keyword]の値は"query"params[:num]"10"となります。

app/controllers/users_controller.rb
  class UsersController < ApplicationController
    def show
      params[:keyword] # "query"
      params[:num] # "10"
    end
  end

 

POSTリクエストによるアクセス

クライアントがフォームからの入力で「送信」ボタンを押した場合などに発生するリクエストです。
HTTPリクエストの『ボディ』にパラメータを含め、Webサーバにアクセスします。

またGETリクエストに比べて、多くのパラメータを送信することができます。
 

paramsを保存する時の注意点

『params』をデータベースに保存する時は、『Strong Parameters』という仕組みを使います。

Strong Parametersとは

Rails3系まで使われていた『Mass Assignment』の脆弱性を解消するための仕組みです。
『Mass Assignment』では、モデルに保存に関するparamsの情報を記述していましたが
『Strong Parameters』では、コントローラーに保存するparamsの情報を記述します。

Strong_Parametersのイメージ
  class UsersController < ApplicationController
    def create
      @user = User.new(user_params) # user_paramsメソッドを使って、データの新規作成
      @user.save # モデルを介して、データベースに保存する
    end

    # Strong Parametersはクラス外部から呼び出さないので、privateメソッドに記述する
    private
    def user_params
      params.require(:user).permit(:name, :age)
    end
  end

今回の例ですと
user_paramsメソッドで、保存するパラメータを:user:name:ageに指定しています。

requireメソッド

データベースに保存するテーブル名を指定します。

permitメソッド

データベースのテーブルに保存するカラム名を指定します。


コントローラーの解説は以上になります。
ありがとうございました。

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

docker-composeでDeviseを導入

Device
ログイン機能やユーザー登録機能をとても簡単に実装することができるgem。

参考にした記事
https://qiita.com/Orangina1050/items/a16e655519a60f35b394

下準備
コントローラーの作成 ついでにアクションとビューを作成する

terminal
$ docker-compose run web bin/rails g controller comments index 

導入編
Gemfileに、deviseを追加する。

terminal
$ docker-compose run web bundle install #deviseをインストールする
$ docker-compose build #構築する。

終わったら、 deviseの設定ファイルを作成する

terminal
$ docker-compose run web bin/rails g devise:install

ログイン機能用のモデル作成を行い(1)、を行いマイグレーション(2)
その後、ログイン機能に必要なビューファイルをまとめて作成(3)

terminal
$ docker-compose run web bin/rails g devise user #・・・(1)
$ docker-compose run web rake db:migrate #・・・(2)
$ docker-compose run web bin/rails g devise:views  #・・・(3)

views/comments/index.html.erbを編集し、下記を加える

index.html.erb
  <div class="field">
    <%= f.label :name %> <br />
    <%= f.text_field :name %>
  </div>

ちなみに、私はここで、
NoMethodError in Devise::Sessions#new
エラーが発生した。

一度、コンテナを止めて(1)、削除し(2)、再度コンテナを構築したら(3)、解決した。
(理由をわかっていないので宿題ですね)

terminal
$ docker ps -a
$ docker stop (コンテナ名) #・・・(1)
$ docker rm (コンテナ名) #・・・(2)
$ docker-compose build #・・・(3)

新規登録時に名前を入力できるようにする
usersテーブルにnameカラムをstring型で追加するマイグレーションファイルを作成

terminal
$ docker-compose run web bin/rails g migration AddNameToUsers name:string $ rake db:migrate

ここでもまた、エラーが発生する場合は、再起動すると直る場合あり!

DBに名前を格納できるように変更する
deviseは初期の状態では、strong parameterが新規登録時のメールアドレスとパスワードのみ受け取るように設定されている。
しかし、deviseのstrong parameterはgem内のため、いじることができない。
なので、deviseが提供しているconfigure_permitted_parametersメソッドを利用する

configure_permitterd_parametersとは・・・

deviseのstrong parameterを追加することができるメソッド
application_controllerに記述する

controllers/application_controller.erb
  before_action :configure_permitted_parameters, if: :devise_controller?
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) # 新規登録時(sign_up時)にnameというキーのパラメーターを追加で許可する
  end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

resourcesメソッド以外のアクションを行いたい場合

【概要】

1.結論
2.collection,memberメソッドとは何か
3.どのように使うか
4.なぜcollection,memberメソッドが必要か
5.ここから学んだこと

1.結論

member,collectionメソッドを使おう!

2.collection,memberメソッドとは何か

簡単に言いますと、
member:resourcesメソッド以外のアクション(特定のデータあり)
collection:resourcesメソッド以外のアクション(特定のデータなし)

resourcesメソッドについては以下のURLを参照してください!
URL:

特定のデータとは”:id”のことを指し、
“member”はAというUserに紐づいているものしか
見れない(=特定の人が特定の情報しかみれない)アクションをしたい場合に使用できます!例えばお気に入り登録を見たい場合です。
“collection”は、全てのデータを対象とします。例えば検索機能を追加したい場合です。

3.どのように使うか

member,collectionも使い方は同じで、

routes.rb
collection do
 get *****(入れたい任意のアクション名)’

で使用できます!

もちろんmember,collectionを使用せずその他のアクションを設定す流方法があります。

memberメソッドですと

routes.rb
 get users/:id/(任意のアクション名), to users#(任意のアクション名)’

colletionメソッドですと

routes.rb
 get users/(任意のアクション名), to users#(任意のアクション名)’

になります。

ただ注意点としてはprefixが自動生成されないので
冗長な表現になりかねないです。簡単にかけるものは簡潔にプログラムしないと、保守性・拡張性・可読性が損なわれます!

4.なぜcollection,memberメソッドが必要か

結論としては、resourcesメソッド以外のアクションを行いたいからです。
つまり、member,collectionメソッドを使おう!ということです。


5.ここから学んだこと

I)7つのアクション以外に設定できるアクションがあることをしり、ユーザーがが求めるユーティリティーへの対応幅が広がりました!

ii)わざわざURLを指定してアクションを設定しないといけない手間が省け
プログラムを見やすく書きやすくできる手段を知りました!

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

CRUD,resourcesメソッドとの関係性

【概要】

1.結論
2.CRUD,resourcesメソッドとは何か
3.なぜCRUD,resourcesメソッドが必要か
4.ここから学んだこと
5.余談

1.結論


webアプリケーションに必要な4つの概念(7つのアクション)の主要機能


Create=new+create
Read=index+show
Update=edit+update
Delete=destroy

2.CRUD,resourcesメソッドとは何か

●CRUDとは、
Create:登録機能
Reading:参照機能
Update:変更機能
Delete:削除機能
の処理の頭文字を取ったものです!

●resourcesメソッドとは”CRUD"を実現するためのメソッドで、
new:新規作成
create:保存
index:一覧表示
show:詳細表示
edit:編集
update:更新
destroy:削除
のRuby on Railsの慣習的な7つのアクションが1セットになったメソッドになります!

3.なぜCRUD,resourcesメソッドが必要か

結論から申し上げますと、
webアプリケーションを作るために必須の概念とアクションなんです!

CRUDは4つの概念(規則)であり、
resourcesメソッドはCRUDを行うための7つの行動(アクション)なんです。
Amazonでも、楽天でも、Twitterでもこのアクションは必ず入っています!

むしろ入っていないと、一般的に我々が使用している
Webアプリケーション機能を果たせません!

CRUDのそれぞれの概念に対応しているアクションが
あります。

4.ここから学んだこと

i)CRUDの4つの概念をさらに細かく7つのアクションに落とし込むことで
 一つの概念をより細かいアクションで理解することができました!
ii)Webアプリケーションを作るには基本的な考え方があり、
 その仕組み作りの部分でCRUDを基本に肉付けしていくという
 フレームワークを知ることができました!

5.余談

では、Railsにその本来備わっている7つのメソッド以外に
どうやってroute.rbにアクションをつけるかということは
次回の”collection,memberメソッド”をお楽しみに!

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

Rails jsファイルの読み込みはなぜviewの一番下に記述するのか?

今までなんとなくでjsファイルの読み込みをviewの一番下に記述してたが、なぜそうするのかが学べたので備忘録投稿

scriptタグを記述する場所

scriptタグを記述する場所は以下の2つ
- </body>の直前
- <head></head>の中

どっちに記述した方がいいの?

通常は</body>の直前に記述するのがいい。
理由としてはブラウザがHTML要素を読み込むとき、上から順々に読み込んでいく。そのときにjsのコードを読み込むのはHTMLに比べて時間がかかる。
つまり上に記述される<head></head>の中にすると、jsの読み込み時間がかかってしまい肝心なHTML要素が読み込まれずに、ブラウザに何も表示されなくなる時間が発生してしまう。

つまり</body>の直前に記述すると、、、?

<body></body>の最後に記述することによって、HTML要素の解析を済ましてからjsファイルの読み込みをさせた方が、ユーザビリティが高い

例外

<body></body>が表示されると同時にjsを実行させたり、jsでcssを操作する場合などは<head></head>の中に記述する必要がある。

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

CSV出力の0落ち対応

はじめに

001などの先頭が0となっている数値をCSV出力しようとすると、0が省略され1と出力される問題の対応についてです。

対応

'="001"'

固定値の場合はこれで問題ないが、変数だと式展開されないので以下のようにする。

# ダブルクォートで囲むことに注意
%Q{="#{hoge}"}

Rubocop準拠すると、

# ダブルクォートで囲むことに注意
%(="#{hoge}")
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

部分テンプレートの実装

部分テンプレートとは

同じHTML構造の部分を共通化することによって、無駄なくビューファイルを作成することができます。この共通化された部分を、 部分テンプレートといいます。

部分テンプレートを使用した場合、そのHTML構造を他のビューでも使いまわすことができるという利点も存在します。

また、部分テンプレートのファイル名は必ずアンダーバー「_」から始まります。

部分テンプレートを使用したい場所を切り取る

例えば、以下のeach文の中身を切り取る(command+x)。

app/views/posts/index.html.erb
<% @posts.each do |post| %>
  <div class="content">
    <div class="content__left">
      <div class="content__left--image"></div>
    </div>
    <div class="content__right">
      <div class="content__right__top">
        <%= link_to post.title, post_path(post.id), class: "content__right__top--title" %>
      </div>
      <div class="content__right__bottom">
        <div class="content__right__bottom--userName">
          <%= link_to post.user.nickname, user_path(post.user), class: "content__right__bottom--userName--btn" %>
        </div>
        <div class="content__right__bottom--date">
          <%= post.created_at %>
        </div>
      </div>
    </div>
  </div>
<% end %>

部分テンプレート用のファイルを作成

app/views/postsディレクトリに、部分テンプレート用のファイル_post.html.erbを作成します。

app/views/posts/_post.html.erb
<div class="content">
  <div class="content__left">
    <div class="content__left--image"></div>
  </div>
  <div class="content__right">
    <div class="content__right__top">
      <%= link_to post.title, post_path(post.id), class: "content__right__top--title" %>
    </div>
    <div class="content__right__bottom">
      <div class="content__right__bottom--userName">
        <%= link_to post.user.nickname, user_path(post.user), class: "content__right__bottom--userName--btn" %>
      </div>
      <div class="content__right__bottom--date">
        <%= post.created_at %>
      </div>
    </div>
  </div>
</div>

部分テンプレートを呼び出す

続いて、こちらの部分テンプレートを呼び出します。そのためには、renderメソッドを利用します。

厳密にいうと、renderメソッドにpartialオプションとlocalsオプションを加えて利用する。

partialオプションとは

renderメソッドで使用できるオプションです。 partialというオプションを付けることで、明示的に部分テンプレート名を指定し、部分テンプレートを表示することができます。
下の例では、_sample.html.erbという部分テンプレートを呼び出しています。

【例】

<% render partial: "sample", locals: { post: "hello!" } %>

localsオプションとは

renderメソッドで使用できるオプションです。 localsというオプションを付けることで、部分テンプレート内でその変数を使えるようになります。

【例】

<% render partial: "sample", locals: { post: "hello!" } %>

これで部分テンプレート内においてhello!という文字列の代入されたpostという変数が使えるようになります。

実装

app/views/posts/index.html.erb
<% @posts.each do |post| %>
  <%= render partial: "post", locals: { post: post } %>
<% end %>

ここでのrenderメソッドのlocalsオプションに注目してみます。{ post: post }の右側のpostはeachメソッドのブロックパラメータのpostで、Postのインスタンスを示しています。一方、左側のpostは部分テンプレート内での変数の名前を表しています。

以上!

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

Railsでワクワク個人開発  第2回:画面遷移図とログイン実装

画面遷移図を書こう

 人の記憶は儚いもので、各所に散らされたコードを見てもなんら思い出せることがない。githubのコミット履歴には確実に残っているが、そのときの私の思いはどこにあるのだろう。個人開発の記録を少しずつ記していく。

 画面遷移図を書いた。drawioという便利なソフトがあった。vscodeの拡張機能としても利用できたので大変ありがたい。
 この記事にとても詳しく書かれている。
 https://qiita.com/riku-shiru/items/5ab7c5aecdfea323ec4e

 スクリーンショット 2020-08-11 22.58.06.png
 drawioの操作感はわりと優れている。さっさと好きな絵がかける。githubにも図形がそのまま反映されるといいな。なにか方法があるはずだ。

 とりあえず風呂敷は広げるべきだ。まだ実装できないところもとりあえず書いておく。そうすれば後々いい思い出になるはず。

ログイン機能の実装

 さっそくログイン機能を作ろう。これはdeviseというgemをつかう。Gemfilegem 'devise' を追加してコマンドラインでbundle installを行う。
あとの詳しい設定はこちらの記事にある。
https://qiita.com/salvage0707/items/d3ddc889458ac186e62e

いろいろ書いてあるが、「4, viewファイルの生成」まで行えば問題ない。 (私はモデル作成のコマンドを rails g devise user とした。)

 htmlの表示を変更しよう。app/views/layouts/application.html.erb を変更する。

<!-- 略 -->
   <body>
    <% if user_signed_in? %>
      <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
    <% else %>
      <%= link_to "ログイン", new_user_session_path %>
      <%= link_to "新規登録", new_user_registration_path %>
    <% end %>
    <%= yield %>
  </body>
<!-- 略 -->

 よく調べていないが、このapplication.html.erbというのは全てのビューファイルの根幹になるものらしい。手打ちでHTMLをやっていたころにフレームページをつくったがそれに似ている。上記の <%= yield %> に各ファイルの内容が表示されるようだ。

 <% if user_signed_in? %> という文を書くことで、ログインしているかどうかで表示を変更できるようにしている。

 link_to記法はよく使われるものなので勉強したい。

<%= link_to 'link', パス名 %>

 linkが表示される文字、パス名に行き先を設定する。パス名はコマンドラインでrails routesとやると現在設定されているパスの一覧が表示されるので、それを参考にして欲しい。

 ↓ rails guideに詳しい記述があった。

https://railsguides.jp/getting_started.html#%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%AE%E8%BF%BD%E5%8A%A0

おわり

 ちょっとずつ記憶が掘り起こされてきた感がある。これでログイン/ログアウトができるようになったので、ちょっとユーザーのサンプルデータをつくってみよう。seed.rbとかいうファイルに設定すればいい。それが終わったら今度はモデルの関連付けをする。これが曲者だった。

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

Rails Tutorialを咀嚼する【第3章 ほぼ静的なページの作成】

3.1 セットアップ

【演習】
1.BitbucketがMarkdown記法のREADME (リスト 3.3) をHTMLとして正しく描画しているか、確認してみてください。
2.本番環境 (Heroku) のルートURLにアクセスして、デプロイが成功したかどうか確かめてみてください。

⇒そのままやってみてください。

3.2 静的ページ

■コントローラ
コントローラとは (基本的に動的な) Webページの集合を束ねるコンテナのこと。
→ちょっと意味が分からない。

■rails generate controller StaticPages home help
コントローラーにstatic_pages_controller.rbが生成される。
routes.rbに
・static_pages/home
・static_pages/help
が生成される。

この時点でアドレスバーに「static_pages/home」と入力すれば移動する。
異動する先はビューの「home.html.erb」。
※helpも同様。

■HTTPメソッド
GET、POST、PATCH、DELETEの4つがある。
GET:ページを呼び出す
POST:ユーザーが何かを入力して送信するときに使う。
PATCH:おそらく更新に使う。
DELETE:削除に使う

【演習】
1.Fooというコントローラを生成し、その中にbarとbazアクションを追加してみてください。
→コントローラーを生成するのでrails generateを使います。
rails generate controller Foo bar baz

2.コラム 3.1で紹介したテクニックを駆使して、Fooコントローラとそれに関連するアクションを削除してみてください。
コラムを参照
→rails destroy controller Foo bar baz

3.3 テストから始める

■テストケース、テストスイート
1つのテストのことをテストケースと呼ぶ。
テストケースが集まったものをテストスイートと呼ぶ。

■テスト駆動設計
テストコードを書いてから開発を進める手法

■static_pages_controller_test.rb
rails gと同時に生成されている。

test/controllers/static_pages_controller_test.rb
  test "should get home" do
    get static_pages_home_url
    assert_response :success
  end

このファイルは既にActionDispatch::IntegrationTestを継承しているので、
そういうものなのだと理解する。
「should get home」というテストを新しく生成。
「get static_pages_home_url」でアクセス。
「assert_response :success」で成功か否か判断。

■touch app/views/static_pages/about.html.erb
touch app/views/static_pagesのディレクトリに
about.html.erbのファイルを生成する。

右クリックからの「ファイルを作成」でもいける。

■about.html.erb

とかはいらない。

3.4 少しだけ動的なページ

→リファクタリングを行っているページなので、最悪後回しでも大丈夫。
■mv app/views/layouts/application.html.erb layout_file
application.html.erb を layout_fileに移動する。

■assert_select "title", "Home | Ruby on Rails Tutorial Sample App"
移動した先のページのタイトルタグの中身が「"Home | Ruby on Rails Tutorial Sample App"」かどうか確認する。

【演習】
1.StaticPagesコントローラのテスト (リスト 3.24) には、いくつか繰り返しがあったことにお気づきでしょうか? 特に「Ruby on Rails Tutorial Sample App」という基本タイトルは、各テストで毎回同じ内容を書いてしまっています。そこで、setupという特別なメソッド (各テストが実行される直前で実行されるメソッド) を使って、この問題を解決したいと思います。まずは、リスト 3.30のテストが green になることを確認してみてください (リスト 3.30では、2.2.2で少し触れたインスタンス変数や文字列の式展開というテクニックを使っています。それぞれ4.4.5と4.2.2で詳しく解説するので、今はわからなくても問題ありません)。
→「Ruby on Rails Tutorial Sample App」という文字ががたくさん出てきて面倒だよね?という話です。

@base_titleにRuby on Rails Tutorial Sample Appという文字列を代入し、
それぞれで展開をしている。

■Provideメソッド
provideメソッドでパラメータを引き渡し、yieldメソッドで受け取る。
タイトルを統一させることで、

タグの中身以外が同じになるようにしている。

■app/views/layouts/application.html.erb
デザインの根幹をなしているもの。

【演習】
1.サンプルアプリケーションにContact (問い合わせ先) ページを作成してください17 (ヒント: まずはリスト 3.15を参考にして、/static_pages/contactというURLのページに「Contact | Ruby on Rails Tutorial Sample App」というタイトルが存在するかどうかを確認するテストを最初に作成しましょう。次に、3.3.3でAboutページを作ったときのと同じように、Contactページにもリスト 3.40のコンテンツを表示してみましょう。)。

1.static_pages/にcontact.html.erbというファイルを作る。

routes.rb
<% provide(:title, "Contact") %>
<h1>Contact</h1>
<p>
  Contact the Ruby on Rails Tutorial about the sample app at the
  <a href="https://railstutorial.jp/contact">contact page</a>.
</p>

2.テストを作る。名前をcontactに変えるだけ

static_pages_controller_test.rb
test "should get contact" do
    get static_pages_contact_url
    assert_response :success
    assert_select "title", "contact | #{@base_title}"
  end

3.routesを設定する

routes.rb
get  'static_pages/contact'

4.コントローラーにパスを通す。

static_pages_controller.rb
def contact
end

【演習】
1.リスト 3.41にrootルーティングを追加したことで、root_urlというRailsヘルパーが使えるようになりました (以前、static_pages_home_urlが使えるようになったときと同じです)。リスト 3.42のFILL_INと記された部分を置き換えて、rootルーティングのテストを書いてみてください。

rootはどこのディレクトリにも属していないのでstatc_pagesは不要

static_pages_controller_test.rb
test "should get root" do
    get root_url
    assert_response :success
  end

3.5 最後に

3.6 高度なセットアップ

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