20210322のRubyに関する記事は19件です。

フォームに入力した値の重複の確認

写真のようにフォームに入力した値に重複があるのかを、保存前に確認する方法を見つけることができたので記録します。

スクリーンショット 2021-03-22 21.54.52.jpg

ポジションは、f.selectを使用して、選択した値に対応する数字が、
選手名は、f.collection_selectを使用して、対応する選手ID(player.id)が送られるようにしています。

フォームから送られるparamsは、以下のようにタイトル、ポジション、名前が存在します。
(starting,relief,closerは、対応する投手の選手IDが入っています。)
今回は、ポジション選手名に重複がないかを確認します。

{"title"=>"サンプル1",
 "one_position"=>"6", "one_name"=>"11",
 "two_position"=>"4", "two_name"=>"11",
 "three_position"=>"4", "three_name"=>"5",
 "four_position"=>"5", "four_name"=>"14",
 "five_position"=>"3", "five_name"=>"27",
 "six_position"=>"7", "six_name"=>"12",
 "seven_position"=>"9", "seven_name"=>"17",
 "eight_position"=>"8", "eight_name"=>"3",
 "nine_position"=>"2", "nine_name"=>"19",
 "starting"=>"20", "relief"=>"21", "closer"=>"22"}

手順

1.処理しやすいようにポジション選手名を別々の配列に振り分ける
・ 交互にポジションと選手名に振り分けたいが、starting,relief,closerと連続で選手のIDが入っているので、一旦切り分ける
2.ポジションと選手名を分ける。
3.重複の確認

処理しやすいように分ける

field_player = params[:best_nine].values[1..-4] #タイトルと投手情報以外をいれる
pitcher = params[:best_nine].values[-3..-1] #投手の選手IDをいれる

ポジションと選手を分ける

each_slice(n)で、n要素ずつブロックに渡してを繰り返す。
・野手のポジションと選手IDがブロックに渡される([[one_position, one_name],[two_position, two_name], ・・・])
・ブロックの1つ目をポジション、最後(2つ目)を選手名として扱う
Ruby 3.0.0 リファレンスマニュアル
playerには、投手の選手IDを追加する。
・配列に配列をpushで挿入すると、二重配列のような形になるので、flattenを用いて平坦化する
position = field_player.each_slice(2).map(&:first)
# field_player.each_slice(2).map {|n| n.first} と同じ処理
player = field_player.each_slice(2).map(&:last).push(pitcher)
player.flatten!

重複がないか確認

配列の要素の数と、配列内で重複していない要素の数の差が0でなければ、重複した値があると判定します。

if ((position.count - position.uniq.count) != 0 || (player.count - player.uniq.count) != 0)

全てのコード

field_player = params[:best_nine].values[1..-4]
pitcher = params[:best_nine].values[-3..-1]

position = field_player.each_slice(2).map(&:first).push(pitcher) # {|n| n.first}
position.flatten!
player = field_player.each_slice(2).map(&:last)

if ((position.count - position.uniq.count) != 0 || (player.count - player.uniq.count) != 0)

参考記事

Ruby | 配列の奇数番目と偶数番目を取り出す方法
Ruby 3.0.0 リファレンスマニュアル (※each_slice)
Rubyで複数の配列を1つの配列に結合するために色々やってみた
重複した要素を取り除く

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

サインアップview イメージ(自分用)

Sign up

<%= form_with model: @user, url: user_registration_path, class: 'registration-main', local: true do |f| %>

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


<%= f.label :name %>

<%= f.text_field :name, autofocus: true, autocomplete: "name" %>


<%= f.label :email %>

<%= f.email_field :email, autofocus: true, autocomplete: "email" %>


<%= f.label :password %>
<% if @minimum_password_length %>
(<%= @minimum_password_length %> characters minimum)
<% end %>

<%= f.password_field :password, autocomplete: "new-password" %>


<%= f.label :password_confirmation %>

<%= f.password_field :password_confirmation, autocomplete: "new-password" %>


<%= f.submit "Sign up" %>

<% end %>

<%= render "devise/shared/links" %>

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

ログインしているとき(条件分岐)

<% if user_signed_in? %>
A
<% end %>

ログインしているなら、Aを表示させる

<% if user_signed_in? && current_user.id == @tweet.user_id %>
B
<% end %>

ログインしていて、かつあなたのuser.idがそのツイートをしたuserのidと一致していたら(あなたがそのツイートの投稿主なら) Bを表示させる。

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

Devise 導入の流れ

復習も兼ねて

① gem 'devise' をGemfileに記述

② % bundle install

③ % rails s

④ % rails g devise:install

⑤ % rails g devise user

⑥ マイグレーションファイルに必要なカラムなどを記述

⑦ % rails db:migrate

⑧ % rails g devise:views

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

解決!Rubyのバージョンアップに伴うトラブル|rails コマンドが動かない

1. 状況

1) 開発環境にあったプロジェクトをherokuにpushしようとしたところ、ruby のバージョンが 2.6.3 になっているけど、2.6.6 を使用しろと言われた。

2) これは、なんとか解決。その時の戦記はこちら

3) 無事にherokuにpushはできた。

4) しかし、そのあと、rails s しようとしたところ、謎のエラーが出た。

環境
% ruby -v
ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-darwin20]

% rbenv versions
  system
  2.5.1
  2.6.3
* 2.6.6 (set by /Users/randytozuka/.rbenv/version)

% gem -v
3.2.15

エラー文

ターミナル
% rails s            
/Users/randytozuka/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-1.17.2/lib/bundler/rubygems_integration.rb:200: warning: constant Gem::ConfigMap is deprecated
Traceback (most recent call last):
    71: from bin/rails:3:in `<main>'
    70: from bin/rails:3:in `load'
    69: from /Users/randytozuka/Desktop/deskschedule2-master/bin/spring:15:in `<top (required)>'
  (中略)
    2: from /Users/randytozuka/Desktop/deskschedule2-master/vendor/bundle/gems/bootsnap-1.7.2/lib/bootsnap/load_path_cache/loaded_features_index.rb:89:in `register'
   1: from /Users/randytozuka/Desktop/deskschedule2-master/vendor/bundle/gems/bootsnap-1.7.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/Users/randytozuka/Desktop/deskschedule2-master/vendor/bundle/gems/bootsnap-1.7.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require': cannot load such file -- etc (LoadError)

2. 対応

ググってみたところ、先人がこのようなアドバイスを残してくれていた。
・bundle install をしろ
・gem install bundler を試してみろ
・gem を update したら bundler も update せよ
・RubyGemsのバージョンをupdate か downgradeして、bundlerのバージョンと相性のよいバージョンに合わせろ

ターミナル
% gem update --system
Latest version already installed. Done.

% gem update bundler
Updating installed gems
Nothing to update

% gem list rubygems-update
*** LOCAL GEMS ***
rubygems-update (3.2.15)

状況変わらず…(TT)
ここでメンターさんから、これやってみと教えていただいた事をやってみる。

その1
gem uninstall -I -a -x --user-install --force
ERROR:  While executing gem ... (Errno::ENOTEMPTY)
    Directory not empty @ dir_s_rmdir - /Users/randytozuka/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rails-6.1.3

エラーか強い心でスルーする。

その2
gem install bundler
Fetching bundler-2.2.15.gem
Successfully installed bundler-2.2.15
1 gem installed

その3、ここでGemfile.lock を削除して,

その4
% bundle install
% rails s 

どうじゃ!! お?? エラーがちょっと変わった。
ん〜〜〜となったところで,たまたま見た記事 にあった ↓ を試してみる。

ターミナル
% bundle install --redownload

解決! やった!

3. まとめ

丸一日彷徨いました。
今回のトラブルは、ruby 及び rails のバージョンを上げたが、gem がそれについてきていなかったので、もう一回最新の gem のライブラリを読み込んだら解決した…ということだったのかなと。安易にrubyのバージョンあげると大変だよということでいい勉強させてもらいました。

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

Rails API 設定

[API 設定方法]

通常のrails newコマンドの末尾に--apiをつけることでAPIモードでアプリを作成することができる。
(APIに必要ない部分をデフォルトで作成しなくなる。)

--apiをつけない場合

config/application.rbのApplicationクラス定義の冒頭に、次を追加します。

config.api_only = true

app/controllers/application_controller.rbの以下のコードを置き換えます。

class ApplicationController < ActionController::Base
end

上を以下に変更します。

class ApplicationController < ActionController::API
end

routing分割方法

rails6.1からroutes.rbのファイルを複数に分けることができるようになった。

  • ファイル分割する際のディレクトリ構成
  ├─ routes.rb
  │
  └─ routes/ #ここに分割したroutesファイルを格納
     ├─ api.rb
     └─ admin.rb
  • routes.rbの記載を変更

draw(:読み込みたいファイル名)

 Rails.application.routes.draw do

  draw(:api) #別ファイルのルーティングを読み込む
  draw(:admmin) #別ファイルのルーティングを読み込む
end
  • routesディレクトリ&外部ファイルの作成

以下のディレクトリ構成になるようにroutesディレクトリと外部ファイルを作成します。

config
  ├─ routes.rb
  │
  └─ routes/ #このディレクトリを作成
      ├─ api.rb    #外部ファイルを作成
      └─ admin.rb  #外部ファイルを作成
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-compose Rails + Postgresql環境構築

作業ディレクトリと必要なファイルを作成

まず開発していくディレクトリとアプリケーションを構築するために必要なファイルを作成する

必要なファイル


Dockerfile
Gemfile
Gemfile.lock
entrypoint.sh
docker-compose.yml
$ mkdir myapp
$ cd myapp
$ touch {Dockerfile,Gemfile,Gemfile.lock,entrypoint.sh,docker-compose.yml}
$ ls
Dockerfile      Gemfile.lock        entrypoint.sh
Gemfile         docker-compose.yml

ファイルの中身を記述してく

Rails6ではwebpackerが搭載されyarnのインストールが必要

Dockerfile
FROM ruby:2.6.6

RUN 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

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarn
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
Gemfile
source 'https://rubygems.org'
gem 'rails', '6.0.3'
entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

プロジェクトの構築

作成したファイルを利用してdocker-compose runを実行しアプリケーションを生成

$ docker-compose run web rails new . --force --no-deps --database=postgresql

そして

$ docker-compose build
.
.
.
Successfully built 0b14a3eedc73
Successfully tagged myapp_web:latest

imageを構築

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

【Ruby on Rails6.0】データベースを指定してアプリ作成

前提

■あくまで個人の備忘録。見やすは非重視
■PostgreSQLが既にインストールされていること
※されていない場合は以下でインストールとPath設定を完了させる
PostgreSQL インストール方法

Rubyインストール

★以下のサイトからWITH DEVKITの推奨版をダウンロード
※サイト内左側の一覧に「=>」となっているものが推奨

Ruby公式サイト 

★ダウンロードしたファイルで設定を進める
※途中コマンドプロンプトにて入力を求められた場合には、各々指定が無ければ「1,2,3」と入力

★ダウンロードが完了したら、コマンドプロンプトを起動し、バージョンを確認し正常に確認出来たらインストールされている

# コマンドプロンプト
$ ruby -v
# 出力結果
ruby 2.7.2p137(2020-10-01 reversion 5445e04352) [x64-mingw32]

※「$」は入力不要

Railsインストール

■以下のコードを実行し、Railsをインストールする

# コマンドプロンプト
$ gem install rails

■Railsがインストールされたかを確認するために、バージョンを確認

# コマンドプロンプト
$ rails -v
# 出力結果
Rails 6.1.3

Yarnインストール

★以下のコードを実行し、Yarnをインストールする

# コマンドプロンプト
$ npm install --global yarn

★Yarnがインストールされたかを確認するためにバージョンを確認

# コマンドプロンプト
$ yarn -v
# 出力結果
1.22.10

Node.jsインストール

■以下サイトでNode.jsをダウンロード・インストールを実行

Node.js

■システム詳細設定内の環境変数(ユーザ環境変数)にPathを設定

デフォルトの場合の設定:C:\Program Files\Nodejs

■Node.jsがインストールされたかを確認するためにバージョンを確認

# コマンドプロンプト
$ node -v
# 出力結果
v14.16.0

アプリの作成

★コマンドプロンプトで以下のコードを実行

# コマンドプロンプト
$ rails new (アプリ名) -d postgresql

★アプリケーション毎にGemバージョンを管理する場合は以下を実行

# コマンドプロンプト
$ rails new (アプリケーション名) -d postgresql --skip-bundle

★インストール完了後にアプリケーションディレクトリに移動し、以下のコードを実行

# コマンドプロンプト
# 初回のみ以下
$ bundle install --path vendor/bundle

# 2回目以降
$ bundle install

データベースの連携

■psql.exe が保存されたディレクトリをPatchに設定

デフォルトの場合の設定:C¥:Program Files¥PostgreSQL¥(バージョン)\bin

■作成したアプリケーションの以下のファイルを編集
ルート:(アプリケーション名)\config\database.yml

#省略

default: &default
adapter: postgresql
encoding: unicode
username: postgres #デフォルトの場合
password: postgres #デフォルトの場合

#省略

Railsアプリの起動・表示

★cdコマンドでアプリケーションディレクトリに移動

★以下のコードを実行

# コマンドプロンプト
$ rails s

※「Use Ctrl-C to stop」の出力が表示されたらサーバー接続完了

★ブラウザで以下のURLにアクセスし、画像の表示になれば無事設定完了

localhost:3000

qwe.png

★サーバーとの接続を解除する場合は「Use Ctrl-C to stop」と出力された状態のコマンドプロンプトで「Ctrl」+「C」を入力し停止
⇒コマンド入力待機に切り替わったら接続解除完了

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

【Refile】attachment_image_tag の書き方

attachment_image_tagの書き方

<%= attachment_image_tag 保存先インスタンス名, :保存先カラム名, :fill, 幅, 高さ, format:'拡張子', fallback:"代替画像" %>

例えば、
<%= attachment_image_tag post_image.user, :profile_image, :fill, 100, 100, format:'jpg', fallback:"no_image.jpg"

*fillでうまく表示されない場合は、sizeでサイズを指定
:fill, 幅, 高さsize: "幅x高さ"

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

Refileの保存先をS3に変更する(Rails, AWS)

環境

  • Ruby 2.6.3
  • Rails 5.2.4

[IAM]ユーザー作成

IAMのダッシュボードでユーザーを選択し、ユーザーの追加をクリックします。
ユーザー名を入力AWSアクセスの種類を選択プログラムによるアクセスを選択肢、次へ

スクリーンショット 2021-03-22 12.30.07.png

既存のポリシーを直接アタッチを選択後S3で検索AmazonS3FullAccessを選択し、次へ
ユーザー登録は完了させ、.csvダウンロードする。
access_key secret_access_keyが書いてあるので忘れないように保管する。

(IAM)ユーザーのポリシーの追加

[S3]バケットポリシーの編集

S3に入ってバケットの選択し、アクセス許可のタブをクリック
バケットポリシーを編集するをクリックし、下のコード追加します。
AWSアカウントのidは右上の自分の名前をクリックし、マイアカウントの数字です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::awsアカウントのid:user/IAMで作成したユーザー名""
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::バケット名/*"
        }
    ]
}

refile.rbを作成

$ touch config/initializers/refile.rb
config/initializers/refile.rb
require 'refile/s3'

#if !Rails.env.production? # 開発環境でS3へアップロードできているか確認する方法

if Rails.env.production? # 本番環境の場合
  aws = {
    access_key_id: ENV['S3_ACCESS_KEY_ID'], # アクセスキーID
    secret_access_key: ENV['S3_SECRET_ACCESS_KEY'], # シークレットアクセスキー
    region: 'ap-northeast-1', # リージョン
    bucket: 'S3バケット名',
  }
  Refile.cache = Refile::S3.new(prefix: 'cache', **aws)
  Refile.store = Refile::S3.new(prefix: 'store', **aws)
end

Refile.cache Refile.store残っていると本番環境で反映されなかったので
エラーになる方は消した方がいいです。

.env
AWS_ACCESS_KEY_ID="アクセスキー"
AWS_SECRET_ACCESS_KEY="シークレットキー"
Gemfile
gem "refile-s3"

bundle installでgemを入れます。
本番環境にも同じように反映させたら完成です。

参考になった記事です
https://qiita.com/matsubishi5/items/c2abdd7375a4c683392a
https://qiita.com/piyor/items/36d2c3c9b8fd638a71a0

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

Rails 検索機能 ransack

ransackを使って検索機能を実装する

gem 'ransack'

ビューファイルに表示するフォームの作成
@pというのはコントローラーで作成するオブジェクトです。
urlについてはコントローラー、ルーティングに記述して、resultアクションを作成。

<%= search_form_for @p, url: result_rooms_path do |f| %>
      <div class="search-select">
            <div class="search-select__container">
              <%= f.label '性別', class: "search-select__container__label" %>
              <%= f.collection_select :user_sex_id_eq, Sex.all, :id, :name, {disabled: 1, include_blank: '指定なし'}, {class: "search-select__container__list"} %>
            </div>

            <div class="search-select__container">
              <%= f.label 'お部屋の場所', class: "search-select__container__label" %>
              <%= f.collection_select :place_id_eq, Place.all, :id, :name, {disabled: 1, include_blank: '指定なし'}, {class: "search-select__container__list"} %>
            </div>
      </div>
<% end %>

collection_selectの中身について

引数 役割
1. メソッド名 :place_id_eq カラム名、name属性やid属性を決める
2.オブジェクト Place.all アクティブハッシュを指定する
3.value :id 表示する際に参照するDBのカラム名
4.name :name 実際に表示されるカラム名
5.オプション include_blank: 何も選択していない時に表示される内容

disabled: 1はその値を無効にするオプションです。
controllerを記述する

 def result
    @rooms = @p.result.includes(:user).limit(20).order(updated_at: "DESC")
 end



 privata
    def result_rooms
    @p = Room.joins(:user).ransack(params[:q])
  end

キー情報である[:q]によってRoomテーブルからデータを探してオブジェクトを生成する。
そしてresultアクション内で@roomsに検索結果を代入している。
.resultで取得することができる。

またresult_roomsでDBからレコードを取得する際に、joinsでテーブル同士を内部結合して検索できるようにしています。
紐づいているユーザー情報からも検索できるようにしています。
そしてresult.html.erbを編集。
コントローラー内で記述した@roomsに対して繰り返し処理を行なって、ビューページに表示をしていきます。

views/rooms/result.html.erb
  <% rooms.each do |room| %>
     <div class="rooms-item__card">
       <%= link_to room_path(room.id), class: "link-cover" do %>
         <h4 class="rooms-item__card__title"><%= room.title %></h4>
         <p class="rooms-item__card__user"><%= room.user.name %></p>
             <div class="rooms-item__img">
               <%= image_tag room.image %>
             </div>
       <% end %>
     </div>
  <% end %>

以上がポートフォリオで作成したransackを用いた検索ページの実装でした。ポートフォリオはまた別記事で公開いたします。
ありがとうございました。

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

エラ〜メッセージ

エラーメッセージの日本語化の実装
app/modelsにて

with_options numericality: { other_than: 1 } do
validates :category_id
validates :status_id
validates :cost_id
validates :prefecture_id
validates :by_send_id
end

と記述。するとこのように表示される。

しかしこのままでは下5つの「1以外の値を入力してください」の部分がユーザー視点だと分かりづらい。

そこで

with_options numericality: { other_than: 1, message: 'を選択してください' } do
validates :category_id
validates :status_id
validates :cost_id
validates :prefecture_id
validates :by_send_id
end

このように変更。

すると

これで分かりやすくなった。

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

コントローラー 単体テスト実装

今回詰まった内容を備忘録のためと、知識定着させるためアウトプット!

現在ポートフォリオで簡単な画像付きの投稿サイトを作成中、コントローラーの単体テストを行っておりました。

indexアクションにリクエストするとレスポンスに投稿済みの画像が存在する

上記テストだけがどうしてもうまくいかず、進まなかった状況です。

開発フレームワークはrailsを使用しており、
RSpec FactoryBot
は導入済みの状態です。

エラー内容

TypeError:
       no implicit conversion of ActiveStorage::Attached::Many into String
     # ./spec/requests/posts_spec.rb:19:in `block (3 levels) in <top (required)>'

ソースコード

posts_spec.rb

equire 'rails_helper'
describe PostsController, type: :request do
  before do
    @post = FactoryBot.create(:post)
  end

  describe 'GET #index' do
    it 'indexアクションにリクエストすると正常にレスポンスが返ってくる' do 
      get posts_path
      expect(response.status).to eq 200
    end
    it 'indexアクションにリクエストするとレスポンスに投稿済みのテキストが存在する' do
      get posts_path
      expect(response.body).to include(@post.name)
    end
    it 'indexアクションにリクエストするとレスポンスに投稿済みの画像が存在する' do
      get posts_path
      expect(response.body).to include("@post.images")
    end
    it 'indexアクションにリクエストするとレスポンスに投稿検索フォームが存在する' do
      get posts_path
      expect(response.body).to include('')
    end
  end
end

posts.rb

FactoryBot.define do
  factory :post do
    name { '投稿名' }
    post_text { '投稿文' }
    association :user

    after(:build) do |post|
      post.images.attach(io: File.open('public/test_image.png'), filename: 'test_image.png')
    end
  end
end

上記の記述で行っていました。
どうしても画像の確認だけができず、つまずいていたという状況でした。

エラーログから考察するに、画像がstring(文字列型)になっているため確認が取れないよと認識する。

そのためbinding.pryを入力してターミナル上で情報の確認
response.body
@post
@post.images
@post.images.blobs

上記全てをターミナル上で確認して、正常に画像がある事を把握する。

画像があるのに対して、string(文字列)になってしまっているエラーのためなぜかを考察する。

そこで、

include("@post.images")

上記の記述の仕方が行けないのではないかと仮説を立てる。

画像情報を取得しているname属性の値を入れてみた。

include("post[images][]")

上記に変更してみたが、同様のstring(文字列)のエラーが出ている。

それでエラーが出るのであれば、直接画像のimg属性のクラス名を指定するやり方で再度実行する

include("item-box-img")

上記コードで出力を行う。

そうしたらテストが成功した。

エラーの原因で文字列になってしまっているというところに着目し、修正を加えて行ったのがエラー解読につながったとみている。

未だ一点だけ不明点があり、
なぜ画像を指定する際に、その画像のname属性ではなく、クラスを指定しなくては行けないのかという点が不明であった。

同じ指定方法をしているのになぜなんだろうと思っている。

参考記事等も見つからず、もしご教授いただけるようでしたら、コメントいただけましたら助かります!

今回はコントローラー単体テストで画像確認のテストをする際におきたエラーでした。

同じようなエラーで迷われている方いましたら、是非ご参考にして頂けましたら幸いです!

宜しくお願いします!

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

Chef で Ruby 2.4 を使っていて依存関係を解決した話

Chef で Ruby 2.4 を使っていて依存関係を解決した話

td-agent Ruby
v4 2.7
v3 2.4

起こったこと

       STDERR: ERROR:  Error installing fluent-plugin-bigquery:
        signet requires Ruby version >= 2.5.

chef でインストールバージョンを特に変更していないのに,fluent-plugin-bigqueryのインストールができなくなった.
Error は,requires Ruby version >= 2.5
確かに,今の td-agent の Ruby version は 2.4 なので満たせていないが,今までインストールできていた.

Require (Ruby) version を確認する

依存関係を確認する

例えば,1つの gem の require を確認するのは簡単だが,そこに至るrequire tree を確認しておかないとどういう解決をするか検討しにくい.

とりあえず,これは Require 2.5 なので無理.

検索してみたところ依存関係を再帰的に辿ってくれれるツールがあるらしい.

http://rubygems.org/https://rubygems.org/ にするだけで動く

どういう依存ツリーでそのパッケージ(Ruby 2.5 以上を必要としているかはこれでわかる)

required バージョンを確認する

$ ruby depsearch.rb fluent-plugin-bigquery | grep signet | sed -e 's/^ *//' | uniq
signet ~> 0.14

version 0.14.1 → 0.15 で変更になっている.

バージョン 説明
~> x.0 x.1からx.9は良いが、メインのバージョンがあがるとは不可。例えば、3.2は良いが、4.0は不可など

対応する

シンプルには,td-agent パッケージを v4 にすれば Ruby 2.7 になってOK そうだが,
td-agent パッケージを上げるのが少し面倒だった.
(td-agent が v4 に対応していないというのもある)

v3 のまま何かできないかと考えて,先に必要なgem をインストールしておけばrequired が満たされて新しいバージョンをインストールしようとしないだろうという想定.

$ gem install signet -v=0.14.1

大丈夫そうでした.

その他

バージョンチェックのツリーをバージョン指定して確認できるといいかも.
あと Ruby のバージョンのチェックも可能にしてもいいかもな.と思った.

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

devise

ウィザード形式のdevise

% rails g devise:controllers users

ルーティング(例)

Rails.application.routes.draw do
devise_for :users, controllers: {
registrations: 'users/registrations'
}
root to: "home#index"

end

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

Bundlerについて

はじめに

初学者です。間違いあればご指摘いただきたいです。

参考

Bundler概要
Bundlerの使い方
Bundlerとは?

Bundlerとは?

  • プロジェクト内で使うRubygemsを管理する仕組みのこと。

  • gemは手動で個別にインストールする事ができる。が、様々なgemを組み合わせて使っていくと「バージョンの組み合わせ」によっては上手くいかないなどの問題が出てくることがある。

  • 複数人、複数環境で開発を行う場合、各々の環境で使うライブラリの名前やバージョンを合わせる必要がある。

  • 上記2点の問題を解決できるのがBundler。
    手動でgemをインストールするよりも、gem同士の互換性を保ってくれるBundlerでインストールする方が便利。

Bundlerのインストール

まず初めに、Bundlerもgemの1つです。
つまり、インストールの必要があるってことですね。

  • Bundlerは手動インストールします。
ターミナル
gem install bundler
  • 導入されたか確認します。バージョンが表示されるかを確認してください。
ターミナル
bundler -v

Bundlerの使い方

  • Gemfileを作る
ターミナル
bundle init

上記のコマンドでGemfileの雛形が作成されます。

  • 使いたいgemをGemfileに記述する  
    • インストールしたいGemパッケージを記述後、bundle installを実行することで、自動的に調べて全部インストールしてくれます!

Bundlerのコマンド

  • bundle init ・・・・Gemfileを生成する
  • bundle install・・・Gemfileに書かれたGemパッケージをインストール
  • bundle exec・・・・Bundlerでインストールされたgemパッケージを使用してコマンドの実行
  • bundle list・・・・・インストール済みのgemパッケージの一覧を表示
  • bundle update・・・インストール済みのgemパッケージのバージョンを更新

Gemパッケージの保存先

bundle installと実行すると、
rbenvを利用していた場合、/Users/ユーザー名/.rbenv/versions/バージョン名/lib/ruby/gems/...に保存されます。

もしこの保存先を変更したい場合、

ターミナル
bundle install --path <フォルダ名>

と打つと、指定したフォルダの下に保存することが可能です。

ちなみに2回目以降は、保存先を記憶してくれているので % bundle install と打つだけで大丈夫です。

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

formの値をコントローラに送る 基本

フォームから送られた値を受け取るには

ルーティングの修正


post "move" => "users#move"

アクションの追加

`
def move

end
`

erbにフォームの送信先を修正


<%= form_tag("/move") do %>
<p>メールアドレス</p>
<input name="email">
<p>パスワード</p>
<input type="password" name="password">
<input type="submit" value="移動">
<%= end %>

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

link_to form_tag form_for の違い

link_to

getのコントローラーを探しに行く

<%= link_to("移動", "/move") → get "move" => "users#move_form"

form_tag

postのコントローラーを探しに行く

<%= form_tag("/move") do %> → post "move" => "users#move"

form_for

<%= form_tag("/move") do %> 
  <p>メールアドレス</p>
  <input name="email">
  <p>パスワード</p>
  <input type="password" name="password">
  <input type="submit" value="移動">
<%= end %>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】pluckメソッドのソースコードを読んでみた

アプリケーション作成時に使用した「pluck」メソッドについて、便利な機能だと思っていましたが、どのように処理をしているのか気になったのでRailsのソースコードを読んでみました。

pluckとは

公式ドキュメントでは以下のように記載されています。

pluckは、1つのモデルで使用されているテーブルからカラム (1つでも複数でも可) を取得するクエリを送信するのに使用できます。引数としてカラム名のリストを与えると、指定したカラムの値の配列を、対応するデータ型で返します。

例えば、Productモデルがあったとして、nameカラムの中身を確認したい場合は、

Product.pluck(:name)
=> ["Ruby on Rails Tote",
 "Ruby on Rails Bag",
 "Ruby on Rails Baseball Jersey",
 "Ruby on Rails Jr. Spaghetti",
 "Ruby on Rails Ringer T-Shirt",
 "Ruby Baseball Jersey",
 "Apache Baseball Jersey",
 "Ruby on Rails Mug",
 "Ruby on Rails Stein"]

といったようにProductモデル内のnameカラムを一覧表示することができます。

Product.pluck(:id,:name)
=> [[1, "Ruby on Rails Tote"],
 [2, "Ruby on Rails Bag"],
 [3, "Ruby on Rails Baseball Jersey"],
 [4, "Ruby on Rails Jr. Spaghetti"],
 [5, "Ruby on Rails Ringer T-Shirt"],
 [6, "Ruby Baseball Jersey"],
 [7, "Apache Baseball Jersey"],
 [8, "Ruby on Rails Mug"],
 [9, "Ruby on Rails Stein"]]

このように第二引数を設定することも可能です。

pluckの処理内容と、第二引数を設定した場合の処理がどのように行われているか気になったので、ソースコードを見てみることにしました。

Railsのソースコード

rails/activesupport/lib/active_support/core_ext/enumerable.rb
def pluck(*keys)  
  if keys.many?  
    map { |element| keys.map { |key| element[key] } }  
  else  
  key = keys.first  
    map { |element| element[key] }  
  end  
end

実際に読んでみる①

まず、引数が一つのケースで考えてみます。

[{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)  
# => ["David", "Rafael", "Aaron"]
def pluck(*keys)  
  if keys.many?  
    map { |element| keys.map { |key| element[key] } }  
  else  
  key = keys.first  
    map { |element| element[key] }  
  end  
end

一行目
(*keys)に、:nameが配列として格納されます。

pluck(*keys): *をつければ引数を複数個設定できる。(可変長引数)  引数は配列として受け取られる。

二行目
keys.many? → 今回、keysは一つだけなのでスルー

many? → 条件を満たす要素が 2 つ以上ある場合に true。

五行目
keysの配列で、最初の要素(:name)を、keyに格納

六行目

[{ name:  "David"  },  { name:  "Rafael"  },  { name:  "Aaron"  }]

上記の配列をmapメソッドでそれぞれ、key に関連づけられた値を抽出。その後、配列として出力した結果、

=> ["David", "Rafael", "Aaron"]

nameカラムの要素のみ表示できました。

実際に読んでみる②

次に、引数が2つ以上のケースで考えてみます。

[{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name)  
# => [[1, "David"], [2, "Rafael"]]
def pluck(*keys)  
  if keys.many?  
    map { |element| keys.map { |key| element[key] } }  
  else  
  key = keys.first  
    map { |element| element[key] }  
  end  
end

一行目
(*keys)に、:id, :name が配列として格納されます。

二行目
keysが、2つ以上なのでそのまま進みます。

三行目

[{ id: 1, name: "David" }, { id: 2, name: "Rafael" }]

まず、上記の配列からmapメソッドで、keys → (:id, :name) に関連づけられた要素を抽出。
そこからさらに、mapメソッドを使って配列の要素それぞれに、上記の処理を行う。

その後、配列として出力した結果、

=> [[1, "David"], [2, "Rafael"]]

idカラムとnameカラムの要素を表示することができました。

終わりに

ソースコードのどこを読めばいいのかとか、おろそかにしてきた基礎文法の知識の足りなさが露呈したりと、たったこれを読むだけでもかなり苦戦しました。
ただ、今まで公式ドキュメント読んでも、「...?」だった内容が事細かに書いてある(当たり前)ので、ソースコードで確認することで、どういう仕組みか納得して進められるなと思った次第です。
これからも、誰かのソースコードを読むことは必須になってくるので、気になったメソッドとかがあったらソースコードを見てみる癖を付けておきたいなと思うのでした。

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