20200627のRubyに関する記事は20件です。

Docker で Ruby on Jets + React のアプリを作成する開発環境構築

概要

Ruby on Jets(API)と React のアプリを作成するための開発環境構築手順です。
Ruby on Jets は API 専用として作成します。DB は MySQL を利用。
React は Typescript を使います。
Docker は Docker for Mac を利用。

ローカルでページを開くと API から DB に保存されているユーザー情報を取得して表示するところまでやっています。
AWS へのデプロイまではしていません。

ファイル構成

reactjets/
  ├ api/
  │  ├ ...
  ├ front/
  │  ├ ...
  ├ docker/
  │  ├ api/
  │  │  ├ Dockerfile
  │  ├ front/
  │  │  ├ Dockerfile
  │  ├ mysql/
  │  │  ├ conf.d
  │  │  │  ├ my.cnf
  │  ├ docker-compose.yml

Docker 環境構築

Dockerfile(2種),Gemfile, Gemfile.lock, my.cnf, docker-compose.yml を作成

docker/front/Dockerfile
FROM node:12.18
docker/api/Dockerfile
FROM ruby:2.7.1

WORKDIR /api
COPY api /api
RUN bundle install
api/Gemfile
source 'https://rubygems.org'
gem 'jets'

Gemfile.lock は空のファイルを作成

api/Gemfile.lock
touch Gemfile.lock
docker/mysql/conf.d/my.cnf
[mysqld]
character-set-server=utf8mb4
explicit-defaults-for-timestamp=1

[client]
default-character-set=utf8mb4
docker/docker-compose.yml
version: '3'

services:
  front:
    build:
      context: ../
      dockerfile: docker/front/Dockerfile
    volumes:
      # :より左の部分は自分の環境に合わせる
      - ~/Dev/reactjets/front:/front
    ports:
      - "8000:3000"
    stdin_open: true

  api:
    build:
      context: ../
      dockerfile: docker/api/Dockerfile
    command: bash -c "bundle exec jets server --port 3000 --host 0.0.0.0"
    volumes:
      # :より左の部分は自分の環境に合わせる
      - ~/Dev/reactjets/api:/api
    ports:
      - "3000:3000"
    depends_on:
      - db

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: app
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      TZ: 'Asia/Tokyo'
    ports:
      - 3306:3306
    volumes:
      - ./mysql/conf.d:/etc/mysql/conf.d

docker-compose ビルド

$ docker-compose build

Jets アプリ作成

$ docker-compose run api jets new . --mode api --database=mysql

※ Overwrite /api/Gemfile? (enter "h" for help) [Ynaqdhm] がでてきたら Y

api 配下に jets アプリケーションが作成されていることを確認
DB 接続のために .env.development に環境変数を追加

.env.development
DB_HOST=db
DB_NAME=app
DB_USER=docker
DB_PASS=docker

React アプリ作成

$ docker-compose run --rm front sh -c 'yarn create react-app front --template typescript'

front 配下に react アプリケーションが作成されていることを確認

起動

$ docker-compose up --build

react 起動

$ docker exec -it docker_front_1 bash

# cd front
# yarn start

画面が表示されることを確認
Ruby on Jets : http://localhost:3000
React : http://localhost:8000
スクリーンショット 2020-06-27 10.42.37.pngスクリーンショット 2020-06-27 17.56.45.png

api 作成

user を scaffold で作成

$ docker exec -it docker_api_1 bash

# jets generate scaffold user name:string age:integer
# jets db:create db:migrate

※ jets db:create db:migrate で access denied など出ていたら mysql 側のユーザーの権限設定を確認する

GRANT ALL ON *.* to docker@'%';

users テーブルが作成されているので、直接2件適当に INSERT し
http://localhost:3000/users にアクセスすると、以下のようなデータが返ってきていることが確認できる

[{"id":1,"name":"mikami","age":26,"created_at":"2020-06-27T18:57:44.000Z","updated_at":"2020-06-27T18:57:44.000Z"},{"id":2,"name":"tomoyuki","age":32,"created_at":"2020-06-27T18:57:44.000Z","updated_at":"2020-06-27T18:57:44.000Z"}]

front と api の疎通

front 側

axios インストール

$ docker exec -it docker_front_1 bash

# cd front
# yarn add axios

App.tsx を編集

App.tsx
import React from 'react';
import axios from 'axios';
import './App.css';

class App extends React.Component<any, any> {
  constructor(props: any) {
    super(props);
    this.state = {
      users: []
    }
  }

  componentDidMount() {
    axios.get('http://localhost:3000/users')
      .then((result) => {
        this.setState({ users: result.data });
      })
  }

  render() {
    return (
      <div className="App">
        <h1>Users</h1>
        <div>
          { this.state.users.map((v: any) => {
            return (
              <div key={v.id}>
                <p>id: {v.id}</p>
                <p>name: {v.name}</p>
                <p>age: {v.age}</p>
              </div>
            )
          })}
        </div>
      </div>
    )
  }
}

export default App;

このままでは CORS で通信できないので、api 側で CORS の設定をする

api 側

以下のコメントアウトを外す

application.rb
config.cors = true # for '*'' # defaults to false

確認

再起動

$ docker-compose stop
$ docker-compose start
$ docker exec -it docker_front_1 bash

# cd front
# yarn start

http://localhost:8000/ にアクセスすると以下のように表示されていれば疎通ok
スクリーンショット 2020-06-27 19.25.09.png

WIP

AWS へのデプロイ手順

Ruby on Jets デプロイ

https://qiita.com/kskinaba/items/9c570093ed912f8f1681 この通りにやる

Ruby 2.5系じゃないとだめらしい…

Deploying to Lambda api-dev environment...
/usr/local/bundle/gems/memoist-0.16.2/lib/memoist.rb:213: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/usr/local/bundle/gems/jets-2.3.16/lib/jets/lambda/dsl.rb:319: warning: The called method `_unmemoized_find_all_tasks' is defined here
Building CloudFormation templates.
Generated CloudFormation templates at /tmp/jets/api/templates
Deploying CloudFormation stack with jets app!
Waiting for stack to complete
02:25:31AM CREATE_IN_PROGRESS AWS::CloudFormation::Stack api-dev User Initiated
02:25:34AM CREATE_IN_PROGRESS AWS::S3::Bucket S3Bucket
02:25:35AM CREATE_IN_PROGRESS AWS::S3::Bucket S3Bucket Resource creation Initiated
02:25:56AM CREATE_COMPLETE AWS::S3::Bucket S3Bucket
02:25:58AM CREATE_COMPLETE AWS::CloudFormation::Stack api-dev
Stack success status: CREATE_COMPLETE
Time took for stack deployment: 28s.
You are using Ruby version 2.7.1 which is not supported by Jets.
Jets uses Ruby 2.5.3.  You should use a variant of Ruby 2.5.x
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

バブルソート、選択ソートをRubyで作る

目的

ソートアルゴリズムについて、実際にコードを書いてまとめてみる。
言語はRubyでやってみます。

ソートについて

ソートは、入力として与えられた数字を小さい順に並び替えること。

バブルソート

バブルソートは、「数列の右から左に向かって、隣り合う2つの数字を比較して入れ替える」操作を繰り返し行う。数列に対して、処理を1周行えば、一番小さい数字が配列の1番目に入る。要素の数だけ周回することで並び替えることができる。

bubble.rb
def bubble_sort(array)
  length = array.length
  (length - 1).times do |round|
    (length - 1 - round).times do |n|
      if array[length - n - 1] < array[length - n - 2]
        smaller = array[length - n - 1]
        array[length - n - 1] = array[length - n - 2]
        array[length - n - 2] = smaller
      end
    end
  end
  array
end

array = [2, 3, 13, 7, 8, 9, 11, 1, 5]
bubble_sort(array) #=> [1, 2, 3, 5, 7, 8, 9, 11, 13]

バブルソート関数の中身
・配列arrayの長さをlengthで取得(1行目)
・(length - 1)ラウンドで入れ替えが終了する(2行目)
・n回目のラウンドでは、(length - n - 1)回比較して、入れ替える処理を行う(3行目)
・左の数値が右の数値よりも大きい場合は入れ替える(4~7行目)
大小比較の回数は、(length - 1) + (length - 2) + ・・・+ 1 = (length)^2 / 2 になる。

選択ソート

選択ソートは、「数列の中から最小値を検索し、左端の数字と入れ替える」という操作を繰り返す。

selection.rb
def selection_sort(array)
  length = array.length
  (length - 1).times do |round|
    min = round + 1
    round.upto(length - 1) do |n|
      if array[n] < array[min]
        min = n
      end
    end
    min_number = array[min]
    array[min] = array[round]
    array[round] = min_number
  end
  array
end

最小値のインデックス番号を取得して、検索した後に入れ替える。
バブルソートと同じで、大小比較する回数は (length)^2 / 2 になる。

後書き

次は、挿入ソート、ヒープソート、マージソート、クイックソート、バケットソートについてもまとめようと思います。

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

Rubyの基本用語

プログラミング初心者が
アウトプット用にRubyの基本用語をまとめていきます。

Rubyの基本用語

1.Ruby
大きなWebアプリケーションから小さなプログラムまで作ることができるプログラミング言語。
拡張子は「.rb」

2.rubyコマンド
Rubyに関するさまざまな操作が実行できるコマンド。
ターミナルで打ち込む。

3.irb(Interactive Ruby)
ターミナルから直接Rubyのプログラムを動かすことができる機能。

4.式展開
文字列の中に式を入れることができる機能。
「文字列の中で#{式}」とするだけでOK。

5.配列
複数の値をもつことができる値。
[ ]を用いて順番で値を管理する。
配列の中のデータを「要素」という。

6.添字
配列の各要素に割り振られた番号のこと。
添字は「0」から始まる。

7.ハッシュ
複数の値を持つことができる値。
{ }を用いてキー(名前)とバリュー(値)で管理する。

8.クラス
値の共通の属性と処理を定義するもの。設計図のようなもの。

9.インスタンス
クラスを元にして作られるデータのこと。

10.クラスメソッド
クラスで共通の情報を使った処理に使用するメソッド。
クラス自身が使用する。

11.インスタンスメソッド
インスタンスごとの個別の情報を使った処理に使用するメソッド。
「インスタンスメソッドを定義したクラス」から生成されるインスタンスが使用する。

12.属性と属性値
属性はデータの性質となる情報のこと。
属性値はそれぞれにあてはまる具体的な情報のこと。

13.インスタンス変数
データが持つ属性を定義する変数。
すべてのインスタンスが同じ属性をもち、個々のインスタンスが別の値をもつことができる。
先頭に「@」をつける。

14.ローカル変数
データが持つ属性を定義する変数。
記述してあるインスタンスメソッド内でしか使用できない。

15.initializeメソッド
インスタンスが生成された瞬間に、生成されたインスタンスが実行する処理を定義するインスタンスメソッド。

16.Sinatra
Rubyのフレームワークのひとつ。
基本的に処理速度が速い。
既存の機能が少ないので、初心者でもゼロからWebアプリケーションを構築しやすくなっている。
大規模なアプリを作成しようとすると相応のカスタマイズが必要になる。

まとめ

厳密にはRuby"限定"の用語ではないものも含まれていますが、Rubyの学習において学んだ用語なので記述しておきます。

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

Rubyにおけるクラスとインスタンスの違いについて

はじめに

Rubyを学習していて出てくる、
クラスとインスタンスの概念。

初学時にどういう意味かさっぱりわからなかったので、
例を挙げながら書いていきます。

クラスとは

値(データ)に持たせたい、共通の属性と処理に関するルールを決めるための雛形。
実体を持たないので、クラスだけではデータを動かせません。

例) 車でいうと「設計図」にあたる。
   設計図は、色や形(共通の属性)をどうするかとか、
   走る、止まる、ウィンカーを出すなど(共通の処理)をどうするか、
   などが書かれた紙。
   あくまで設計図なので、車(インスタンス)がないと動かない。

# クラスの定義(大文字で始める)
class Car

end

インスタンスとは

クラスを元にして作られるデータのこと。
実体を持っており、クラスで定義した共通の属性と処理を持っています。

例) 車でいうと「車」にあたる。
   車は、色や形(共通の属性)を持っていて、
   走る、止まる、ウィンカーを出すなど(共通の処理)ができる。
   設計図から作られた車そのものなので、実体もあるし、もちろん動く。

# インスタンスの生成
class Car

end

taxi = Car.new  # newメソッドでCarクラスのインスタンスを生成して、変数taxiに代入
puts taxi  # インスタンスを出力
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DragonRubyで簡易タイピングゲーム

以前、DragonRuby GTK (Game Toolkit) で遊んでみた という記事を書きました。

QiitaにHello, Worldを投稿するとだいたい飽きる(!)のですが、今回は引き続き触っています。

ふと「タイピングゲームを作りたいな」と思ったので、その練習に単純なものを作ってみました。

作ったもの

tor.gif

テキストが表示されて、それを入力するだけです。
タイムオーバーとかもなく、ただそれだけです。

こちらのリンクからWebブラウザでプレイできます。
https://tnantoka.github.io/typing-on-rails/
※ Firefoxだとたまにエラーになります(ページ更新で解消するはず)

ソースコードはGitHubにあります。
https://github.com/tnantoka/typing-on-rails

タイプするテキストをRails Guidesのサンプルコードから借りたので、Typing on Railsという名前になっています。

Tips

基本的にはDragonRuby GTK (Game Toolkit) で遊んでみた の内容で作れるのですが、
一部書いてないものがあったのでメモしておきます。

背景色を変える

outputs.background_color[R, G, B] を設定すれば変更できます。

# 赤!!!
outputs.background_color = [255, 0, 0]

押されたキーの一覧を取る

前回使った inputs.keyboard.key_up.space でも入力状態は取れるのですが、
今回はキーの一覧を見る実装にしてみました。

入力されたキーはinputs.keyboard.key_down.truthy_keysで取得できます。

# aを入力
[:char, :raw_key, :a]

# A(Shift + a)を入力
[:char, :raw_key, :a, :shift]

# Command + Shift + aを入力
[:char, :raw_key, :a, :shift, :meta]

フォントによってLabelのサイズわりと違う

Labelsize_enumには -1010を指定できるのですが、同じ10を指定しても、フォントによって結構サイズが違います。

例えば、以下の4つのフォントを並べてみると…

Screen Shot 2020-06-20 at 14.10.57.png

こうなります。

使うフォントによって size_enum を調整する必要がありそうです。

公開したゲームが動かない

packageしたbuildをGitHub pagesで公開したら、動きませんでした。

原因は、

Server reported failure downloading 'app/.main.rb.swp'!

というエラーでした。
.gitignoreでGitは無視してくれますが、当然DragonRubyは無視してくれないので…。

builds/typing-on-rails-html5-0.1/manifest.json を見ると不要なファイルが含まれていることに気づけるかもしれません。
(今回の .swp ファイルもバッチリ入っていました)

まとめ

200行足らずで作れました。
(前回作ったPrimitives.rbの分は数えていませんが)
お手軽です。

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

開発メモ ~複数枚投稿した画像の一枚目のみを表示させたい~

はじめに

画像を同時に複数枚投稿した場合に、画像を表示させるための記述に工夫を加えなければなりませんでした。
その内容を忘れないために、メモとして記事を投稿します。

やりたいこと

複数枚投稿した写真のindex番号が一番若いものをindex画面に表示させたい

記述

ファイル名.html.haml

section.fifth-headline
  %h2.title ピックアップカテゴリー
  .contentsbox
    .contents-title
      %h3.heading 新規投稿商品
    .contents-lists
      .contents-list
        - @newProducts.each do |product|
          =link_to "#" do
            .contents-list__itmes
              .contents-list--item
                = link_to product_path(product), class: "listBtn" do
                  %figure.product__images
                    = image_tag product.images[0].name.url, alt: "image_url",size: "200x150", class:"new-img"
              .contents-list--inner
                %h3.name  
                  = product.name
                .data
                  %ul
                    %li 
                      = product.price
                      
                    %li
                      %i.fa.fa-star.likeIcon 0
                  %p (税込)

home_controller

def index
    @newProducts = Product.includes(:images).where(status: 0).order("RAND()")
     ~省略~
  end

ポイント

画像を複数枚投稿した場合で、1枚目だけを表示させたい時以下の様に記述する事でindex番号の[0]を取得することができる

= image_tag product.images[0].name.url, alt: "image_url",size: "200x150", class:"new-img"

また、この場合はindexアクションで呼び出すファイルを定義してあげなければならい。
よって、.where(status: 0)定義しインスタンス変数に代入してあげる。

@newProducts = Product.includes(:images).where(status: 0).order("RAND()")

これで上手く実装できると思います!

終わりに

今回は、『こんな書き方もできるんだ!』と思い、記事にしました!
まだまだ、勉強中ですので間違っている箇所がありましたらコメントください!

ありがとうございました!

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

Rails CRUD機能実装②(今回は、編集、詳細)

前回の続きで、編集と詳細を記載します。

機能追加するときの手順復習:routes.rb→controller追記→view追加

編集機能


新規投稿と似たような手順です。
編集画面表示(edit)→入力内容で更新(update)
routes.rb
resources :birds, only: [:index, :new, :create, :destroy, :edit]

image.png

一覧画面に編集画面へのリンクを貼ります。
Prefixが「edit_bird」でidを渡して、GETメソッドなので以下のようになりますね。

index.html.erb
<%=link_to "編集", edit_bird_path(bird.id), method: :get %>

渡されたidと一致するレコードを取得し、編集画面へと渡します。

birds_controller.rb
def edit
  @bird = Bird.find(params[:id])
end

そして、編集画面です。

edit.html.erb
<%=form_with(model:@bird, local:true) do |form|%>
  <%=form.text_field :name, placeholder: "鳥の名前"%>
  <%=form.text_field :pic, placeholder: "鳥の写真のURL"%>
  <%= form.submit "更新"%>
<%end%>

ちゃんと編集画面へのリンクが表示されています。
image.png

クリックするとちゃんと遷移しますね!
image.png

ここからは更新処理です!

まずはroutes.rb!

routes.rb
resources :birds, only: [:index, :new, :create, :destroy, :edit, :update]

controllerで入力内容を受け取って、DBを更新します!新規投稿で作成した、bird_paramを使用します!

birds_controller.rb
...
  def update
    bird = Bird.find(params[:id])
    bird.update(bird_params)
  end
  private
  def bird_param
    # params.require(:モデル名).permit(:カラム名,:カラム名,......)
    params.require(:bird).permit(:name, :pic)
  end
...

image.png

image.png

image.png

ちゃんとカワセミ2に変更されていますね!

詳細表示機能

いよいよ最後の機能です!頑張りましょう!!

routes.rb
resources :birds, only: [:index, :new, :create, :destroy, :edit, :update, :show]

としてもいいですが、全機能追加しているので、onlyの記述はいらないですね!消しましょう!

routes.rb
  resources :birds

かなりスッキリしました!!

一覧画面に詳細画面へのリンクを貼りましょう!
rails routesコマンドを実行すると
image.png
prefixがbird,methodがGETで、idもしてしてあげましょう!

index.html.erb
<%= link_to '詳細', bird_path(bird.id), method: :get %>

そしてcontrollerでidを受け取り、レコードを取得します!

birds_controller.rb
def show
    @bird = Bird.find(params[:id])
  end

いよいよ最後に、show.html.erbです!

show.html.erb
<%= @bird.name %>
<div style=
"background-image: url(<%= @bird.pic %>); 
 background-position: center center;
 background-size: cover;
 width: 300px; 
 height: 300px;
 margin-bottom: 10px;
 ">
</div>

image.png

きちんと選択したものが表示がされています。

まとめ

railsは、modelを渡せばリンク先を自動識別してくれたりと、フレームワークの決まりを理解すれば、爆速で基本的なサイトが作れますね。
今度は、ログイン機能を実装させますので、ご期待ください!
最後まで、ありがとうございました!!

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

初投稿。グループ機能作成中に起きた事

Routing Error

グループ機能作成中に起きたRouting Errorについて、
この画像では、controllerがgroupsになっている。
スクリーンショット 2020-06-27 17.58.09.png
下の画像では、groupsとなっているが、ここでgroupにした事でRouting Errorが起きてしまった。
スクリーンショット 2020-06-27 17.57.30.png

マイグレーションについて

例えばこの様マイグレーションファイルにdb:migrateで間違った記述をしてしまった時
スクリーンショット 2020-06-27 18.08.31.png
db:rollbackで戻して訂正する事ができる。
また、db:migrateで訂正完了です。

db:rollback

db:rollbackでは一つ前しか戻せない。

db:rollback STEP=数字

db:rollback STEP=数字を使う事で任意に所まで戻す事ができる。

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

Rails CRUD機能実装①(今回は、新規追加、削除)

この記事の目的

railsを用いた、CRUD機能をもったwebアプリケーションの作成手順です。鳥の写真と名前を投稿できるサイト(birdtweet)です。

railsアプリケーションの作成

railsのバージョン6.0.0を指定。-dの後ろに使用するDB(今回はmysql)を指定。

rails _6.0.0_ new birdtweet -d mysql

設定変更。

config/database.yml
...
#  encoding: utf8mb4
  encoding: utf8
...

DB作成

cd birdtweet
rails db:create

Gemfileの編集
プロジェクト直下にあるGemfileを開く

Gemfile
# gem 'mysql2', '>= 0.4.4'
gem 'mysql2', '>= 0.5.3'
........
(ファイル最下行)
gem 'pry-rails'

ターミナルで設定内容の更新

bundle update

modelの作成

ターミナルにて

rails g model bird

カラムを追記

db/migrate/2020********create_birds.rb
...
create_table :birds do |t|
      t.string :name
      t.text :pic
      t.timestamps
end
...

コマンドにて、変更内容の更新!

rails db:migrate

コンソールでDBにデータをいくつか入れます。

rails c
Bird.create(name: "ツノメドリ", pic: "https://cdn.pixabay.com/photo/2020/05/26/13/22/puffins-5223057_1280.jpg")
Bird.create(name: "カワセミ", pic: "https://cdn.pixabay.com/photo/2017/02/07/16/47/kingfisher-2046453_1280.jpg")
exit

コントローラの作成

以下のコマンドで、コントローラを作成します。

rails g controller birds

複数形にしたり、しなかったり混乱しますが、
モデルだけが単数形です!

ここからの流れ

各機能作成の流れはほぼほぼ同じです!

routes.rbに追記

index.html.erbに各機能へのリンクを追記(index意外)

birds_controller.rbに追記

機能名.html.erb作成

一覧表示機能

railsには7つのアクションがある。


  • index:一覧

  • show:詳細

  • new:新規作成画面への遷移

  • create:新規データの保存

  • edit:編集画面への遷移

  • update:編集内容の更新

  • destroy:削除

全機能を使わない場合は、onlyオプションで使うものだけを指定する。

config/routes.rb
# resourcesの後ろは、モデル名の複数形
  resources :birds, only: :index
app/controllers/birds_controller.rb
...
def index
    # インスタンス変数にBirdモデルのデータを格納します。
    @birds = Bird.all
  end
...

index.html.erbファイル作成
ビュー内でインスタンス変数を、eachメソッドを使って全て表示します。

app/views/birds/index.html.erb
<% @birds.each do |bird| %>
<%= bird.name %>
<div style=
"background-image: url(<%= bird.pic %>); 
 background-position: center center;
 background-size: cover;
 width: 300px; 
 height: 300px;
 margin-bottom: 10px;
 ">
</div>
<%end%>

以下のように、表示されました!!!
image.png

新規投稿機能

流れは同じく、routes → controller → viewなのですが、投稿画面への移動(new)からのデータ追加(create)なので、一連の流れを二回やります!

routes.rb
Rails.application.routes.draw do
  # resourcesの後ろは、モデル名の複数形
  # アクションが複数あるときは、配列の形にしてあげます
  resources :birds, only: [:index, :new]
end
index.html.erb
<%=link_to '新規投稿', new_bird_path, method: :get%>
...

image.png

birds_controller.rb
...
def new
  # Birdモデルのインスタンス化したものを、インスタンス変数に格納します。
  @bird = Bird.new
end
...

new.html.erb作成

app/views/birds/new.html.erb
<%# 遷移先urlを記載しなくても、インスタンス変数に入れたモデルから判断して、遷移してくれます %>
<%=form_with(model: @bird, local: true) do |form| %>
  <%= form.text_field :name, placeholder: "鳥の名前" %>
  <%= form.text_field :pic, placeholder: "鳥の写真のURL" %>
  <%= form.submit "投稿" %>
<%end%>

http://localhost:3000/birds/new
にアクセスすると投稿画面ができてます!
image.png

次は、入力情報を登録する機能です。

routes.rb
Rails.application.routes.draw do
  # resourcesの後ろは、モデル名の複数形
  # アクションが複数あるときは、配列の形にしてあげます
  resources :birds, only: [:index, :new, :create]
end

birds_controller.rb
formからのハッシュの形でデータが送られてきます。
全てのデータを受け取るのは危険です!

名前と写真のURLだけでいいのに、ログイン情報のキーを悪意で追加されて、他人のログイン情報を勝手に変更し乗っ取るということができてしまいます。
そこで、ストロングパラメータを使います。
また、privateを記述した行より下は、他のファイルから呼び出せないメソッドとなります。メソッドが増えたときに、見るべきファイルを減らせるメリットがあります。

birds_controller.rb
...
  def create
    # private下に定義したbird_paramで指定したパラメータを受け取り、保存する。
    Bird.create(bird_param)
  end

  private
  def bird_param
    # params.require(:モデル名).permit(:カラム名,:カラム名,......)
    params.require(:bird).permit(:name, :pic)
  end
...

create.html.erb作成

app/views/birds/create.html.erb
<h3>投稿完了!</h3>
<a href="/birds">一覧へ</a>

image.png

image.png

今のままだと、何も入力しないで登録ができてしまいます。そこでバリデーションチェックするための記述をします。

app/models/birds.rb
class Bird < ApplicationRecord
  # 入力必須にしたいカラム名を書きます。
  validates :name, presence: true
  validates :pic, presence: true
end

これでからのデータを登録できなくなりました!!

削除機能

routes.rb
...
resources :birds, only: [:index, :new, :create, :destroy]
...

削除機能へのリンクの調べかたは、まずコマンドで

rails routes

とします。
すると、以下の出力がされます。
Prefixの値に「_path」をつけると、URIに記載されているURLが出力されます。
image.png

今回は削除なので、VerbにDELETEと描かれている行に注目します。Prefixは「bird」となっているので、「bird_path」とすればいいですね。メソッドは、「Verb」に「DELETE」とあるので「delete」とすれば良いですね。あとは、idも渡します!

index.html.erb
...
<%= bird.name %><%=link_to "削除", bird_path(bird.id), method: :delete%>
...

リンクが表示されました。
image.png

bird_controller.rb
...
  def destroy
    # 今回は抽出したデータをどこにも送らないので、@をつけません。
    bird = Bird.find(params[:id])
    bird.destroy
  end
...
destroy.html.erb
<a href="/birds">一覧画面</a>

image.png
image.png
つのめどりがちゃんと削除されています!

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

【Rails】form_withを使ったフォロー機能の実装手順を解説します

概要

form_withを使ってフォロー機能を実装する手順を書いていきます!

以下の機能を実装していきます
1.ユーザーをフォロー/フォロー解除できる機能
2.フォローユーザー/フォロワーの一覧表示機能

Railsでフォロー機能を作る方法の記事の方を参考にしており、特にフォロー機能に関するアソシエーションの詳しい解説などはこの記事が大変参考になりました!

前提

環境
 ・Rails 5.2.4.2
 ・Ruby 2.6.5
 ・Slim
 ・devise

加えて、User系機能が実装されていることが前提となります。

上記の環境でのRailsアプリケーションのセットアップ方法
 ・Railsアプリケーションをセットアップ後にdeviseとSlimを導入する手順

↓実装後はこんな感じになります。(見栄えが簡素ですみません…)↓
ezgif.com-video-to-gif (3).gif

フォロー/フォロー解除機能の実装

1.Relationshipモデル作成

$ rails g model Relationship user:references follow:references

・ここで作成されるrelationshipsテーブルが、フォローするユーザー&フォローされるユーザーにとっての中間テーブルとなる。

userをフォローする側のユーザーモデル、followをフォローされる側のユーザーモデルとして、中間テーブルには認識させます。


2.relationshipsマイグレーションファイルの編集

db/migrate/[timestamps]_create_relationships.rb
class CreateRelationships < ActiveRecord::Migration[5.2]
  def change
    create_table :relationships do |t|
      t.references :user, foreign_key: true
      t.references :follow, foreign_key: { to_table: :users }
 
      t.timestamps
 
      t.index [:user_id, :follow_id], unique: true
    end
  end
end

・userとfollowでそれぞれ参照先のモデルを分けているのは、フォローする側のユーザフォローされる側のユーザーとでは別々のモデルとして考える必要があるからです。

t.references :user, foreign_key: trueuserモデルに対する外部キーを張っています。

t.references :follow, foreign_key: { to_table: :users }followモデルに対する外部キーを張っています。followモデルというのは実在しない架空のモデル名で、今この時勝手に作成してます。よって、{ to_table: :users }とする事で、参照元のモデルを教えてあげています。

t.index [:user_id, :follow_id], unique: trueuser_idとfollow_idの組み合わせに一意性を持たせることでデータの重複を防ぎます、つまり同じユーザーを2度フォローされる事を防いています。


3.DBの内容を保存

$ rails db:migrate


4.RelationshipモデルにUserに対するアソシエーションを記述する。

app/models/relationship.rb
class Relationship < ApplicationRecord
  belongs_to :user
  belongs_to :follow, class_name: "User"
 
  validates :user_id, presence: true
  validates :follow_id, presence: true
end

belongs_to :userこれはいつも通りのアソシエーションです。

belongs_to :follow, class_name: "User"followクラスに所有される事を記述していますが、上述したようにfollowは架空のクラスですので、class_name: "User"によって参照元のモデルを教えてあげます。


5.UserモデルファイルにRelationshipに対するアソシエーションを記述する。

app/models/user.rb
class User < ApplicationRecord
 
#==============あるユーザーがフォローしているユーザーとのアソシエーション=================
  has_many :relationships, foreign_key: "user_id",
                           dependent: :destroy
  has_many :followings, through: :relationships, source: :follow
#==========================================================================
 
#==============あるユーザーをフォローしてくれてるユーザーとのアソシエーション================
  has_many :passive_relationships, class_name: "Relationship",
                                   foreign_key: "follow_id",
                                   dependent: :destroy
  has_many :followers, through: :passive_relationships, source: :user
#===========================================================================
end

・上記のRelationshipモデルファイルでは、あるユーザーがフォローしているユーザーにアクセスするためのアソシエーションと、あるユーザーがフォローされているユーザーにアクセスするためのアソシエーションを記述しています。
 つまりどういうことか、詳しくは図で後述します。

5-1.まずは、あるユーザーがフォローしているユーザーとのアソシエーションの解説です!

has_many :relationships, foreign_key: "user_id", dependent: :destroyこれは、あるUserが中間テーブルrelationshipsの外部キーuser_idにアクセスする事を可能にするアソシエーションを宣言をしています。

以下のようにイメージすると分かり易いかと思います!

スクリーンショット 2020-06-27 13.44.10.png

has_many :followings, through: :relationships, source: :followこれは、あるUserが中間テーブルrelationshipsのfollow_idを通して、followingモデルにアクセスする事を可能にするアソシエーションを宣言をしています。

イメージで言うと以下のような感じです!

スクリーンショット 2020-06-27 13.57.34.png

・上記の2行により、User.followingsとする事でUserがフォローしているユーザー達を取得できるようになります。これが取得できるようになると、あるUserのフォローユーザーの一覧表示などが簡単に行うことができます。

5-2.次は、あるユーザーをフォローしてくれているユーザーとのアソシエーションの解説です!

has_many :passive_relationships, class_name: "Relationship", foreign_key: "follow_id", dependent: :destroyこれは、あるUserがpassive_relationshipsのfollow_idへアクセスする事を可能にするアソシエーションを宣言をしています。
  passive_relationshipsは、この場で勝手に作った架空のモデルなので、class_name: "Relationship"として参照元のモデルを教えています。

イメージは以下の通りです!

スクリーンショット 2020-06-27 14.13.33.png

has_many :followers, through: :passive_relationships, source: :userこれは、あるUserがpassive_relationshipsのuser_idを通してfollowersへアクセスする事を可能にするアソシエーションの宣言をしています。

イメージは以下の通りです!

スクリーンショット 2020-06-27 14.26.37.png

・上記の2行により、User.followersとすれば、Userをフォローしてくれているユーザー達を取得することが可能になります。これを使えば、あるユーザーをフォローしてくれているユーザーの一覧表示などが簡単に行えるようになります!


6.Userモデルファイルに、フォロー関連のインスタンスメソッドを定義する

app/models/user.rb
class User < ApplicationRecord
  .
  .
  .
  #<アソシエーション関連の記述省略>
  .
  .
  .
  def following?(other_user)
    self.followings.include?(other_user)
  end

  def follow(other_user)
    unless self == other_user
      self.relationships.find_or_create_by(follow_id: other_user.id)
    end
  end

  def unfollow(other_user)
    relationship = self.relationships.find_by(follow_id: other_user.id)
    relationship.destroy if relationship
  end
end

following?(other_user)User.followings.include?(@user)などとすることで、Userが@userのことをフォローしてるかどうかを確かめます。フォローボタン実装の際に、フォローするボタンを表示するのか、それともフォローを解除するボタンを表示するのかを条件分岐させるために使います。

follow(other_user)User.follow(@user)とすることで、@userをフォローすることができるようにします。unless self == other_userで、自分のことをフォローできないようにしてます。find_or_create_byを使って、@userのidレコードが存在する場合はそれを参照し、なければ作成するようにしてます。

unfollow(other_user)User.unfollow(@user)とする事で、@userのフォローを解除できるようにします。

ユーザーをフォローするメソッド、フォロー解除するメソッドの定義ができたので、次はこれらのメソッドを使って実際にDBへアクセスしてフォロー・フォロー解除する機能をrelationshipsコントローラを作成して、実装していきます!


7.relationshipsコントローラを作成する。

$ rails g controller relationships 
app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController

  before_action :set_user

  def create
    following = current_user.follow(@user)
    if following.save
      flash[:success] = "ユーザーをフォローしました"
      redirect_to @user
    else
      flash.now[:alert] = "ユーザーのフォローに失敗しました"
      redirect_to @user
    end
  end

  def destroy
    following = current_user.unfollow(@user)
    if following.destroy
      flash[:success] = "ユーザーのフォローを解除しました"
      redirect_to @user
    else
      flash.now[:alert] = "ユーザーのフォロー解除に失敗しました"
      redirect_to @user
    end
  end

  private
  def set_user
    @user = User.find(params[:relationship][:follow_id])
  end
end

relationshipsコントローラでは、ユーザーをフォローするcreateアクション、フォローを解除するdestroyアクションしか機能しないので、createアクション、destroyアクションだけを記述します。
  
フォロー/フォロー解除ボタンフォームからは、params[:relationship][:follow_id]と言う形でデータが送信されるので、find(params[:relationships][:follow_id])と言う形でデータを受け取ります。

before_action :set_userそれぞれのアクションでは必ず@userを取得する事になるので、set_userプライベートメソッドを定義してからbefore_actionを使ってあらかじめ取得させています。

createアクションログインしているユーザー(current_user)が、取得した@userをフォローしています。Userモデルファイルで定義したfollow(other_user)インスタンスメソッドを使用しています。

destroyアクションログインしているユーザーが、取得したユーザーのフォローを解除しています。Userモデルファイルで定義したunfollow(other_user)インスタンスメソッドを使用しています。

実際にDBへアクセスしてフォロー・フォロー解除する機能が仕上がったので、次は実際にフォロー・フォロー解除するためのボタンの実装を行います!


8.フォロー/フォロー解除ボタンをform_withで実装する。

・始めに、app/viewsディレクトリ配下に、relationships/_follow_form.html.slimファイルを作成してください。

app/views/relationships/_follow_form.html.slim
- unless current_user == user
  #フォロー解除ボタン
  - if current_user.following?(user)
    = form_with model: @relationship, url: relationship_path, method: :delete, local: true do |f|
      = f.hidden_field :follow_id, value: user.id
      = f.submit "フォローを解除する"
  #フォローボタン
  - else
    = form_with model: @set_relationship, url: relationships_path, local: true do |f|
      = f.hidden_field :follow_id, value: user.id
      = f.submit "フォロー"

- unless current_user == user自分自身のことをフォローできないよう、ボタン自体の表示を切り替えています。ここでのuserとは、このパーシャルを配置するビューが取得する@userのことを指します。

8-1.フォロー解除ボタンの解説

- if current_user.following?(user)ログインユーザーが相手ユーザーをフォローしているかどうかを確かめています。フォローしていればフォロー解除ボタンを表示し、フォローしていなければフォローボタンを表示するようにしています。

= form_with model: @relationship, url: relationship_path, method: :delete, local: true do |f|こちらはフォロー解除用のボタンです。

  model: @relationship@relationshipはインスタンス変数で、ログインユーザーと相手ユーザーとのRelationshipを取得しています。
  (app/views/users/show.html.slimにこのフォローボタンのフォームを配置するなら、app/controllers/users_controller.rbファイルのshowアクションに、@relationshipインスタンス変数を定義する事になります。)

  url: relationship_pathは、relationshipsコントローラのdestroyアクションへのルーティングです。ルーティングの記述はあとで行います。

  method: :deleteでは、HTTPリクエストでDELETEメソッドを指定しています。

  local: trueは、これを付けないとフォームの送信の仕様がAjaxになり、データを送信できなくなるのでform_withでは必ず記述します。

f.hidden_field :follow_id, value: user.id:この部分は、実際に完成形のソースコードを見てみるとわかりやすいです。__

スクリーンショット 2020-06-27 15.28.15.png

:follow_idを指定することで、params[:relationship][:follow_id]と言う形でデータが送信されます。relationshipsコントローラのset_userプライベートメソッドで定義した部分では、このデータを受け取っています。

value: user.idを指定することで、:follow_idにフォローしている相手ユーザーのidが格納されて、データが送信されます。

8-2.フォローボタン

= form_with model: @set_relationship, url: relationships_path, local: true do |f|相手ユーザーをフォローするためのフォームです。

  model: @set_relationship@set_relationshipインスタンス変数では空のモデルを生成しており、この空のモデルを参照して、params[:relationship][:follow_id]と言う形でデータが送信されるようにします。

  url: relationships_pathは、relationshipsコントローラのcreateアクションへのルーティングです。ルーティングの記述は後で行います。

= f.hidden_field :follow_id, value: user.id:これも実際の完成後のソースコードを確認してみます。

スクリーンショット 2020-06-27 15.47.01.png

フォロー解除ボタンと同じで、params[:relationship][:follow_id]と言う形でデータが送信されてます。

・フォロー/フォロー解除ボタンの作成が完了しましたので、次はこのデータが正常にアクションへ送られるようルーティングを設定します!


9.relationshipsコントローラへのルーティングを追加する。

config/routes.rb
Rails.application.routes.draw do
  .
  .
  #<他のルーティングは省略>
  .
  .
  resources :relationships, only: [:create, :destroy]

$ rails routes | grep relationshipコマンドで、追加されたルーティングを確認してみます。

$ rails routes | grep relationship
  relationships  POST   /relationships(.:format)                                                        relationships#create
  relationship   DELETE /relationships/:id(.:format)                                                             relationships#destroy

・これでrelationships_pathでフォロー/relationship_pathでフォロー解除できるようになってるのが確認できたかと思います。


10.フォロー/フォロー解除ボタンを配置する。

・相手ユーザーのページに飛んだ際にフォローしたり、フォロー解除できるようにする場合を考えて、app/views/users/show.html.slimファイルに配置していきたいと思います。

app/views/users/show.html.slim
h1 ユーザープロフィールページ
p
  = "名前 : "
  = @user.username

#================フォローボタンの追加=============================

  = render 'relationships/follow_form', user: @user

#============================================================

p= link_to "プロフィール編集", edit_user_path(current_user)

・user: @user__パーシャルに記述したuserが、showアクションで定義されている@userを参照しています。__

・ボタンの配置はできましたが、このままではボタンは機能しません。先ほども述べたように、@relationshipインスタンス変数と、@set_relationshipインスタンス変数を、showアクションに定義してあげなければならないからです。


11.app/controllers/users_controller.rbのshowアクションに、インスタンス変数を定義する。

app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
  def show
    @user = User.find(params[:id])
    @relationship = current_user.relationships.find_by(follow_id: @user.id)  
    @set_relationship = current_user.relationships.new
  end
  .
  .
  .
end

@relationship = current_user.relationships.find_by(follow_id: @user.id)フォロー解除フォームで参照しているインスタンス変数です。ここでcurrent_userと@userとのrelationshipsを取得することで、フォームにてparams[:relationship][:follow_id]のようにデータを送信することができるようになります

@set_relationship = current_user.relationships.newフォローするフォームで参照しているインスタンス変数です。params[:relationship][:follow_id]と言う形にしてデータを送信したいので、このように空のインスタンス変数を生成してます。

・以上で、ユーザーをフォロー/フォロー解除する機能の実装が完了しました!
 次は、フォローしているユーザー/フォローしてくれているユーザーを一覧で表示する機能を実装していきます!


フォローユーザー/フォロワーの一覧表示機能

1.始めにフォローユーザー/フォロワーの一覧ページへのリンクをビューに作成する

・app/views/users/show.html.slimに、そのユーザーのフォローユーザー/フォロワーの一覧ページへのリンクを追加します。

app/views/users/show.html.slim
h1 ユーザープロフィールページ
p
  = "名前 : "
  = @user.username

#==============フォロー/フォロワー一覧ページへのリンク=================

  = link_to "フォロー: #{@user.followings.count}", followings_user_path(@user.id)
  = "/"
  = link_to "フォロワー: #{@user.followers.count}", followers_user_path(@user.id)

#============================================================

  = render 'relationships/follow_form', user: @user
p= link_to "プロフィール編集", edit_user_path(current_user)

・フォローユーザー/フォロワーへのアクセスは、先ほどUserモデルファイルで定義したfollowings/followersを使います。

@user.followings.countユーザーのフォローしているユーザーの数を表示してます。
followings_user_path(@user.id)URLがusers/:id/followingsとなるパスを指定したいので、左記のように記述します。この形のパスを指定できるように、ルーティングの記述を後で行ってあげます。

・フォロワー一覧ページへのアクセスも、フォローユーザー一覧ページへアクセスするのと同じような方法で記述しています。


2.フォロー/フォロワー一覧ページへのルーティングを追加する。

config/routes.rb
Rails.application.routes.draw do
  .
  .
  .
  resources :users do
    get :followings, on: :member
    get :followers, on: :member
  end
  .
  .
  .
end

・上記のように記述したら$ rails routes | grep followコマンドでルーティングを確認してみます。

$ rails routes | grep follow
  followings_user  GET    /users/:id/followings(.:format)                                                          users#followings
  followers_user   GET    /users/:id/followers(.:format)                                                           users#followers

followings_user_pathはフォローユーザー一覧のページへ、followers_user_pathはフォロワー一覧ページへ飛ぶようになったので、これでOKです。

・followingsアクションも、followersアクションもusersリソースにネストさせたので、usersコントローラで2つのアクションを定義します。


3.usersコントローラにfollowingsアクション、followersアクションを追加する。

app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
  def followings
    @user = User.find(params[:id])
    @users = @user.followings.all
  end

  def followers
    @user = User.find(params[:id])
    @users = @user.followers.all
  end
  .
  .
  .

・followingsアクション内では、@userのフォローしているユーザー全てを、followersアクション内では、@userのフォロワー全てを取得しています。


4.フォローユーザー/フォロワー一覧を表示するビューを作成する。

・app/views/usersディレクトリに、followings.html.slimファイルとfollowers.html.slimファイルを作成します。

app/views/users/followings.html.slim
h2 フォローしている方々

- @users.each do |user|
  hr
  = "username: "
  = link_to user.username, user_path(user.id)
app/views/users/followers.html.slim
h2 フォロワーの皆さん

- @users.each do |user|
  hr
  = "username: "
  = link_to user.username, user_path(user.id)

・以上で、フォローユーザー/フォローユーザー一覧ページの作成が完了しました!

参考にさせて頂いた記事

 Railsでフォロー機能を作る方法

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

[Rails] ヘルパーメソッドform_withについて[基礎]

学習中に理解が浅かったところなのでアウトプットしながら整理したいと思います。
基礎から丁寧に書いていきます。もし指摘あればお願いいたします。

ヘルパーメソッドとは

そもそもrailsでは、viewでHTMLタグを出現させたりテキストを加工するためのメソッドが予め用意されています。これらをヘルパーメソッドといいます。
form_withはヘルパーメソッドの一種です。

*ヘルパーメソッドの一例
ヘルパーメソッド 使用用途
form_tag 投稿ページなどにおけるフォームの実装
link_to      リンクの実装
simple_format 投稿した文章を自動で見やすく整形する
submit_tag    submit機能をつけたいときに使う。
text_field_tag
などなど、、
自作することも可能らしいです。
【参考記事】
https://qiita.com/Yukaaaah/items/19e524fd0c0e4a3451f1

form_withについて

Rails 5.1というバージョンから推奨されているフォーム実装のためのヘルパーメソッドです。
form_tag/form_forは非推奨となっているらしいです。(この2つのメソッドについては説明を省略します。)

<!-- form_tagを使用した例 -->
<%= form_tag('/posts', method: :post) do %>
  <input type="text" name="content">
  <input type="submit" value="投稿する">
<% end %>
<!--form_withを使用した例-->
<%= form_with model: @post, local: true do |form| %>
  <%= form.text_field :content %>
  <%= form.submit '投稿する' %>
<% end %>

form_withの特徴としては、
①自動でパスを選択してくれて、HTTPメソッドを指定する必要が無いこと
②コントローラーから渡された、ActiveRecordを継承するモデルのインスタンスが利用できること(上記では@postがそれに該当)

またこの場合は、
①新規投稿の場合
②既存の投稿を呼び出した場合
で処理が変わってきます。

①新規投稿の場合

posts_controller.rb
def new
  @post = Post.new
end

投稿ボタンをクリックしたらcreateアクションに送られます。

new.html.erb
<%= form_with model: @post, class: :form, local: true do |form| %>
  <%= form.text_field :title, placeholder: :タイトル, class: :form__title %>
  <%= form.text_area :content, placeholder: :ブログ本文, class: :form__text %>
  <%= form.submit '投稿する', class: :form__btn %>
<% end %>

②既存の投稿を呼び出した場合

posts_controller.rb
def edit
  @post = Post.find(params[:id])
end
edit.html.erb
<%= form_with model: @post, class: :form, local: true do |form| %>
  <%= form.text_field :title, placeholder: :タイトル, class: :form__title %>
  <%= form.text_area :content, placeholder: :ブログ本文, class: :form__text %>
  <%= form.submit '投稿する', class: :form__btn %>
<% end %>

投稿ボタンをクリックしたらupdateアクションに送られます。

まとめ

比較してみるとnew.html.erbとedit.html.erbのフォーム部分は同じです!!!
そのためフォーム部分を部分テンプレート化できて記述量を減らせます。
モデルの@postの中身があるかどうかで自動で判断して送ってくれるのです。

このほかにも
例えばform_with model: [@￰post, @￰comment]のように複数モデルを渡すことができます。
それは別記事で書ければと思います、、

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

Railsのdevise導入でdefault_url_optionsの設定でハマった

deviseのユーザー認証設定

デフォルトの場合以下のようにconfig.action_mailer.default_url_options{ host: 'localhost', port: 3000 }と設定されると多います。

development.rb
  # default url
  config.action_mailer.default_url_options = {  host: 'localhost', port: 3000 }
  # mail setting
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => "smtp.gmail.com",
    :port => 587,
    :user_name => Rails.application.credentials.gmail[:user_name],
    :password => Rails.application.credentials.gmail[:password],
    :authentication => :plain,
    :enable_starttls_auto => true
  }

その場合認証メールで送られてくるURLはhttp://localhost:3000/users/confirmation?confirmation_token=-XiHyA_1xCxhk846ae9G
みたいな形になる思います。

Dockerでrootディレクトリが3000ポートを付けない形で構築したのでポート番号がない形でURLを作成しなければいけないので以下のように設定を変更しました。

development.rb
config.action_mailer.default_url_options = {  host: 'localhost' }

URLが変更されない

本来であればhttp://localhost/users/confirmation?confirmation_token=-XiHyA_1xCxhk846ae9Gのような形でURLが生成されるはずがされず数時間ハマりました。

結論

Dockerの再起動で反映された。

Web開発をしていると常にハマるポイントがありますが、再起動で動くことが多々あるので「ハマったら再起動してみる」ということをもっと心がけて行きたいです。

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

調べる力 各方法まとめ プロジェクト内とGemで定義されている場合

動機

新しいプロジェクトに参加した時、もうメソッドだらけでどこに定義されているか調べることにかなり苦労しました。早くキャッチアップするためには、「早く調べて理解する力」が非常に重要と感じまとめてみました。

調べ方も一長一短あります。

プロジェクト内で定義されているメソッドの場合

1. git grep -n <メソッド名>

  • エディタの全文検索より、ターミナルで色付きで表示されるので見やすいです
  • -n オプションで行番号がつくので、コマンド + パスクリックでエディタで開きます!
  • デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とすると多少絞られる。

2. ブラウザでGithubの検索窓に入力し、"in this repository"で検索

  • この方法は1.と結果は同じなのですが、マッチした箇所の上下数行もまとめて表示されます。
  • エディタを使いたくない時にいいです
  • デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とダブルクオーテーションをいれると絞られる

3. pry-docsのshow-source機能を使う

  • Railsコンソールを開き、$ <メソッド名> OR show-source <メソッド名>
  • 定義箇所のdefからendまでを表示してくれます!
  • パスも出るので、コマンド + クリックでエディタで表示できます。
  • デメリット:user.method を調べたい時、Userインスタンスを作成してからでないと調べられないので手間。

4. Pryの"step"機能を使う

  • binding.pryで停止した時に、stepを実行すると、そのメソッド内に"入る"ことができます。
  • 処理の流れと変数の定義も見ることができ、深い理解ができます。
  • Gemなど深いところも見れます。
  • デメリット:binding.pryの設置と、処理を走らせ止めることがめんどくさい。

ピカワカ【Rails】Pryについて徹底解説!

Gemなどプロジェクト外で定義されている場合

1. Dashで検索する

  • Dashとは、素のRuby、Gem、JavaScriptなど色んなドキュメントの横断検索ができるツールです。
  • ソースコードに加えて、そのメソッドの説明付きなので理解も早くなります。
  • VSCodeに拡張機能"Dash"をいれることで、コマンド + H でDash検索に飛べます
  • デメリット:たまに調べたいGemがなかったりする

2. bundle show <gem名>

  • Gemのインストールされたディレクトリが表示されるので、VSCodeならコマンド + クリックで別ウィンドウで開くことができます。
  • デメリット:gitやpryは使えないので、エディタの横断検索でメソッドを見つける必要があります。

3. Pryの"step"機能を使う

  • プロジェクト内で定義されているメソッドの場合と同じです。

4. ブラウザでGithubの検索窓に入力し、"in this repository"で検索

  • プロジェクト内で定義されているメソッドの場合と同じです。

その他

1. Rubymineの定義元ジャンプを使う

  • VSCode使用者なので使ったことないです。が、RubyやRails、Gem内の定義ならDashでほぼまかなえる気がします。
  • デメリット:高い、遅い

2. VSCodeの拡張機能 Solargraphを使う

  • Rubyメソッドの上にカーソルを載せるだけで、そのドキュメントや使用例が表示されます。
  • 補完機能もあり
  • デメリット:Dockerを使用する場合は辛い。SolargraphはそのLanguage serverを起動させ続ける必要がある。Solargrapコンテナを立ち上げ、Portの設定をVSCodeにする必要がある。参考:Docker環境でsolargraphを使う方法

最後に

  • 皆様の「調べ方」が知りたいです。
  • 他に良い方法があれば、コメントにて教えてくださいm(_ _)m
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

調べる力 各方法まとめ プロジェクト内とRails/Gem内で定義されている場合

動機

新しいプロジェクトに参加した時、もうメソッドだらけでどこに定義されているか調べることにかなり苦労しました。早くキャッチアップするためには、「早く調べて理解する力」が非常に重要と感じ、先輩エンジニアにも聞きながらまとめてみました。

調べ方も一長一短あります。

プロジェクト内で定義されているメソッドの場合

1. git grep -n <メソッド名>

  • エディタの全文検索より、ターミナルで色付きで表示されるので見やすいです
  • -n オプションで行番号がつくので、コマンド + パスクリックでエディタで開きます!
  • デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とすると多少絞られる。

2. ブラウザでGithubの検索窓に入力し、"in this repository"で検索

  • この方法は1.と結果は同じなのですが、マッチした箇所の上下数行もまとめて表示されます。
  • エディタを使いたくない時にいいです
  • デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とダブルクオーテーションをいれると絞られる

3. pry-docsのshow-source機能を使う

  • Railsコンソールで、$ <メソッド名> OR show-source <メソッド名>
  • 定義箇所のdefからendまでを表示してくれます!
  • パスも出るので、コマンド + クリックでエディタで表示できます。
  • デメリット:user.method を調べたい時、Userインスタンスを作成してからでないと調べられないので手間。

4. Pryの"step"機能を使う

  • binding.pryで停止した時に、stepを実行すると、そのメソッド内に"入る"ことができます。
  • 処理の流れと変数の定義も見ることができ、深い理解ができます。
  • Rails/Gemなど深いところも見れます。
  • デメリット:binding.pryの設置と、処理を走らせ止めることがめんどくさい。

ピカワカ【Rails】Pryについて徹底解説!

Gemなどプロジェクト外で定義されている場合

1. Dashで検索する

  • Dashとは、素のRuby、Rails, Gem、JavaScriptなど色んなドキュメントの横断検索ができるツールです。
  • ソースコードに加えて、そのメソッドの説明付きなので理解も早くなります。
  • VSCodeに拡張機能"Dash"をいれることで、コマンド + H でDash検索に飛べます
  • デメリット:たまに調べたいGemがなかったりする

2. bundle show <gem名>

  • Gemのインストールされたディレクトリが表示されるので、VSCodeならコマンド + クリックで別ウィンドウで開くことができます。
  • デメリット:gitやpryは使えないので、エディタの横断検索でメソッドを見つける必要があります。

3. Pryの"step"機能を使う

  • プロジェクト内で定義されているメソッドの場合と同じです。

4. ブラウザでGithubの検索窓に入力し、"in this repository"で検索

  • プロジェクト内で定義されているメソッドの場合と同じです。

その他

1. Rubymineの定義元ジャンプを使う

  • VSCode使用者なので使ったことないです。が、RubyやRails、Gem内の定義ならDashでほぼまかなえる気がします。
  • デメリット:高い、遅い

2. VSCodeの拡張機能 Solargraphを使う

  • Rubyメソッドの上にカーソルを載せるだけで、そのドキュメントや使用例が表示されます。
  • 補完機能もあり
  • デメリット:Dockerを使用する場合は辛い。SolargraphはそのLanguage serverを起動させ続ける必要がある。Solargrapコンテナを立ち上げ、Portの設定をVSCodeにする必要がある。参考:Docker環境でsolargraphを使う方法

最後に

  • 皆様の「調べ方」が知りたいです。
  • 他に良い方法があれば、コメントにて教えてくださいm(_ _)m
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

メソッドの定義場所 調べる方法まとめ プロジェクト内とRails/Gem内で定義されている場合

動機

新しいプロジェクトに参加した時、もうメソッドだらけでどこに定義されているか調べることにかなり苦労しました。早くキャッチアップするためには、「早く調べて理解する力」が非常に重要と感じ、先輩エンジニアにも聞きながらまとめてみました。

調べ方も一長一短あります。

プロジェクト内で定義されているメソッドの場合

1. git grep -n <メソッド名>

  • エディタの全文検索より、ターミナルで色付きで表示されるので見やすいです
  • -n オプションで行番号がつくので、コマンド + パスクリックでエディタで開きます!
  • デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とすると多少絞られる。

2. ブラウザでGithubの検索窓に入力し、"in this repository"で検索

  • この方法は1.と結果は同じなのですが、マッチした箇所の上下数行もまとめて表示されます。
  • エディタを使いたくない時にいいです
  • デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とダブルクオーテーションをいれると絞られる

3. pry-docsのshow-source機能を使う

  • Railsコンソールで、$ <メソッド名> OR show-source <メソッド名>
  • 定義箇所のdefからendまでを表示してくれます!
  • パスも出るので、コマンド + クリックでエディタで表示できます。
  • デメリット:user.method を調べたい時、Userインスタンスを作成してからでないと調べられないので手間。

4. Pryの"step"機能を使う

  • binding.pryで停止した時に、stepを実行すると、そのメソッド内に"入る"ことができます。
  • 処理の流れと変数の定義も見ることができ、深い理解ができます。
  • Rails/Gemなど深いところも見れます。
  • デメリット:binding.pryの設置と、処理を走らせ止めることがめんどくさい。

ピカワカ【Rails】Pryについて徹底解説!

Gemなどプロジェクト外で定義されている場合

1. Dashで検索する

  • Dashとは、素のRuby、Rails, Gem、JavaScriptなど色んなドキュメントの横断検索ができるツールです。
  • ソースコードに加えて、そのメソッドの説明付きなので理解も早くなります。
  • VSCodeに拡張機能"Dash"をいれることで、コマンド + H でDash検索に飛べます
  • デメリット:たまに調べたいGemがなかったりする

2. bundle show <gem名>

  • Gemのインストールされたディレクトリが表示されるので、VSCodeならコマンド + クリックで別ウィンドウで開くことができます。
  • デメリット:gitやpryは使えないので、エディタの横断検索でメソッドを見つける必要があります。

3. Pryの"step"機能を使う

  • プロジェクト内で定義されているメソッドの場合と同じです。

4. ブラウザでGithubの検索窓に入力し、"in this repository"で検索

  • プロジェクト内で定義されているメソッドの場合と同じです。

その他

1. Rubymineの定義元ジャンプを使う

  • VSCode使用者なので使ったことないです。が、RubyやRails、Gem内の定義ならDashでほぼまかなえる気がします。
  • デメリット:高い、遅い

2. VSCodeの拡張機能 Solargraphを使う

  • Rubyメソッドの上にカーソルを載せるだけで、そのドキュメントや使用例が表示されます。
  • 補完機能もあり
  • デメリット:Dockerを使用する場合は辛い。SolargraphはそのLanguage serverを起動させ続ける必要がある。Solargrapコンテナを立ち上げ、Portの設定をVSCodeにする必要がある。参考:Docker環境でsolargraphを使う方法

最後に

  • 皆様の「調べ方」が知りたいです。
  • 他に良い方法があれば、コメントにて教えてくださいm(_ _)m
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

検索機能の実装 学習メモ(ポートフォリオ 作成編)

はじめに

ポートフォリを作成にあたり、検索機能を実装しましたのでそのメモとして記事を投稿します

検索の入力欄とボタンを作成

app/views/tweet/index

= form_with(url: search_tweets_path, local: true, method: :get, class: "search-form") do |form|
  = form.text_field :keyword, placeholder: "投稿を検索する", class: "search-input"
  = form.submit "検索", class: "search-btn"

searchアクションのルーティングを設定

routes

 resources :tweets do 
    resources :comments, only: :create
      collection do #追加
        get 'search' #追加
      end  #追加
    〜省略〜
  end

下の様に表示される。
image.png

ポイント

railsでは、7つのアクション以外でルーティングを設定する方法にcollectionとmemberがあります

- -
collection ルーティングに:idがつかない
member ルーティングに:idがつく

今回は、を使いいます。
定義しましたら、rails routesをして実際にお確かめてみてください。

検索するメソッドをTweetモデルに定義

モデルにテーブルから検索するためのメソッドsearchを定義します。

MVCの観点で検索するなどのロジックは、メソッドとしてモデルにまとめて定義するようにします。

searchメソッドをTweetモデルに定義します。
検索したキーワードが含まれている投稿を取得するために、whereメソッドとLIKE句を利用します。

モデルを編集

app/models/tweet.rbに以下を追加。

def self.search(search)
    if search
      Tweet.where('text LIKE(?)', "%#{search}%")
    else
      Tweet.all
    end
  end

ポイント

whereメソッドについて

ActiveRecordメソッドの1つです。モデル.where(条件)のように引数部分に条件を指定することで、テーブル内の条件に一致したレコードのインスタンスを配列の形で取得できます。

引数の条件には、「検索対象となるカラム」を必ず含めて、条件式を記述します。

モデル.where('検索対象となるカラムを含む条件式')

LIKE句について

LIKE句は、曖昧(あいまい)な文字列の検索をすることができるもので、whereメソッドと一緒に使います。

例えば、1文字目に'a'という文字列が入ったデータや最後の文字に'b'が入っているデータ、文字列の途中に'c'が入ったデータなどを検索したい時に、曖昧文字列というものを使って検索することです。

実行例 実行例
where('title LIKE(?)', "a%") aから始まるタイトル
where('title LIKE(?)', "%b") bで終わるタイトル
where('title LIKE(?)', "%c%") cが含まれるタイトル
where('title LIKE(?)', "d_") dで始まる2文字のタイトル
where('title LIKE(?)', "_e") eで終わる2文字のタイトル

searchアクションをコントローラーに定義

モデルに書いたsearchメソッドを呼び出します。seachメソッドの引数にparams[:keyword]と記述して、検索結果を渡しています。

また、未ログイン状態にトップページへリダイレクトされてしまうことを回避するため、before_actionのexceptオプションに:searchを追加しています。

app/controllers/tweets_controller.rb

  before_action :move_to_index, except: [:index, :show, :search]

 def search
    @tweets = Tweet.search(params[:keyword])
  end

〜省略〜

 private
  def move_to_index
    redirect_to action: :index unless user_signed_in?
  end

最後にhtmlを作成

記述は以下です

app/views/tweets/search.html.erb

= form_with(url: search_tweets_path, local: true, method: :get, class: "search-form") do |form|
  = form.text_field :keyword, placeholder: "投稿を検索する", class: "search-input"
  = form.submit "検索", class: "search-btn"
.contents.row
  - @tweets.each do |tweet|
    = render partial: "tweet", locals: { title: tweet }

tweet部分テンプレートの記述は自分の場合以下の様になています。
まだ未完成ですが、とりあえずこちらで問題なく動きました。
app/views/tweets/_tweet.html.erb

.users_tweets
  - @tweets.each do |tweet|
    .users_tweets__lists
      .users_tweets__lists_list
        .users_tweets__lists_list__tweet_image
          = link_to tweet_path(tweet) do
            = attachment_image_tag tweet, :image
          = tweet.title

        .users_tweets__lists_list__user_image    
          = link_to user_path(tweet.user.id) do
            = attachment_image_tag tweet.user, :profile_image, fallback: "no-image.png"  
          = link_to tweet.user.username,user_path(tweet.user.id)  

        .users_tweets__lists_list__user_name  
          = tweet.updated_at.strftime("%Y-%m-%d %H:%M")
          更新日
          - if current_user.already_liked?(tweet)
            = link_to tweet_likes_path(tweet), method: :delete do
              %i.fas.fa-heart
          - else
            = link_to tweet_likes_path(tweet), method: :post do
              %i.far.fa-heart
          = tweet.likes.count

これで実装できると思います!

もしエラーが発生した場合などは、コメントください。

ありがとうございました!

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

RailsとDockerでよく使うコマンドまとめ

docker-compose build #コンテナの作成
docker-compose up #コンテナ立ち上げ
docker-compose down #コンテナをダウン ctrl+cでも止められるがserver.pidでエラーになる
docker-compose stop #コンテナをストップ
docker-compose up --build #docker関連のファイルの変更を反映した上に、サーバーを再起動
docker images #イメージ一覧
docker ps #動いているコンテナ一覧
docker ps -a #動いていないコンテナも含めた一覧
docker rm `docker ps -a -q` #コンテナの一括削除
docker rmi `docker images -a -q` #イメージの一括削除
mysql -u root -p -h localhost -P 3306 --protocol=tcp #DockerからMYSQLへ

docker-compose run web bundle install #bundle install
docker-compose run web rails db:create #db作成
docker-compose run web rails db:migrate #マイグレート

以上、RailsとDockerでよく使うコマンドたちでした!
参考になれば幸いです。
間違えなどありましたらご指摘お願いします。

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

【Rails】ブラウザのページタイトルをページごとに変更する方法

目標

スクリーンショット 2020-06-27 10.43.42.png

開発環境

・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

前提

下記実装済み。

Slim導入

実装

1.application_helper.rbを編集

application_helper.rb
module ApplicationHelper
  # 追記
  def full_title(page_title = '')
    base_title = "Bookers"
    if page_title.empty?
      base_title
    else
      "#{ page_title } | #{ base_title }"
    end
  end
end

【解説】

◎ ベースとなるタイトル(アプリ名等)を設定し、変数へ代入する。

base_title = "Bookers"

◎ 引数で受け取った各ページのタイトルが空の場合はベースタイトルのみを表示する。

if page_title.empty?
  base_title

◎ 引数で受け取った各ページのタイトルが存在する場合は両タイトルを表示する。

else
  "#{ page_title } | #{ base_title }"

page_titleが「本一覧」だとすると、本一覧 | Bookersと表示される。

2.ビューを編集

application.html.slimを編集する。

application.html.slim
/ 変更前
title
  | Bookers

/ 変更後
title
  = full_title(yield(:title))

② 各ページのビューを編集する。

例として、books/index.html.slimのタイトルを設定します。

books/index.html.slim
/ 追記
= provide(:title, '本一覧')
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】エラーメッセージを個別に表示する方法

目標

ezgif.com-video-to-gif.gif

開発環境

・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

前提

下記実装済み。

Slim導入
投稿機能実装

実装

1.application.rbを編集

application.rb
module Bookers2Debug
  class Application < Rails::Application
    config.load_defaults 5.2

    # 追記
    config.action_view.field_error_proc = Proc.new do |html_tag, instance|
      if instance.kind_of?(ActionView::Helpers::Tags::Label)
        html_tag.html_safe
      else
        class_name = instance.object.class.name.underscore
        method_name = instance.instance_variable_get(:@method_name)
        "<div class=\"has-error\">#{html_tag}
          <span class=\"help-block\">
            #{I18n.t("activerecord.attributes.#{class_name}.#{method_name}")}
            #{instance.error_message.first}
          </span>
        </div>".html_safe
      end
    end
  end
end

【解説】

① エラーが出ていない場合はHTMLをそのまま表示する。

if instance.kind_of?(ActionView::Helpers::Tags::Label)
  html_tag.html_safe

② エラーが出ている場合はエラーメッセージをフォームの下に表示する。

else
  class_name = instance.object.class.name.underscore
  method_name = instance.instance_variable_get(:@method_name)
  "<div class=\"has-error\">#{html_tag}
    <span class=\"help-block\">
      #{I18n.t("activerecord.attributes.#{class_name}.#{method_name}")}
      #{instance.error_message.first}
    </span>
  </div>".html_safe

◎ インスタンスのクラス名を変数へ代入

class_name = instance.object.class.name.underscore

◎ インスタンスのメソッド名を変数へ代入

method_name = instance.instance_variable_get(:@method_name)

◎ エラーメッセージ部分のHTMLを作成する。

"<div class=\"has-error\">#{html_tag}
  <span class=\"help-block\">
    #{I18n.t("activerecord.attributes.#{class_name}.#{method_name}")}
    #{instance.error_message.first}
  </span>
</div>".html_safe

「タイトルを入力してください」と表示する場合、
#{I18n.t("activerecord.attributes.#{class_name}.#{method_name}")}が、
「タイトル」にあたる部分で、
#{instance.error_message.first}が、
「を入力してください」にあたる部分になる。

2.エラーメッセージを日本語化

① Gemを導入

Gemfile
# 追記
gem 'rails-i18n'
ターミナル
$ bundle

application.rbを編集

application.rb
module Bookers2Debug
  class Application < Rails::Application
    config.load_defaults 5.2
    config.i18n.default_locale = :ja # 追記

    config.action_view.field_error_proc = Proc.new do |html_tag, instance|
      if instance.kind_of?(ActionView::Helpers::Tags::Label)
        html_tag.html_safe
      else
        class_name = instance.object.class.name.underscore
        method_name = instance.instance_variable_get(:@method_name)
        "<div class=\"has-error\">#{html_tag}
          <span class=\"help-block\">
            #{I18n.t("activerecord.attributes.#{class_name}.#{method_name}")}
            #{instance.error_message.first}
          </span>
        </div>".html_safe
      end
    end
  end
end

ja.ymlを作成し、編集

ターミナル
$ touch config/locales/ja.yml
ja.yml
ja:
  activerecord:
    attributes:
      book:
        title: タイトル
        body: 本文
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsチュートリアル 第1章 ゼロからデプロイまで【やってみた】

Railsチュートリアル第1章をやってみて終えたので、やったことや失敗したことを振り返ります。細かく見ていくので、チュートリアルしながらみてもらえれば嬉しいです。

※こちらの記事ではRailsチュートリアル第4版を使用しています。
現在はRailsチュートリアル第6版が出ています。
下記リリース時のnote
https://note.com/yasslab/n/n1543187c3ed6?magazine_key=md778735d3f77

ちなみに細かなことですが、読む字体を明朝体かゴシック体に変更することができます。自分はゴシック体にするととても読みやすくなったので、お好みに合わせて変更すると良いかと思います。

また2章で新しいアプリを作るので、この章でデプロイできなくても大丈夫です。

1.1.1 前提知識

RailsチュートリアルでProgeteの関連講座を紹介してますが、
これは本当にやった方がいいと感じます。
第1章でコマンドラインとGitコースが紹介されていますが、
「後ででもいけるだろ」と思って結局コマンドのミスで、アプリが作り直しになったりと、大変なことになりました!
始める前にこちらのコースをすることをおすすめします。

1.2.1 開発環境

クラウドIDEである、Cloud9をインストールする

1.2.2 Railsをインストールする

    $ printf "install: --no-document \nupdate:  --no-document\n" >> ~/.gemrc
    $ gem install rails -v 5.1.6     # -vでバージョンを指定 
    $ cd ~/environment    # 'environment' ディレクトリに移動する
    $ rails _5.1.6_ new hello_app

1.3.1 Bundler

Gemfile内にあるデフォルトの内容をバージョンを指定して記述、インストールします。

$ cd hello_app/
$ bundle install

上手くいかない時はbundle updateを実行

1.3.2 rails sever

$ cd ~/environment/hello_app/    #hello_appディレクトリへ移動
$ rails server    #サーバーを起動

rails serverを起動した後は、このターミナル内はリアルタイムで更新されていくので、注意すること。
画面をプレビューするとRailsのぺージが!!Yay!

1.3.3 Model-View-Controller

モデル・ビュー・コントローラーがそれぞれ関わっているというお話。

model: アプリケーションデータ、ビジネスルール、ロジック、関数
view: グラフや図などの任意の情報表現
controller: 入力を受け取りmodelとviewへの命令に変換する
--Wikipediaより引用

ここで一つの疑問が。
RailsはこのMVCアーキテクチャパターンを採用しているということ。「このパターンを採用している」ということは他のパターンもあるということ...?調べてみました。

・フォームとコントロール
・プレゼンテーション・モデル
・アプリケーション・モデル
・MVVM
・モデル・ビュー・プレゼンタ(MVP)

参考記事 https://www.atmarkit.co.jp/fdotnet/chushin/greatblogentry_10/greatblogentry_10_01.html

内容は上手く理解できなかったけど、MVC以外ももちろんあるよ!ということが分かりました。
構造からもう自由なんだなと思うとプログラミングはすごい
この詳しい内容もまた勉強していきます。

1.3.4 Hello,wold!

ビューも通さずHello,world!を表示させるため、以下のようなコードを記述しています。

titleapp/controllers/application_controller.rb
 def hello
    render html: "hello, world!"
  end

renderメソッドはrender("フォルダ名"/"ファイル名")のように使うと思っていましたが、こんな使い方もできるんですね

Railsガイド 2.2 renderを使用する
Railsガイドによると最早何でも出力できます、みたいな勢い。

ルーティングを設定してブラウザで表示させます。

1.4.1インストールとセットアップ

ここからGitでのバージョン管理ができるようにしていきます。

$ git config --global user.name "Your Name"
$ git config --global user.email your.email@example.com

ここでの名前とメールアドレスは今後一般に公開されるので注意。

リポジトリを作成するため、以下の内容をターミナル内で記述する

$ git init    #Gitの初期化
$ git add -A    #現在のディレクトリにあるすべてのファイルを追加
#ファイル追加後ステージングされ、コミット待ちになる
$ git status    #現在のステージングの確認
$ git commit -m "Initialize repository"    #リポジトリにコメント付きで反映させる
$ git log    #コミットメッセージの履歴を見る

いきなりリポジトリとは何だろう?という感じでしたが、こちらを読んだらとても分かりやすかったです。
【イラストで覚える】初心者のためのGitとGitHub用語集

1.4.3 Gitbucket

Gitbucketにソースコードをアップデートします。
他の開発者と共同作業できるのが大きなメリットです。

手順の中の、「公開鍵・暗号鍵」ってなんだろう?
とりあえず言われるがまま作ってみたけどよくわかっていないので、調べてみました。

インターネットを経由してデータのやりとりをする上で、情報が盗まれないようにするために暗号化が必要です。
そのために生まれたのが公開鍵暗号方式です。
この鍵はお互いが対応しています。
・公開鍵で暗号化したデータは秘密鍵(暗号鍵)でしかもとに戻せない
・秘密鍵(暗号鍵)で暗号化したデータは公開鍵でしかもとに戻せない

公開鍵は誰でも見れるようになっています。
データを送信する側は公開鍵で情報を取得、暗号化して送信します。
受信側は誰にも見せていない秘密鍵(暗号鍵)で暗号化された情報を元に戻し、見ることができます。
これで第三者に情報を見られることはありません。

このような方式をとっているため、情報のやりとりのために公開鍵を入れることが必要です。

参考記事
https://railstutorial.jp/chapters/beginning?version=5.1#sec-bundler

1.4.4 ブランチ、編集、コミット、マージ

$ git checkout -b modify-README    #一時的に使うトピックブランチを作成
$ git branch    #すべてのローカルブランチを確認
$ git commit -a -m "Improve the README file"    #すべてのファイルの変更を一括でコミットする
$ git checkout master    #masterブランチへ移動
$ git merge modify-README    #masterブランチにトピックブランチmodify-READMEをマージ
$ git push    #プッシュする

1.5.1 Herokuのセットアップ

HerokuではPostgreSQLデータベースを使う、とありますが、
PostgreSQLってなんだろう...

PostgreSQL は、オープンソースのリレーショナル・データベースです。商用データベ>ースに匹敵する本格的な機能と、オープンソースならではの利用の柔軟度が魅力です。
https://lets.postgresql.jp/map/intro

リレーショナルデータベースは、テーブル型で、関連付けられたデータの集合ということのようです。まだまだ難しい
https://aws.amazon.com/jp/relational-database/

SQLiteを加え、インストールします。

また、Herokuをインストールしてデプロイします。

$ heroku --version    #Herokuがインストールされているかとバージョンの確認
$ source <(curl -sL https://cdn.learnenough.com/heroku_install)    #HerokuをクラウドIDEにインストール
$ heroku login --interactive
$ heroku keys:add
$ heroku create    #Herokuに新しいアプリケーションを作る
$ git push heroku master    #Herokuにデプロイ

ここで1章は終わりです。
ログを載せたかったのですが、デプロイが上手くいきませんでした。
後から考えると、ブランチを作り間違えたのと、Herokuは heroku createで生成されたアドレスからアクセスする必要があるということをいまいち理解していなかったためだと思います。

長くなってしまいましたが、ここまで読んでいただきありがとうございます。
間違いなどありましたら、教えていただけると嬉しいです。

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