20200430のRailsに関する記事は28件です。

【�database.yml】DBをDockerとrails server両方で使えるように�設定

Dokerで開発時に、docker-compose rundocker-compose run よりも早いrails serverで一時的に動作確認をしたい場合があるかと思う。
そういった場合にも、以下のconfig/database.yml内の記述だけで対応することができる。

検証環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.3
BuildVersion:   19D76
$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin19]
$ rails -v
Rails 5.2.4.2

database.ymlについて

まず、database.ymlとは

config/database.yml(例)
default: &default
  adapter: mysql2
  encoding: utf8
  collation: utf8_general_ci
  pool: 5
  host: <%= ENV['MYSQL_HOST'] || 'localhost' %>
  username: <%= ENV['MYSQL_USERNAME'] || 'root' %>
  password: <%= ENV['MYSQL_PASSWORD'] || '' %>
  socket: /tmp/mysql.sock

主な内容

adapter: 使用するデータベースの種類(postgresql, mysql2等)

encoding: 文字コード

collation: MySQLの文字列と照合順序(ソート順)、”文字コード言語名比較法”で構成される

pool: 確保する接続プールの数

host: データベースが動作しているホスト名またはIPアドレス

username,password: データベースに接続するユーザー名・パスワード

socket: DB通信の接続口

比較演算子: ||

orと同じ働きをする。
Ruby 2.7.0 リファレンスマニュアル 演算子式

文法:

式 `||' 式
式 or 式
左辺を評価し、結果が真であった場合にはその値を返します。左辺の評価結果が偽であった場合には右辺を評価しその評価結果を返します。

config/database.ymlのhost,username,passwordの部分をこれで書くことで、ENV['MYSQL_HOST']等の環境変数がない場合に、localhost等を返してくれる。

終わりに。

最後まで読んで頂きありがとうございます:bow_tone1:
転職の為、未経験の状態からRailsを学習しております。正しい知識を着実に身に着け、実力のあるエンジニアになりたいと考えています。継続して投稿していく中で、その為のインプットも必然的に増え、成長に繋がるかと考えています。
今現在、初心者だからといって言い訳はできないですが、投稿の内容に間違っているところや、付け加えるべきところが多々あるかと思いますので、ご指摘頂けると幸いです。この記事を読んで下さりありがとうございました。

参考にさせて頂いた記事

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

テストをまともにやってこなかったから、rspec-railsを使ってモデルの単体テストを初めてまともにやってみた話。

超簡単なモデルの単体テストをやってみる。

前回せっかくミニアプリまで作ったので、今までまともにやってこなかったモデルの単体テストもやってしまおう!

と、今回は、超簡単な単体テストを実施しました。
テスト環境の準備が色々あったので備忘録として記載します。

動作環境

ruby 2.5.1
rails 5.2.4.2

下準備

modelとかmigration等、ここまでの環境は前回記事の下準備をご覧ください。

テスト環境の準備

gemをインストール

.Gemfile
 (以下を追記)
  gem 'rspec-rails'
  gem 'factory_bot_rails'
terminal.
$ bundle install

respecをインストール

terminal.
$ rails g rspec:install

.rspecへの追記

.rspec
(以下を追記)
--format documentation

これ、なんの意味があるのかと思ったら、書かないとターミナルにテスト結果がdocument形式で表示されません。

spec/rails_helper.rbへの追記

spec/rails_helper.rb
RSpec.configure do |config|
  (以下を追記)
  config.include FactoryBot::Syntax::Methods #Factory_botのメソッドを使用するため
end

rspecファイルを作成する

terminal.
$ bin/rails g rspec:model item

単体テスト実装

それでは単体テストのコードを書いていきます。

とりあえずテスト用インスタンスをつくってみた。

まずは半端な知識でテスト用のインスタンスを作ります。

spec/factoreis/item.rb
FactoryBot.define do
  factory :item do
    #name に "test" とだけ入れます。
    name    {"test"}
  end
end

とりあえずテストコードも書いてみた。

次に半端な知識でテストコードも書いていきます。

spec/models/item_spec.rb
require 'rails_helper'

RSpec.describe Item, type: :model do
  describe '#create' do
    let(:item) {build(:item)}
    context 'can save' do
      it "is valid with a name" do
        expect(item).to be_valid   #name に "test" が入っていれば成功する(はず)
      end
    end
    context 'can not save' do
      it "is valid without a name" do
        item.name = ""              #name が 空の場合
        expect(item).to be_invalid  #失敗する(はず)
      end
    end
  end
end

テストコード走らせてみた。

インスタンスも作った。テストコードも書いた。
次にやることと言ったら、もう決まってる。
いざ。

terminal.
$ bundle exec rspec spec/models/item_spec.rb
terminal.
Item
  #create
    can save
      is valid with a title
    can not save
      is valid without a title (FAILED - 1)

Failures:

  1) Item#create can not save is valid without a title
     Failure/Error: expect(item).to be_invalid
       expected `#<Item id: nil, title: "", created_at: nil, updated_at: nil>.invalid?` to return true, got false
     # ./spec/models/item_spec.rb:14:in `block (4 levels) in <top (required)>'

Finished in 0.34277 seconds (files took 5.22 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/models/item_spec.rb:12 # Item#create can not save is valid without a title

あれ? エラー?
あ、validation書いてないですねこれ。

validationを追加してみた。

null: falseだけ追加します。

app/models/item.rb
class Item < ApplicationRecord
  (中略)
  validates :name,presence: true #null: false
end

結果

terminal.
$ bundle exec rspec spec/models/item_spec.rb
terminal.
Item
  #create
    can save
      is valid with a title
    can not save
      is valid without a title

Finished in 0.33208 seconds (files took 6.29 seconds to load)
2 examples, 0 failures

上手(?)にできました!

教訓

validationを忘れない!

今回は以上です。

参考にさせていただいた記事

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

超基礎 Rails DBの作成

データベースを作成

$ rails db:create

以下のような表示がされれば成功

Created database 'ファイル名_development'
Created database 'ファイル名_test'

モデルの作成

$ rails g model モデル名

マイグレーションファイルが生成されるので必要な型、カラムや制約を追加

マイグレーションファイルの実行

$ rails db:migrate

マイグレーションファイルの状況を確認

$ rails db:migrate:status

修正する際にはマイグレーションファイルを差し戻す

$ rails db:rollback

マイグレーションファイルに追記

$ rails g migration Addカラム名To 追加先テーブル名 追加するカラム名:型

# マイグレーションファイルの実行
$ rails db:migrate
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]カラムのreference型について

reference型とは

外部キーになるカラムを生成する時にこの型にすることが多い。

使い方

20××××××××××××.rb
class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string    :name
      t.references :category, foreign_key: true
    end
  end
end

この場合category_idカラムが生成されます。
reference型は、外部キー制約をつけるときに「foreign_key: true」を使うことで制約が適用される。
※ちなみに、インデックスを自動で張ってくれるため自分で設定する必要はありません。

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

Railsのform_withを使った時にページが更新されない時

form_withとは

Railsアプリケーションでformを作成する時にform_for/form_tagを使っていました。

任意のmodelに紐づくフォームを作成したい場合にはform_forを使い、modelに紐づかない場合にはform_withを使います。

form_forを使えばPOSTの送信先urlなどを全て自動で行いますが、form_forの場合は全て明示します。

HTMLタグのヘルパーのようなイメージで使います。

【Rails】form_for/form_tagの違い・使い分けをまとめた

しかし、Rails5.1以降は2つのメソッドを統合したform_withが登場し、form_withの利用が推奨されています。

form_withでページが更新されない

form_withを使ってユーザのログインフォームを作っていました。

form_withにはUserModelを紐づけており、バリデーションやログイン認証の結果にエラーがあれば、viewに反映せるようにしていました。

views/users/_form.html.erb
<%= form_with model: @user, url: user_path do |f| %>

    <%= render 'shared/error_messages',  object: f.object %>

    <%= f.label :name %>
    <%= f.text_field :user_name, class: "form-control" %>

    <%= f.label :email %>
    <%= f.email_field :email, class: "form-control" %>

    <%= f.label :password %>
    <%= f.password_field :password, class: "form-control" %>

    <%= f.label :password_confirmation, "Confirmation" %>
    <%= f.password_field :password_confirmation, class: "form-control" %>

    <%= f.submit yield(:btn_text), class: "btn btn-primary" %>
<% end %>

ところが、エラーは発生しているのにviewには反映されない問題に衝突しました。

これは、form_withでのパラメータの送信はajaxで行われているためです。

HTMLのフォームとしてPOSTしたい場合はlocal: trueオプションを付け加えます。

views/users/_form.html.erb
<%= form_with model: @user, url: user_path, local: true do |f| %>
  :
<% end %>

これでバリデーションなどのエラー結果を表示するviewを表示できます。

都度フォームにオプションをつけるのが面倒な場合は、config/initializeディレクトリに適当なファイルを作成し以下のコードを追記します。

config/initialize/some_file.rb
Rails.application.configure do
    config.action_view.form_with_generates_remote_forms = false
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】住所を入力すると自動的に地図表示される方法(Google Maps API)

はじめに

ポートフォリオ制作で、Google Map APIを用いて住所フォームを送信した際に住所名と地図を自動的に地図表示される設定を行ったので、アウトプットも兼ねて手順を紹介していきます。

手順

1.Google MapのAPI Keyを取得
2.住所(address)、緯度(latitude)、経度(longitude)カラムを追加する
3.住所を登録するフォームを作成する
4.gem geocoderを追加する
5.viewにGoogle Mapを表示させる記述を追加する
6.詳しい住所を表示させる
7.GitHubにPushされないように設定する
8.APIキーの書き換え
(その他)AWSでデプロイしている場合

1.Google MapのAPI Keyを取得

APIの取得はこちらの記事がわかりやすいので参考にしてみてください。

https://qiita.com/tiara/items/4a1c98418917a0e74cbb

2.住所、緯度、経度カラムを追加する

住所(address)、緯度(latitude)、経度(longitude)カラムを追加しましょう。

class ChangeDatatypeLanguageOfLabs < ActiveRecord::Migration[5.2]

  def change
        change_column :labs, :address, :string
        change_column :labs, :latitude, :float
        change_column :labs, :longitude, :float
  end
end

labsはモデル名なので人によって変わります。

latitudeとlongitudeはfloat型にします。

floate型については下記の記事を参考にしてみてください。
https://wa3.i-3-i.info/word14968.html

カラムを追加したら$ rails:db:migrateしましょう。

3.住所を登録するフォームを作成する

<%= form_for(@lab) do |f| %>
・・・
<%= f.label :住所 %>
<%= f.text_area :address, autofocus: true %>
・・・
<%= f.submit '投稿' %>
<% end %>

これで住所を登録するフォームが投稿できます。

4.gem geocoderを追加する

地図表示する際に、Google Mapでは緯度・経度から位置を取得します。

なので、緯度・経度の登録を行う為に今回はgem geocoderを導入します。
geocoderによって住所の情報を元に緯度、経度を割り出してくれます。

Gemfile.
gem 'geocoder'

記述後、ターミナル上で$ bundle installを実行します。

lab.rb
  geocoded_by :address(←住所のカラム名)
  after_validation :geocode, if: :address_changed?

これで、モデル登録時と住所(address)変更時にgeocoderが動いて緯度・経度のデータが登録・更新されます

5.viewにGoogle Mapを表示させる記述を追加する

labs/show.html.rb
・・・
<p>住所</p>
<p><%= @lab.address %></p>(住所名表示)

<div id="map"></div>(地図を表示)
・・・

<style>(地図の大きさ指定)
#map{
  height: 150px;
  width:270px;
}
</style>

<script type="text/javascript">
    function initMap() {

        var test ={lat: <%= @lab.latitude %>, lng: <%= @lab.longitude %>};
        var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 15,
            center: test
        });
        var transitLayer = new google.maps.TransitLayer();
        transitLayer.setMap(map);

        var contentString = '住所:<%= @lab.address %>';
        var infowindow = new google.maps.InfoWindow({
            content: contentString
        });

        var marker = new google.maps.Marker({
            position:test,
            map: map,
            title: contentString
        });

        marker.addListener('click', function() {
            infowindow.open(map, marker);
        });
    }
</script>

<script async defer
        src="https://maps.googleapis.com/maps/api/js?v=3.exp&key=取得したAPIキー&callback=initMap">
</script>

map-google.png

これで登録した住所を元に地図表示ができるようになりました。
しかし、この状態では住所名によって地図が表示されない場合があります。

それはデフォルトのgeocoderのままでは詳しい住所の経度、緯度を持ってくることができないからです。

なので、詳しい住所でも表示されるように設定していきます。

6.詳しい住所を表示させる

ターミナル上で$ bin/rails g geocoder:configコマンドを入力。
そうすると、config/initializers/geocoder.rbファイルが作成されます。

作成されたファイルを開き、中身を変更させましょう。

geocoder.rb
Geocoder.configure(
  # Geocoding options
  # timeout: 3,                 # geocoding service timeout (secs)
   lookup: :google,         # name of geocoding service (symbol)
  # ip_lookup: :ipinfo_io,      # name of IP address geocoding service (symbol)
  # language: :en,              # ISO-639 language code
   use_https: true,           # use HTTPS for lookup requests? (if supported)
  # http_proxy: nil,            # HTTP proxy server (user:pass@host:port)
  # https_proxy: nil,           # HTTPS proxy server (user:pass@host:port)
   api_key: ENV['GOOGLE_MAP_API_KEY'],               # API key for geocoding service
  # cache: nil,                 # cache object (must respond to #[], #[]=, and #del)
  # cache_prefix: 'geocoder:',  # prefix (string) to use for all cache keys

  # Exceptions that should not be rescued by default
  # (if you want to implement custom error handling);
  # supports SocketError and Timeout::Error
  # always_raise: [],

  # Calculation options
  # units: :mi,                 # :km for kilometers or :mi for miles
  # distances: :linear          # :spherical or :linear
)

これで、Google mapのAPIを使って緯度、経度を検索できるようになりました。

7.GitHubにPushされないように設定する

この状態でPushしてしまうと取得したAPIキーもGitHub上に上がってしまいます。
なので、Pushしても表示されないように設定しましょう。

gemのdotev-railsを用いて設定していきます。

Gemfile.
gem 'dotenv-rails'

ターミナル上で$ bundle installを実行します。

app等と同じステージに.envファイルを作成しましょう。

change.png

.envファイルにAPIキーを記述する。

env.
GOOGLE_MAP_API_KEY=取得したAPIキー

.envファイルの下にある
.gitignoreファイルの最後の行に.envと記述しましょう。
(ちなみにignoreとは無視するという意味です。)

gitignore.
・・・
・・・
/.env

これでPushしても.envファイルは無視されます。

8.APIキーの書き換え

今までAPIキーを直接書き込んでいた全てのファイルでAPIキーの記述を.envファイル内で定義したGOOGLE_MAP_API_KEYに書き換えます。

labs/show.html.rb
<script async defer
        src="https://maps.googleapis.com/maps/api/js?v=3.exp&key=<%= ENV['GOOGLE_MAP_API_KEY'] %>&callback=initMap">
</script>
geocoder.rb
 api_key: ENV['GOOGLE_MAP_API_KEY'],  

これでGitHub上にAPIキーが上がることなく地図が表示されるようになります。

(その他)AWSでデプロイしている場合

AWSでデプロイしている場合、本番環境に反映させる為には
EC2にログイン後、Git pullをして変更内容を取り込みます。

その後、$ sudo vi .envコマンドで.envファイルを開き、

GOOGLE_MAP_API_KEY=取得したAPIキー

を記述するとデプロイ先でも反映されるようになります。

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

【Rails】住所を入力すると自動で地図表示される方法(Google Maps API)

はじめに

ポートフォリオ制作で、Google Maps APIを用いて住所フォームを送信した際に住所名と地図を自動で地図表示される設定を行ったので、アウトプットも兼ねて手順を紹介していきます。

手順

1.Google MapのAPI Keyを取得
2.住所(address)、緯度(latitude)、経度(longitude)カラムを追加する
3.住所を登録するフォームを作成する
4.gem geocoderを追加する
5.viewにGoogle Mapを表示させる記述を追加する
6.詳しい住所を表示させる
7.GitHubにPushされないように設定する
8.APIキーの書き換え
(その他)AWSでデプロイしている場合

1.Google MapのAPI Keyを取得

APIの取得はこちらの記事がわかりやすいので参考にしてみてください。

https://qiita.com/tiara/items/4a1c98418917a0e74cbb

2.住所、緯度、経度カラムを追加する

住所(address)、緯度(latitude)、経度(longitude)カラムを追加しましょう。

class ChangeDatatypeLanguageOfLabs < ActiveRecord::Migration[5.2]

  def change
        change_column :labs, :address, :string
        change_column :labs, :latitude, :float
        change_column :labs, :longitude, :float
  end
end

labsはモデル名なので人によって変わります。

latitudeとlongitudeはfloat型にします。

float型については下記の記事を参考にしてみてください。
https://wa3.i-3-i.info/word14968.html

カラムを追加したら$ rails:db:migrateを実行します。

3.住所を登録するフォームを作成する

<%= form_for(@lab) do |f| %>
・・・
<%= f.label :住所 %>
<%= f.text_area :address, autofocus: true %>
・・・
<%= f.submit '投稿' %>
<% end %>

これで住所を登録するフォームが投稿できます。

4.gem geocoderを追加する

地図表示する際に、Google Mapでは緯度・経度から位置を取得します。

なので、緯度・経度の登録を行う為に今回はgem geocoderを導入します。
geocoderによって住所の情報を元に緯度、経度を割り出してくれます。

Gemfile.
gem 'geocoder'

記述後、ターミナル上で$ bundle installを実行します。

lab.rb
  geocoded_by :address(←住所のカラム名)
  after_validation :geocode, if: :address_changed?

これで、モデル登録時と住所(address)変更時にgeocoderが動いて緯度・経度のデータが登録・更新されます

5.viewにGoogle Mapを表示させる記述を追加する

labs/show.html.rb
・・・
<p>住所</p>
<p><%= @lab.address %></p>(住所名表示)

<div id="map"></div>(地図を表示)
・・・

<style>(地図の大きさ指定)
#map{
  height: 150px;
  width:270px;
}
</style>

<script type="text/javascript">
    function initMap() {

        var test ={lat: <%= @lab.latitude %>, lng: <%= @lab.longitude %>};
        var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 15,
            center: test
        });
        var transitLayer = new google.maps.TransitLayer();
        transitLayer.setMap(map);

        var contentString = '住所:<%= @lab.address %>';
        var infowindow = new google.maps.InfoWindow({
            content: contentString
        });

        var marker = new google.maps.Marker({
            position:test,
            map: map,
            title: contentString
        });

        marker.addListener('click', function() {
            infowindow.open(map, marker);
        });
    }
</script>

<script async defer
        src="https://maps.googleapis.com/maps/api/js?v=3.exp&key=取得したAPIキー&callback=initMap">
</script>

map-google.png

これで登録した住所を元に地図表示ができるようになりました。
しかし、この状態では住所名によって地図が表示されない場合があります。

それはデフォルトのgeocoderのままでは詳しい住所の経度、緯度を持ってくることができないからです。

なので、詳しい住所でも表示されるように設定していきます。

6.詳しい住所を表示させる

ターミナル上で$ bin/rails g geocoder:configコマンドを入力。
そうすると、config/initializers/geocoder.rbファイルが作成されます。

作成されたファイルを開き、中身を変更させましょう。

geocoder.rb
Geocoder.configure(
  # Geocoding options
  # timeout: 3,                 # geocoding service timeout (secs)
   lookup: :google,         # name of geocoding service (symbol)
  # ip_lookup: :ipinfo_io,      # name of IP address geocoding service (symbol)
  # language: :en,              # ISO-639 language code
   use_https: true,           # use HTTPS for lookup requests? (if supported)
  # http_proxy: nil,            # HTTP proxy server (user:pass@host:port)
  # https_proxy: nil,           # HTTPS proxy server (user:pass@host:port)
   api_key: ENV['GOOGLE_MAP_API_KEY'],               # API key for geocoding service
  # cache: nil,                 # cache object (must respond to #[], #[]=, and #del)
  # cache_prefix: 'geocoder:',  # prefix (string) to use for all cache keys

  # Exceptions that should not be rescued by default
  # (if you want to implement custom error handling);
  # supports SocketError and Timeout::Error
  # always_raise: [],

  # Calculation options
  # units: :mi,                 # :km for kilometers or :mi for miles
  # distances: :linear          # :spherical or :linear
)

これで、Google mapのAPIを使って緯度、経度を検索できるようになりました。

7.GitHubにPushされないように設定する

この状態でPushしてしまうと取得したAPIキーもGitHub上に上がってしまいます。
なので、Pushしても表示されないように設定しましょう。

gemのdotev-railsを用いて設定していきます。

Gemfile.
gem 'dotenv-rails'

ターミナル上で$ bundle installを実行します。

app等と同じステージに.envファイルを作成しましょう。

change.png

.envファイルにAPIキーを記述する。

env.
GOOGLE_MAP_API_KEY=取得したAPIキー

.envファイルの下にある
.gitignoreファイルの最後の行に.envと記述しましょう。
(ちなみにignoreとは無視するという意味です。)

gitignore.
・・・
・・・
/.env

これでPushしても.envファイルは無視されます。

8.APIキーの書き換え

今までAPIキーを直接書き込んでいた全てのファイルでAPIキーの記述を.envファイル内で定義したGOOGLE_MAP_API_KEYに書き換えます。

labs/show.html.rb
<script async defer
        src="https://maps.googleapis.com/maps/api/js?v=3.exp&key=<%= ENV['GOOGLE_MAP_API_KEY'] %>&callback=initMap">
</script>
geocoder.rb
 api_key: ENV['GOOGLE_MAP_API_KEY'],  

これでGitHub上にAPIキーが上がることなく地図が表示されるようになります。

(その他)AWSでデプロイしている場合

AWSでデプロイしている場合、本番環境に反映させる為には
EC2にログイン後、Git pullをして変更内容を取り込みます。

その後、$ sudo vi .envコマンドで.envファイルを開き、

GOOGLE_MAP_API_KEY=取得したAPIキー

を記述するとデプロイ先でも反映されるようになります。

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

seeds.rbの使い方

seeds.rbとは

初期データを生成してくれるファイルのこと。
このファイルにデータを生成するコードを書いておくだけで、アプリにデータを備えさせることができます。
簡単にテストデータを作ったりできます。

使い方

1.自分が用意したいデータをファイル内でcreateする。

db/seed.rb
#通常の場合
User.create(name: "tanaka")
User.create(name: "sato")

#配列の場合
users = User.create([{name: "tanaka"}, {name: "sato"}])

#大量のテストデータの場合
100.times do |n|
  User.create(title: "test{n}人目", content:"test!#{n}回目")
end

2.seedファイルを実行する

$ rails db:seed

おまけ

実際に存在しそうなデータを生成してくるgem(Faker)があるので一応載せておきます。

1.Gemfileに以下を追記

gem 'faker'

こちらも忘れず実行してください。

$ bundle install

2.seeds.rbを以下のように記述する。

db/seed.rb
100.times do |n|
  name = Faker::Name.name
  email = Faker::Internet.email
  content = "test"

  User.create(
    name: name,
    email: email,
    content: content
  )
end

3.seedファイルを実行する。

$ rails db:seed

※Fakerの使い方一覧は以下の表参照。

種類 役割
Faker::Name.name 名前
Faker::Internet.email メールアドレス
Faker::Address.city 都市の名前
Faker::Food.ingredient 食べ物の名前

参考

https://diveintocode.jp/blogs/Technology/SeedData

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

商品情報と別のテーブルに保存している画像を一緒に表示させるためには

現在プログランミングスクールでチーム開発にてフリマアプリを作成中です。

やりたいこと

  • トップページの商品一覧でitemテーブルのアソシエーション先であるimageテーブルから複数ある画像の一つだけを表示させたい。
  • 表示させたいのは出品中の商品のみ。

解決までの思考

とりあえず一覧表示するため商品全部の情報を持ってきてみる

items_controller.rb
  def index
    @items = Item.all
  end

でもこれだと画像がない

items_controller.rb
  def index
    @items = Item.includes([:images]).order(created_at: :desc)
  end

モデルにアソシエーションがあれば.includesで取得可能!

item.rb
class Item < ApplicationRecord
  belongs_to :brand
  belongs_to :category
  has_many :images

念のためアソシエーション確認
これで商品情報と画像を持ってこれた。

でもそも欲しい情報は出品中の商品のみなので、このままだと販売済みなどの必要ない商品まであるよね?

じゃあモデルで定義しちゃおう!

item.rb
class Item < ApplicationRecord
  belongs_to :brand
  belongs_to :category
  has_many :images

  enum status: { sell: 0, buy: 1 , trading:2}

  scope :on_sell, -> { where(status: 0) }
end

まずenumで出品中、購入済み、取引中を定義しておく。
これによってstatusカラムに数字で保存されている。

さらにscopeメソッドを使ってメソッドを定義する。
where句を使ってstatusが0(出品中)のレコードだけをon_sellに代入できた。
(コントローラーにも記述できるがこの方が可読性がいいのでモデル推奨)

items_controller.rb
  def index
    @items = Item.on_sell.includes([:images]).order(created_at: :desc)
  end

あとはコントローラーに記述してあげれば
出品中の商品とそれに紐づいた画像を持ってこれた。ついでに.orderで最新順に表示できるようソートしておく。

あとはビューに表示させるだけ!

  .top-main__product__list__box
   - @items.each do |item|
    = link_to item_path(id: item.id) ,class:"top-main__product__list__box__item" do
     - item.images.first(1).each do |image| 
      = image_tag image.url,class:"top-main__product__list__box__item__img"    
     .top-main__product__list__box__item__body
      %h3.top-main__product__list__box__item__body__name 
       = item.name
      .top-main__product__list__box__item__body__details
       %ul
        %li 
         = item.price
         = "円"
       %p (税込)

itemをeachで順番に表示させたはいいもののそのままだと紐づいた画像を全て表示してしまう。

     - item.images.first(1).each do |image| 

eachは回数を指定できる、、、
じゃあ一回だけ回せば一枚だけ表示できるやん!とひらめき実装完了
(ただこの方法はあまり美しくない気が、、、)

今回学べたこと

  • 関連するテーブルからの取得方法
  • アソシエーションの必要性
  • スコープを使ってモデルに定義しコントローラーに記述することで可読性アップ

初めはどこに何を定義し、どう記述するのか見当もつきませんでしたが必要なポイントを箇条書きにすることで少しずつ近づけました。
ビューの画像表示の方法はもう少しいい表示方法がありそう?なので今後の課題として!

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

railsアプリで別のウィンドウでログアウトした時エラーにならないかRSpecのsystem specでテスト

railsでログイン機能を作った際、ログアウトしてる状態で別タブでログアウトした時にエラーにならないかsystem specでテスト

session_spec.rb
let(:user) { FactoryBot.build(:user) }
# 省略
  it "別タブでログアウトをクリックした時、エラーにならない" do

    user.save
    test_log_in

    # 新しいタブを開く
    within_window open_new_window do
      test_log_in
      click_link "ログアウト"
    end

    # タブを最初のものに戻す
    switch_to_window windows[0]
    click_link "ログアウト"
    expect(current_path).to eq root_path
  end
login_support.rb
# spec/support/login_support.rb
def test_log_in
    visit login_path
    fill_in "User_id", with: user.acount_id
    fill_in "Password", with: user.password
    click_button "Login"
  end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails routesで覚えのないroutingが出力される。

問題のルーティング

こんなの設定してない、、、

$ rails routes
       rails_mandrill_inbound_emails POST   /rails/action_mailbox/mandrill/inbound_emails(.:format)                                  action_mailbox/ingresses/mandrill/inbound_emails#create
        rails_postmark_inbound_emails POST   /rails/action_mailbox/postmark/inbound_emails(.:format)                                  action_mailbox/ingresses/postmark/inbound_emails#create
           rails_relay_inbound_emails POST   /rails/action_mailbox/relay/inbound_emails(.:format)                                     action_mailbox/ingresses/relay/inbound_emails#create
        rails_sendgrid_inbound_emails POST   /rails/action_mailbox/sendgrid/inbound_emails(.:format)                                  action_mailbox/ingresses/sendgrid/inbound_emails#create
         rails_mailgun_inbound_emails POST   /rails/action_mailbox/mailgun/inbound_emails/mime(.:format)                              action_mailbox/ingresses/mailgun/inbound_emails#create
       rails_conductor_inbound_emails GET    /rails/conductor/action_mailbox/inbound_emails(.:format)                                 rails/conductor/action_mailbox/inbound_emails#index
                                      POST   /rails/conductor/action_mailbox/inbound_emails(.:format)                                 rails/conductor/action_mailbox/inbound_emails#create
    new_rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/new(.:format)                             rails/conductor/action_mailbox/inbound_emails#new
   edit_rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/:id/edit(.:format)                        rails/conductor/action_mailbox/inbound_emails#edit
        rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#show
                                      PATCH  /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#update
                                      PUT    /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#update
                                      DELETE /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#destroy
rails_conductor_inbound_email_reroute POST   /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format)                      rails/conductor/action_mailbox/reroutes#create
                   rails_service_blob GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
            rails_blob_representation GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
                   rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
            update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)                                      active_storage/disk#update
                 rails_direct_uploads POST   /rails/active_storage/direct_uploads(.:format)                                           active_storage/direct_uploads#create

解決方法

$ rails new プロジェクトの名前 --skip-active-storage --skip-action-mailer --skip-action-mailbox

rails newでプロジェクトを立ち上げる際にオプションを付け加える事で解決。
既にrails newした後はapplication.rbファイルにコードを記述する事で表示されなくなりました。

Application.rb

class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0

    # CODE YOU SHOULD ADD vvvvvv
    # ここから
     initializer(:remove_action_mailbox_and_activestorage_routes, after: :add_routing_paths) { |app|
     app.routes_reloader.paths.delete_if {|path| path =~ /activestorage/}
     app.routes_reloader.paths.delete_if {|path| path =~ /actionmailbox/ }
    } ←# ここまで追加
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
  end
end

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

Rubyとは

Ruby

特徴

・記述量が少ない
・JavaやPHPといった他の言語同様、オブジェクト指向プログラミング言語である。
・スクリプト言語であるため、コンパイルする必要がない
・日本で生まれたプログラミング言語である。

記述量が少ない

他の言語であれば6行〜10行必要な場合でも、Rubyは1行で済む場合がある。
記述量が少ないということは作業の短縮になり、開発者にとって非常に助かると言う利点がある。

オブジェクト指向とは

プログラムの動作を属性値とメソッドを持ったパーツの組み合わせで実現すると言う考え方である。

スクリプト言語とは

プログラミング言語のうち、プログラムの記述や実行を比較的簡易に行うことができる言語の総称。インタプリンタ型(ソースコードを即座に実行開始できる)型のため、コンパイラ(一括してから実行する方式)に比べ、開発や修正をテンポよく進めることができる。

デメリットして

処理速度が他の言語に比べて遅いため、大規模アプリや処理速度が重要なサービスには向いていない。

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

Rails 初めてのAPIモード

概要

こんにちは。
今回は始めてRailsでAPIを作成してみたのでその備忘録を残したいと思います。

以下を使いました。

  • ツール

    • Postman(レスポンスを確認するためのツール)
  • gem

    • active_model_serializers

今回はUserを管理できるAPIを作ります。

事前にこちらの記事を読んで作成しております。
https://qiita.com/Kaki_Shoichi/items/d4adcf0298ed0b4614a2
https://qiita.com/c5meru/items/1c921676de8a5a038f70
https://qiita.com/yyh-gl/items/30bd91c2b33fdfbe49b5

仕様

  • jobテーブルとuserテーブルは1対多の関係にある。

  • jobとuserを登録できる。

    • userはjob_idを外部キーに持つ
    • job_nameとusernameというリクエストを送る
    • すでにjob_nameが存在しているときはそのIDを外部キーに、job_nameがない場合は新しくjobを作成しそのidを外部キーとする。
  • user一覧を取得できる。

    • リクエストにvalueを含めない場合は全てのuserを表示させる。
    • リクエストにjob_nameを指定した場合は該当するuserのみを表示させる。

以上の仕様で作成したいと思います。

それでは早速始めていきます。

導入

まずはapiモードでRailsを作成してください。

$ rails new testapi --api

以下のgemをインストールします。

gem 'active_model_serializers'

テーブル作成

以下のようにテーブルとカラムを作成します。

db/schema.rb
  create_table "jobs", force: :cascade do |t|
    t.string "name", null: false
    t.index ["name"], name: "index_jobs_on_name", unique: true
  end

  create_table "users", force: :cascade do |t|
    t.text "username", null: false
    t.integer "job_id", null: false
    t.index ["job_id"], name: "index_users_on_job_id"
  end

モデル

モデルのバリデーションは次のようにしました。

job.rb
class Job < ApplicationRecord
  has_many :users, dependent: :destroy
  validates :name, uniqueness: true, presence: true
end

user.rb
class User < ApplicationRecord
  belongs_to :job
  validates :username, presence: true
  validates :job_id, presence: true
end

ルーティング

api作成時はバージョン管理しやすい設計が推奨されているようです。
また今回はusers_contorollerのみを使用して機能実装を行います。

config/routes.rb
Rails.application.routes.draw do
  namespace 'api' do
    namespace 'v1' do
      resources :users, only: [:create, :index]
    end
  end
end

コントローラ

users_controllerはこのように作成致しました。

users_controller
module Api
  module V1
    class UsersController < ApplicationController
      before_action :set_job

      def create
        @job = Job.create(name: user_params[:job_name]) if @job.blank?
        user = User.new(username: user_params[:username], job_id: @job.id)
        if user.save
          render status: :created, json: { status: 201 }
        else
          render status: :unprocessable_entity, json: { status: 422 }
        end
      end

      def index
        if user_params[:job_name].nil?
          users = User.all
          render json: users
        elsif @job.nil?
          render status: :not_found, json: { status: 404 }
        else
          users = @job.users
          render json: users
        end
      end

      private

      def user_params
        params.permit(:username, :job_name)
      end

      def set_job
        @job = Job.find_by(name: user_params[:job_name])
      end
    end
  end
end

レスポンスを整形

次にjsonで返すレスポンスを整形します。
導入でインストールしたactive_model_serializersを使用します。

※ 色々調べたのですが、現在は fast_json_apiというgemの方が推奨されているようです。使い方はほとんど変わらないようですが、レスポンスがシンプルだったので今回はamsを使用しました。

こちらの記事を参考にさせて頂きました。
https://qiita.com/m_nakamura145/items/75fd7c0934daf9bcc21d

使い方は以下の通りです。
まずはコマンドで必要なファイルを作成します。

$ rails generate serializer User

app/serializers/model_serializer.rbファイルが作成されます。
作成されたファイルを以下のように記述します。

serializers/user_serializer.rb
class UserSerializer < ActiveModel::Serializer
  attributes :id, :job, :username
  belongs_to :job
  def job
    object.job.name
  end
end

これでjsonレスポンスに独自のパラメータを追加して返すことができます。

リクエスト

ではPostmanを使用してリクエストし、レスポンスをみてみます。
Postman

まずはルーティングを確認します。

$ rake routes

api_v1_ideas GET    /api/v1/users(.:format)   api/v1/users#index
             POST   /api/v1/users(.:format)   api/v1/users#create

それではPostmanで上記URLにリクエストを送ってみます。(rails s してください。)
画像左上をpostに変更してください。

スクリーンショット 2020-04-30 17.00.27.png

すると以下のようなレスポンスが得られました。

{
    "status": 201
}

これでレコードを登録することができました。

次は作成したレコードを取得してみます。
画像左上をgetに変更してください。

スクリーンショット 2020-04-30 17.05.05.png

[
    {
        "id": 1,
        "job": "testjob1",
        "username": "testuser"
    }
]

先ほど登録したレスポンスを得られました。

ここでkey,valueを設定しない場合は登録している全てのレコードを取得することができます。

以上です。

APIの記事がそもそも少なかった事と、1対多関係にあるテーブルに独自のパラメータをリクエストする方法がなかなか見つからなかったのでかなり時間がかかりました。

お付き合い頂きありがとうございました。

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

【Rails】Kaminariで同一ページにもっと見るを複数実装する

通常の場合

home_controller.rb
def index
  @cats = Cat.page(params[:page]).per(1)
end
app/views/home/index.html.erb
<%= paginate @cats %>

複数の場合

home_controller.rb
def index
  @cats = Cat.page(params[:cats_page]).per(1)
  @dogs = Dog.page(params[:dogs_page]).per(1)
end
app/views/home/index.html.erb
<%= paginate @cats, param_name: 'cats_page' %>
<%= paginate @dogs, param_name: 'dogs_page' %>

ajaxを利用したもっと見るの場合

home_controller.rb
def index
  @cats = Cat.page(params[:page]).per(1)
  @dogs = Dog.page(params[:page]).per(1)
  return unless request.xhr?
  case params[:type]
  when 'dog', 'cat'
    render "#{params[:type]}"
  end
end
app/views/home/index.html.erb
<%= link_to_next_page @cats, 'もっと見る', remote: true, params: { type: :cat }, id: 'more-cat' %>
<%= link_to_next_page @dogs, 'もっと見る', remote: true, params: { type: :dog }, id: 'more-dog' %>
app/views/home/cat.js.erb
$('.cat-wrap').append('<%= escape_javascript(render 'cat', object: @cats) %>');
$('#more-cat').replaceWith('<%= escape_javascript(link_to_next_page(@cats, 'もっと見る', params: { type: :cat }, remote: true, id: 'more-cat')) %>');

app/views/home/dog.js.erb
$('.dog-wrap').append('<%= escape_javascript(render 'dog', object: @dogs) %>');
$('#more-dog').replaceWith('<%= escape_javascript(link_to_next_page(@dogs, 'もっと見る', params: { type: :dog }, remote: true, id: 'more-dog')) %>');

参考

https://qiita.com/Coolucky/items/bde74b020b8d37ccf426
https://www.rubydoc.info/github/amatsuda/kaminari/Kaminari/ActionViewExtension

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

Address already in use - bind(2) for "0.0.0.0" port 3000 (Errno::EADDRINUSE) が出たとき

エラー内容: Address already in use - bind(2) for "0.0.0.0" port 3000 (Errno::EADDRINUSE)

解決策

3000portで繋いでいたのでそのプロセスをkillしたら直った。
割とよくあるエラーでいつもコマンドを忘れるのでメモ。。

$ kill -9 $(lsof -i tcp:3000 -t)

lsofコマンドを先にインストールしておいた方がいいかも。

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

[Rails]FullCalenderで投稿一覧も表示させつつ、マイページでは自分の投稿だけに絞ってカレンダーを表示する

目的

FullCalenderを使って、Twitter+マイページでは自分の投稿をカレンダーで見る
ということを実装する

前提

フルカレンダーを実装し、カレンダーが表示できている
下記のサイトを参考に作りました。
https://qiita.com/sasasoni/items/fb0bc1644ece888ae1d4
https://qiita.com/imp555sti/items/ee9809768f6dc9439ab5

やること

FullCalenderをまずは準備しておきます。
そして自分が一番詰まったのは、indexではフォローしている人全員を表示する。
しかし自分のマイページのカレンダーでは、自分の投稿のみに限定する。
ということです。

どうやらFullCalenderの使い方としてindexアクションで定めた@eventsをカレンダーで表示するようなので
indexでは投稿一覧を@eventsではなく、別の名前を与えて。
ユーザーの投稿一覧を@eventsとしてあげます。

index.html.erb
def index
    @all_events = Event.all.includes(:user)
    @user = User.find(current_user.id)

   #フォローしているユーザーを取得
    @follow_users = @user.followings.map { |f| f[:id] }
    @follow_users << current_user.id

   #フォローユーザーの投稿のみ表示
    @events_onlyfollow = @all_events.where(user_id: @follow_users).order("created_at DESC")
    # 自分の投稿のみ
    @events = Event.where(user_id: current_user.id)
  end

まだまだ理解が浅くちゃんとできている訳ではないと思いますが。。。
とりあえずカレンダーが自分の投稿だけで絞れたのでひとまずOK

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

Rails テストについて 2

はじめに

テストに拒否反応があるので、まずは整理したいと思います。
少しづつ記事を書いていきます。
前回記事 → Rails テストについて 1

もうすでにご存知の方、省略の仕方等ご存知でしたら、ご助言願います。

必要なGemのインストール!

Gemfileに追記

gem 'rspec-rails'

その後、bundle installです。

web_console(gemfile内)の記述!

  • web_console というgemはtest環境で動かすと不具合が起きる可能性があるようです。
  • ということで、development環境でのみ動くようにしてください。
  • group :development do ~ endの記述が無ければ下記のように作成!
  • 既にある場合、その記述の間にweb_consoleを移動!
Gemfile

group :development do
  gem 'web-console'
end

その後、bundle installです。

RSpecの設定

  • RSpec用設定ファイルの作成
ターミナル

%rails g rspec:install

こんな感じで4つ作成されます!

ターミナル

%rails g rspec:install 

Running via Spring preloader in process 3820
      create  .rspec             ①
      create  spec               ②
      create  spec/spec_helper.rb      ③
      create  spec/rails_helper.rb     ④

ファイル説明

  • rails_helper.rb

    • RailsにおいてRSpecを利用する際に、共通の設定を書いておくファイル
    • 各テスト用ファイルでこちらのファイルを読み込むことで、共通の設定や、メソッドを適用できる。
  • spec_helper.rb

    • rails_helper.rbと同じくRSpec用の共通の設定を書いておくファイル
    • しかし、こちらはRSpecをRails無しで利用する際に利用する。

.rspecファイルに追記

表示の出力を綺麗にしてくれる一文です!
その分、出力数が多いです。

.rspecファイル内に追記


--format documentation

正常にRSpecが起動するか確認

ターミナル

% bundle exec rspec
No examples found.

Finished in 0.00077 seconds (files took 0.30404 seconds to load)
0 examples, 0 failures

と出力されれば、おkです!

テスト編、続きます・・・(さて準備が完了っすよ・・・)

さいごに

日々勉強中ですので、随時更新します。
皆様の復習にご活用頂けますと幸いです。

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

Unicorn の自動起動と etc/init.dの使い方

railsをawsに置く作業をしていた時にUnicornの自動起動も試しておきたいと思いやったこと、学習したことを書きます。

Unicornの自動起動をする際に、etc/init.dにスクリプトを置くとのことで置いてみた。
これって、プログラミング言語で言うと何に当たるんだろう??と気になりつつも進めます。

まず、etc/init.d/にUnicornのfileを作成します。
作成した後には、chkconfig コマンドで自動起動をさせなきゃならない。

そもそも、initはlinuxが起動した時に呼ばれ実行する。その際、run levelが0~6まであり、2~5あたりのrun levelをchkconfig コマンドで変更する。ex)chkconfig on unicorn

変更すると、etc/rc0~6.dのfileにrun levelに応じたfileのシンボリックリンクが作成され、
実際に起動、読み込みするのは、etc/rc0.dだが、参照先としてetc/init.d/unicornが参照される。

そして、linixを起動すれば、etc/rcが動きunicornの中身も一緒に読み込まれて起動すると言う仕組みらしい。
以下は、etc/rc3.dをlsで見た際、S85unicornと言うfileができていることが確認できるかと。(シンボリックリンク付き)

[ec2-user@ip-00000 rc3.d]$ ls -la
合計 0
drwxr-xr-x  2 root root  63  4月 26 14:47 .
lrwxrwxrwx  1 root root  20  4月  7 01:51 K50netconsole -> ../init.d/netconsole
lrwxrwxrwx  1 root root  17  4月  7 01:51 S10network -> ../init.d/network
lrwxrwxrwx  1 root root  17  4月 26 14:47 S85unicorn -> ../init.d/unicorn

Unicornの一部

start()
{
  if [ -e $PID ]; then //もしPIDがあれば
    echo "$NAME already started+${PID}"
    exit 1
fi
  echo "start $NAME"//もしPIDがなければ
  su - ${USER} -c "cd ${ROOT_DIR} && ${CMD}"
}

これは、調べるとすんなり出てくる。

#!/bin/sh

#chkconfig:0000 00 00
#description:unicorn shell
USER="ec2-user"
NAME="Unicorn"
ENV=production

ROOT_DIR="/var/www/application"

PID="${ROOT_DIR}/tmp/pids/unicorn.pid"
CONF="${ROOT_DIR}/config/unicorn.rb"
OPTIONS=""
CMD="RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D"

start()
{
  if [ -e $PID ]; then
    echo "$NAME already started+${PID}"
    exit 1
fi
  echo "start $NAME"
  su - ${USER} -c "cd ${ROOT_DIR} && ${CMD}"
}
stop()
{
  if [ ! -e $PID ]; then
   echo "$NAME not started"
    exit 1
  fi
   echo "stop $NAME"
   rm ${PID}
  kill -QUIT `cat ${PID}`
}

force_stop()
{
  if [ ! -e $PID ]; then
    echo "$NAME not started"
    exit 1
  fi
  echo "stop ${NAME}"
  echo ${PID}
 kill -INT `cat ${PID}`
}

reload()
{
  if [ ! -e $PID ]; then
    echo "$NAME not started"
    start
    exit 0

 fi
  echo "reload $NAME"
  ##kill -HUP `cat ${PID}`
  su - $USER -c "cd ${ROOT_DIR} && bundle exec unicorn_rails:reload"
 ## su $USER -lc "cd ${RAILS_ROOT}&& bundle exec rake unicorn_rails:reload"
}

restart()
{
    force_stop
    sleep 5
    start
}


case "$1" in
  start)
    start
    ;;
  stop)

   ;;
  force-stop)
    force_stop
    ;;
  reload)
    reload
    ;;
  restart)
    restart
    ;;
  *)
    echo "Syntax Error: release [start|stop|force-stop|reload|restart]"
    ;;
esac           

自動起動の際につまづいたことは、etc/environmentに環境変数入れていて手動では動いていたけども、
自動起動する際には動かなかったこと。
それは、rails自体の環境変数がないためでcredentials.ymlなどに環境変数をきちんと設定してあげるといいと思います。
自分は、これで三日潰しました。

また、init自体はroot 権限で動かすみたいなので注意が必要かもしれません。

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

【Rails】form_forの基本の基

フォーム作成のメソッド

  • form_tag:(旧)モデルに関連しないフォームの作成に使う
  • form_for:(旧)モデルに基づくフォームの作成に使う
  • form_with:(新)モデルに関わらず、フォームの作成に使う。

※ Rails5.1以前では、データ登録や更新ではform_for、検索ではform_tagで実装する、というような使い分けを行う。
※ 但し、form_tagform_forは Rails5.1以降は、非推奨。今後は form_withを使ってね!という事。

form_tag

指定するのは、URL(パス)とHTTPメソッド(put、post、patch)の2つ。
httpのデフォルトはgetになっている。

基本の構造
<%= form_tag(URL, HTTPメソッド) do %>
    :
<% end %>
<%= form_tag('/items', method: :post, class:"class_name", id:"id_name") do %>
<% end %>

<%= form_tag(items_path, method: :post) do %>
<% end %>

<!-- コントローラーとアクションで指定する場合 -->
<%= form_tag({:controller => 'items', :action => 'create'},
{:method => :post}) do %>
<% end %>

<!-- シンボル型 -->
<%= form_tag({controller: :items, action: :create}, {method: :post}) do %>
<% end %>

<!-- 画像などのファイル登録の場合 -->
<%= form_tag('/items', method: :post, multipart: true) do %>
<% end %>

<!-- Ajax通信の場合 -->
<%= form_tag('/items', method: :post, remote: true) do %>
<% end %>
フォームヘルパー
  <%= label_tag :表示したい文字 %>  <!-- ラベル表示 -->
  <%= text_field_tag :name %>    <!-- 1行テキスト params[:name]に値が入る -->
  <%= text_area_tag :content %>  <!-- 複数行テキスト params[:content]に値が入る -->
  <%= submit_tag "送信" %>        <!-- 送信ボタン -->

form_for

既に保存されている場合は、updateアクション、未保存の時は、createアクションを、自動的に選んでくれる。特別なパスやアクションを呼び出したい時は、url、methodを指定する。
form_forにclassやid名をつけたい時はhtmlオプションを使用する。

基本の構造
<%= form_for モデル名 do |f| %>
    :
<% end %>

<%= form_for モデル名, url: 自分で定義したパス, method: HTTPメソッド, html: {class:'class_name', id:'id_name'} do |f| %>
    :
<% end %>
<% form_for @items do |f| %>
<% end %>

<% form_for([:name, @items]) do |f| %>
<% end %>
フォームヘルパー
 <!-- ラベル -->
  <%= f.label :name %>

 <!-- 一行のテキスト入力 -->
  <%= f.text_field オブジェクト名, プロパティ名 [, オプション] %>
  <%= f.text_field :name, class: "class_name", maxlength: 40 %>
  <%= f.text_field :name, id: :text_name %>

 <!-- 複数行のテキスト入力 -->
  <%= f.text_area オブジェクト名, プロパティ名 [, オプション] %> 
  <%= f.text_area :content, class: "class_name", size: "100x50" %>  <!-- サイズ指定はcols×rows -->

 <!-- メールアドレス入力 -->
  <%= f.email_field オブジェクト名, プロパティ名 [, オプション] %>

 <!-- 数字入力 -->
  <%= f.number_field オブジェクト名, プロパティ名 [, オプション] %>
  <%= f.number_field :item_id, min: 1, max: 150 %>

 <!-- パスワード入力 -->
  <%= f.password_field オブジェクト名, プロパティ名 [, オプション] %>

 <!--日時の入力 -->
  <%= f.datetime_field  オブジェクト名, プロパティ名 [, オプション] %>

 <!-- selectボックス(DBからデータ生成しない:select / する場合:collection_select) -->
  <%= f.select オブジェクト名, プロパティ名, タグの情報 [, オプション] %>
  <%= f.select :category, Category.all, include_blank: true %>
  <%= f.collection_select :category, Category.all, :id, :name, include_blank: true %>

 <!--日付選択selectボックス フォーマットは年月日。例)日が不要であれば{:discard_day => true}) -->
  <%= f.date_select :date, {:discard_day => true}, {start_year: 1950, end_year: 2050}, default: {year: 1950, month: 1} %>

 <!-- ファイル添付 -->
  <%= f.file_field オブジェクト名, プロパティ名 [, オプション] %>

 <!-- チェックボックス(DBからデータ生成しない:check_box / する場合:collection_check_boxes) -->
  <%= f.check_box オブジェクト名, プロパティ名 [, オプション, checked_value = "1", unchecked_value = "0"] %>
  <%= f.collection_check_boxes(:name, :ids, Item.all, :id, :name) do |b| %> 
    <%= b.label {b.check_box + b.text} %>
  <% end %>

 <!-- ラジオボタン -->
  <%= f.radio_button "カラム名", "保存したい内容" %>
  <%= f.collection_radio_buttons(:items, :ids, Item.all, :id, :name) do |b| %>
    <%= b.label {b.radio_button + b.text} %>
  <% end %>

 <!-- 非表示:入力しない情報をパラメーターに送る時に使用 -->
  <%= f.hidden_field :カラム名, value: "値" %>
  <%= f.hidden_field :user_id, value:current_user.id %>
  <%= f.hidden_field 'モデル名[user_ids][]', value: current_user.id) %>

 <!--送信ボタン -->
  <%= f.submit "送信ボタン" %>

form_with

モデルへの送信は、form_for と同様に、URL、スコープが自動推測される。Rails 5.2以降では、id属性も自動付与される。
フォーマットがAjax送信なので、HTML送信には、local: trueをつける必要がある。
フォームヘルパーはform_forと同じ書き方。

基本の構造
<!-- DBに保存しない時 -->
<%= form_with url: パス do |f| %>
    :
<% end %>

<!-- DBに保存する時 -->
<%= form_with model: モデルのインスタンス do |f| %>
    :
<% end %>
<% form_with model: @item, local: true, class: "class_name", id: "id_name" do |f| %>
<% end >

<%= form_with @item, url: {controller: 'items', action: 'index'} do |f| %>
<% end %>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】gemのアンインストール・バージョン変更

Gemのアンインストール方法

バージョンを指定することも可。

$ bundle exec gem uninstall gem名 -v 'バージョン名'

Gemfile.lockを確認すると、消えているハズ。
後は、Gemfileから直接削除すればok。

Gemのバージョン変更

バージョンダウンの場合

アンインストール後に、バージョンを指定してインストールする。

バージョンアップの場合

※ gem名を指定しなければ、Gemfileに記載の全てに対して、最新バージョンにアップデートされる。

$ gem update gem名

インストール済みのGemの確認

$ gem list

インストール済みのGemのバージョン確認

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

erbファイルをまとめてhamlに変換する方法

Hamlとは

Hamlとは、HTMLよりも簡単に書くためのビューテンプレートエンジンです。
Hamlを使用することで、「綺麗に」、「読みやすく」、「生産的に」ビューを作成することができます。

Hamlへの変換

1.Gemの導入

Gemfileの一番下に'haml-rails'を書く

Gemfile
gem 'haml-rails' 

ターミナルでbundle installする。

terminal
bundle install

2.一括変換

ターミナルで以下のコマンドを入力し、実行

terminal
rails haml:erb2haml 

コマンドを実行すると途中で

terminal
Would you like to delete the original .erb files? (This is not recommended unless you are under version control.) (y/n)

と聞かれる。
オリジナルのerbファイルを削除するか聞かれているので、特に不要なら
'y'と入力し、実行

無事にerbファイルがhamlファイルに変換される!!

補足

「=>」(ハッシュロケット)で変換されたものは「:」(シンボル型)に修正すること

参考

http://haml.info/
https://github.com/haml/haml-rails

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

Rails + jQueryでAjaxの動作テストをしてみる

はじめに

Rails + jQueryでAjaxの動作テストをしてみました。
フォームのテキスト項目に入力したユーザー名をキーに、usersテーブルを検索して、検索結果をフォームに表示する動作を、Ajaxで実現してみました。
尚、当記事は、こちらのサイトを参考にさせて頂いております。

参考URL
https://qiita.com/yuki-n/items/fdc5f7d5ac2f128221d1

環境

  • Vagrant + Ubuntu 16.04.5 LTS
  • Rails 5.2.4.2
  • jQuery

やった事

scaffoldで雛形を作成します。
jQueryが動くように動作環境を整備します(手順は省略)。

$rails new scaffold_sample
$cd scaffold_sample
$rails g scaffold user name:string age:integer
$rails db:migrate

indexビューにテキスト項目と、検索結果を表示する項目を作成します。

index.html.erb
<input type=form id="form" placeholder="ユーザー名を入力" style="width: 250px;"/>
<p id="result1"></p>

coffeeスクリプトは利用しないで、jQueryを利用するため、javascrpts/user.coffeeの拡張子を、jsに変更します。そして、ビューのイベントに対応する処理と、イベントが駆動された時にAjax通信を行う設定を記述します。

javascrpts/user.js
$(document).on('turbolinks:load', function(){
    // blurは、テキスト項目からロストフォーカスした時に発生するイベント
    $(document).on('blur', '#form', function(e){
    e.preventDefault();
    
    //テキストで入力した値を変数にセット
    var input = $.trim($(this).val());  
    
    //ajax通信の設定
    $.ajax({
      url: '/users/search',             //searchメソッドへ遷移
      type: 'GET',                      //メソッドを指定
      data: ('keyword=' + input),       //テキスト項目に入力した値を変数にセット
      processData: false,               //おまじない
      contentType: false,               //おまじない
      dataType: 'json'                  //データ形式を指定
    })
    .done(function(data){               
       })
  });
});

userコントローラの中に、searchメソッドを作成するので、searchメソッドへのルートを設定します。

routes.rb
 resources :users do
    collection do
      get 'search'
    end
  end

usersコントローラの中に、searchメソッドを作成します。Viewのテキスト項目に入力した値が、jsファイルの中で、keyword変数にセットされて、コントローラに渡されてきます。コントローラの中では、keyword変数をキーに、Userテーブルを検索して、検索結果を、@user変数にセットしています。そして、json形式でrenderします。render先は、searchというビューあるのではなく、ajaxを利用する場合、遷移元(indexビュー)に遷移される事になります。

users_controller.rb
def search
    @user = User.find_by(name: params[:keyword])
    render json: @user
  end

jsファイルに、ajax通信が成功した後の処理(.doneの中身)を記述します。

javascrpts/user.js
$(document).on('turbolinks:load', function(){
    // blurは、テキスト項目からロストフォーカスした時に発生するイベント
    $(document).on('blur', '#form', function(e){
    e.preventDefault();
    
    //テキストで入力した値を変数にセット
    var input = $.trim($(this).val());  
    
    //ajax通信の設定
    $.ajax({
      url: '/users/search',             //searchメソッドへ遷移
      type: 'GET',                      //メソッドを指定
      data: ('keyword=' + input),       //テキスト項目に入力した値を変数にセット
      processData: false,               //おまじない
      contentType: false,               //おまじない
      dataType: 'json'                  //データ形式を指定
    })
    //ajax通信が成功したらdoneに入る (dataには@usersが入る)
    .done(function(data){               
        // data変数の中身を、viewの#result1に表示する
        $(data).each(function(i, user){ 
            $('#result1').text(user.id + " " + user.name)
        });
      })
  });
});

動作確認

rails sで、http://192.168.33.10:3000/users にアクセスします。
適当にデータを新規更新します。

image.png

hemeと入力して、ロストフォーカスすると、#result1に検索結果が表示されています。
image.png

aopoと入力して、ロストフォーカスすると、#result1に検索結果が表示されています。
image.png

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

resource resourcesって何が違うの??

Railsルーターの目的

そもそもルーティングは何をしてるんや。という話。
Railsのルーターは受け取ったURLを認識し、適切なコントローラ内アクションやRackアプリケーションに割り当てます。ルーターは、ビューでこれらのパスやURLを直接ハードコードすることを避けるためにパスやURLを生成することもできます。

つまり受け取ったURLを捌いて指示を出す、司令塔ですよってこと。

resources と resource の違い

①URLにidを必要とするかしないのか
②resourceの場合単数なので、一覧みたいな概念はなく、indexが作られない

resources 複数

リソースをいくつも定義しなければならない場合は、以下のように簡単にわかりやすくできる。get,new,create,edit,update,destroy,showがresourcesでまとめられる!(only、exceptで限定することも可能)

resources :photos, :books, :videos

上の記法は以下と完全に同一です。

resources :photos
resources :books
resources :videos

ポイントとしては、リソース名がbooks、photosのような複数形になっていることにも注意
リソースが複数なのでidを持たないと識別できない

resource 単数

ユーザーがページを表示する際にidを一切参照しないリソースが使われることがあります。たとえば、/profileでは常に「現在ログインしているユーザー自身」のプロファイルを表示し、他のユーザーidを参照する必要がないとします。このような場合には、単数形リソース (singular resource) を使ってshowアクションに (/profile/:idではなく) /profileを割り当てることができます。

get 'profile', to: 'users#show'

結局どういうこと?

①URLにidを必要とするかしないのか

下記のようにresourcesが複数だとidが必要
resourceが単数だとidは要らない。

/mobile/posts/:id(.:format)  ←postは何個も存在するためidが必要 
/mobile/profile/edit(.:format) ←profileは一つしか存在しないため、idがいらない

②resourceの場合単数なので、一覧みたいな概念はなく、indexが作られない

routes.eb
resource :users

生成されるルーティング

 new_users GET    /users/new(.:format)  users#new
edit_users GET    /users/edit(.:format) users#edit
     users GET    /users(.:format)      users#show
           PATCH  /users(.:format)      users#update
           PUT    /users(.:format)      users#update
           DELETE /users(.:format)      users#destroy
           POST   /users(.:format)      users#create

参考文献

https://railsguides.jp/routing.html#%E5%8D%98%E6%95%B0%E5%BD%A2%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9

https://qiita.com/ryuuuuuuuuuu/items/e5960c7fecad4ef1301b

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

[devise]値を配列の形で保存する

背景

deviseを使っている上で、配列の形でデータを送りたいと考えたが、なかなかやり方が見つからず苦労してやっと実装出来たので、備忘録や他の人の役に立てればと思い書きました。

実装方法

deviseのデフォルトで設定されたカラム以外を保存する際に以下のコードを書いてあげるが、
配列を渡す時は「:category_ids => []」のように空の配列を一緒に付けてあげればうまく保存されます。

application_controller.rb
#中略
  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :self_introduction, :sex, :img_name, :category_ids => []])

    devise_parameter_sanitizer.permit(:account_update, keys: [:name, :self_introduction, :sex, :img_name, :category_ids => []])
  end
#中略

すごく時間がかかりましたが以外と簡単だったことに驚きました。。
deviseはやはり便利な分難しいですね

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

Heroku Postgres じぶんまとめ

プランアップする

1.まずは追加

新しいDatabaseをリソースから追加する。追加するときに、採用したいプランを選ぶ。
HEROKU_POSTGRESQL_CYAN のように追加される。PINKとか色の名前が割り当てられている模様。

2.copy

Database を追加した後、追加された HEROKU_POSTGRESQL_CYAN へコピーする。

heroku pg:copy DATABASE_URL HEROKU_POSTGRESQL_CYAN --app myapp

3. DATABASE 削除

古い方を削除。DATABASEがない状態になる。
フロントとめておくためにはメンテナンスモードにする。

4. attachment

同じ app に attach すると、DATABASEに割り当てられる。
その後、CYAN を削除する。

image.png

cf.

アップグレードの手順の中に、 copy の説明がある。

Upgrading the Version of a Heroku Postgres Database
https://devcenter.heroku.com/articles/upgrading-heroku-postgres-databases

CLIから指定するのはこちらに。
Sharing Heroku Postgres between applications
https://devcenter.heroku.com/articles/heroku-postgresql#sharing-heroku-postgres-between-applications

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

DB設計でのデータ型の決定方法

そもそもなぜデータ型を指定しないといけないの?

データ型を指定するという事は変数がどのくらいのメモリ領域を必要とするかをDBに教えてあげる行為です。

仮にデータ型を指定する,というプロセスがない場合どうなるでしょうか?

宣言された変数はどんな型のデータが入ってもいいように、一番大きくメモリを使うデータ型の分,メモリを占有します。

ユーザーが少ないWebアプリの場合なら一つ一つのメモリが無駄にスペースを取っていても処理結果の差を感じる事はありませんが,TwitterやYouTube等の大型サービスになっていくと無視できない存在になってきます。

ですので,自分の開発アプリが大規模なユーザーを抱えていくであろう事を期待しつつ,丁寧に一つ一つのカラムにデータ型を記述していきましょう。

とりあえずよく使うデータ型について復習しよう

個人的によくみるデータ型を列挙してみますので復習がてらに確認していきましょう。

データ型 特殊能力
string 文字列(1〜255文字)
text 文字列(1〜4294967296文字)
integer 整数(4バイト)
bigint 整数(8バイト)

上記のデータ型だけマスターすればもう貴方はデータ型マスターです。
さよならバイバイして旅に出た甲斐がありました。お疲れ様です。

文字列,整数の長さによってデータ型を選択しないといけないので,それぞれの注意点について解説します。

文字列

これに関してはあまり深く考えなくても大丈夫です。

単語の記入を促す場合はstringを使用する。

文章の記入を促す場合はtextをしようして下さい。

日本語ならピカソのフルネームでもstringで格納できるのでnameカラムの場合もstringでLGTMです。

整数(重要)

半角数字の場合,integerは8桁,bigintは16桁まで格納できます。

クレジットカードの番号は8桁超えるのでbigintで登録して下さい。
※これを伝えたかった

また,idも将来的にユーザーが増えると膨大な桁数になる可能性があります。
railsではデフォルトでbigintになっているので,bigintをチョイスする事をお勧めします。

参考文献

Ruby on Rails のドキュメント
https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_column

ピカソの本名
http://www.studio-cube.com/namae/namae01.html

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

【Favorite】Rails いいね機能 実装

画面収録 2020-04-30 0.34.38.mov.gif

【ゴール】

ユーザーに投稿に対していいね機能を実装する
いいねを押すとハートが赤くなる

参考:https://qiita.com/nojinoji/items/2c66499848d882c31ffa

【メリット】

UI、UXの向上
アソシエーションの理解度向上

【開発環境】

■ Mac OS catalina
■ Ruby on Rails (5.2.4.2)
■ Virtual Box:6.1
■ Vagrant: 2.2.7

【実装】 "user" "post"機能実装は割愛

  1. favorite model作成
mac.terminal
$ rails g model Favorite
  1. アソシエーション 追記

※ user : favorite = 1 : 多 
※ post : favorite = 1 : 多

config/post.rb
has_many :favorites
def favorited_by?(user)
    favorites.where(user_id: user.id).exists?
end
config/user.rb
has_many :favorites
config/favorite.rb
belongs_to :user
belongs_to :post

route 追記
※ "favorite" は "post" に関連しているのでルートをネスト(親子)させる

config/routes.rb
resources :posts do
    resources :favorites , only: [:create , :destroy]
end

favorite controller作成
※ "create" , "destroy"も一緒に作成

mac.terminal
$ rails g controller Favorites create destroy

favorite controller記述
① , ②で user_id post_id をparameterに渡す

favorites_controller.rb
class FavoritesController < ApplicationController
  def create
    @post = Post.find(params[:post_id]) ①
    favorite = @post.favorites.new(user_id: current_user.id) ②
    favorite.save
    flash[:success] = "Liked post"
    redirect_to request.referer
  end

  def destroy
    @post = Post.find(params[:post_id]) ①
    favorite = current_user.favorites.find_by(post_id: @post.id) ②
    favorite.destroy
    redirect_to request.referer
  end
end

view記述
※ modelで記述 ”@post.favorited_by?” を使用

post/show.html/erb
<% if @post.favorited_by?(current_user) %>
   <%= link_to post_favorite_path(@post), method: :DELETE do %>
   <i class="fa fa-heart" aria-hidden="true" style="color: red;"></i>
   <%= @post.favorites.count %>like
   <% end %>
<% else %>
  <%= link_to post_favorites_path(@post) , method: :POST do %>
  <i class="fa fa-heart-o" aria-hidden="true"></i>
  <%= @post.favorites.count %>like
  <% end %>
<% end %>

以上

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

docker-composeでアプリサーバーコンテナからMySQLサーバーコンテナに接続する。

実行環境

Docker for Mac
Docker version 19.03.8

簡単な事だけどかなり手こずったのでまとめ。

Dockerfile

FROM ruby:2.7.1-buster

RUN gem install rails

# node.jsをインストール
RUN apt-get update && \
    apt-get install -y node.js

# yarnをインストール
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update && apt-get install -y yarn
RUN rails webpacker:install
RUN yarn install --check-files

COPY Gemfile /Gemfile
COPY Gemfile.lock /Gemfile.lock

RUN bundle install

*開発環境には node.js、 yarn、 webpackerのインストールが必要なので先にインストールしておく。

docker-compose.yml

version: "3"
services:
  mysql:
    image: mysql:8.0.20
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_ROOT_PASSWORD: root
  app:
    build: .
    volumes:
      - ".:/app"
    ports:
      - "3000:3000"
    tty: true
    depends_on:
      - mysql
    working_dir: "/app"

これらを元にdocker-composeでコンテナを立ち上げていきます。

$ docker-compose up

立ち上がったらコンテナ内にアクセス。

$ docker exec -it (立ち上げたコンテナのNAMES) /bin/bash

mariadb-clientをインストール

$ apt install mariadb-client

mysqlにアクセス

$ mysql -u root -proot -h mysql

* docker-compose.yml参照
-u = ユーザーを指定
-p = 指定したユーザーのパスワード
-h = ホスト、mysqlコンテナの名前?
MySQL [(none)]>

*アクセス成功

一度ログアウトしconfig/database.ymlを編集します。
具体的にはdatabaseがsqliteになっていたのでmysql2に変更します。

# SQLite. Versions 3.8.0 and up are supported.
#   gem install sqlite3
#
#   Ensure the SQLite 3 gem is defined in your Gemfile
#   gem 'sqlite3'
#
default: &default
  adapter: mysql2
  encording: utf8
  username: root
  password: root
  host: mysql
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

development:
  <<: *default
  database: rails_development

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: rails_test

production:
  <<: *default
  database: rails_production

Gemfileもsqliteからmysqlに変更

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

ruby '2.7.1'

gem 'rails', '~> 6.0.2', '>= 6.0.2.2'
# sqliteからmysql2へ
gem 'mysql2'
gem 'puma', '~> 4.1'
gem 'sass-rails', '>= 6'
gem 'webpacker', '~> 4.0'
gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.7'

~省略~
$ rake db:create
$ mysql -u root -proot -h mysql * もう一度mysqlに接続
$ show databases; * rake db:createが出来ているか確認
MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| rails_development  |
| rails_test         |
| sys                |
+--------------------+
6 rows in set (0.011 sec)

一応ここまでやっとけば開発できると思う。完全に自分用で参考にならないかもしれません。
参考: Docker超入門 Part03 - 複数コンテナを動作させる

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