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

[Rails] [メモ] <% %>に=をつける時とつけない時

この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。
ヘルパーメソッドをビューファイルで記述する時、ふとした瞬間に<% %>の=をつけるかつけないかで間違ってしまうので、忘備録として書きました。

<% %>の場合

  • ビューファイルで出力させたくない時に使います。
  • 例えば、if文などの条件分岐やeach文の繰り返し処理の時などです。
#if文
<% if @name == 'hoge' %>
<% end %>

#each文
<% @books.each do |book| %>
<% end %>

<%= %>の場合

  • ビューファイルで記述した処理を出力させたい時に使います。
<%= book.title %>

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

<%= f.label :email %>

<%= render 'shared/error_messages' %>

まとめ

ざっとまとめると<%= %>方が圧倒的に多いですね。
要するに、ifなどの条件分岐やeachのような繰り返し処理は=をつけないで、その他の画面に出力する処理はつけても良いということです。

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

Rails で検索機能を作ろう(ransack)

はじめに

今回はransackというgemを使って検索機能を作っていきます。ransackは少ないコードで複雑な検索機能を簡単に作れるgemでとても便利です。また、ransackではソート機能も簡単に作れるのでそれも含めて作成していきます。

基本的な検索結果の実装

今回検索の対象とするのは、ストレッチ(stretchsテーブル)一覧と、そのカテゴリ(categoriesテーブル)一覧とします。
ストレッチ一覧画面(indexビュー)に検索窓を設けます。

gemをインストール

gem 'ransack';

bundle installでインストール

ビュー

ストレッチのindexビューに検索窓をつける

<div class= serch.id>
      <%= search_form_for @q, class:'form-inline' ,url: stretchs_path do |f| %>
        <%= f.search_field :action_muscles_or_name_cont, class: 'form-control input-lg', placeholder: "ストレッチ名や筋肉名を入力" ,data: {"turbolinks" => false}%>
        <%= f.submit "検索", class: "btn btn-success btn-lg" %>
      <% end %>
</div>

cssで調整

.form-inline .form-control {
    display: inline-block;
    width: 80%;
}

コントローラー

class StretchsController < ApplicationController
  def index
    # 検索機能(検索ワードをparams[:q]で受け取り@stretchsに入れる)
    @q = Stretch.all.ransack(params[:q])
    @stretchs = @q.result(distinct: true).page(params[:page])
  end
end

検索ワードをparams[:q]で受け取り、検索で該当したデータをそれぞれ@stretchsに入れ、
再びindexビューに返す形です。

以上で簡単な検索機能の実装は完了です。

最後に

今回はransackを使って検索機能を作成しました。
間違っていたりするところがあればご教授お願いします。

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

RailsのActive Storageで、アップロード前に画像を圧縮する

概要

Active StorageでAmazon S3等に画像を保存するような場合に、圧縮してから画像をアップロードする。

実装

saveする前に、添付画像(ActionDispatch::Http::UploadedFile)のtempfileを圧縮したものに置き換える。

モデル
class Event < ApplicationRecord
  has_many_attached :images
end
ビュー
<div class="form-group">
  <%= f.label :images %>
  <%= f.file_field :images, multiple: true, class: 'form-control-file' %>
</div>
圧縮&保存
@event.images.each do |image|
  image.tempfile = ImageProcessing::MiniMagick.source(image.tempfile).resize_to_fit(1280, 1280).call
end
@event.save
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ruby on rails でのアプリの作り方(環境構築はできているものとします)

ターミナルにて、「cd 〜」でアプリ作成したいディレクトリを選択する。
rails _ 6.0.0 _ new (作成したいアプリ名) -d mysqlを入力すると「create 〜」がたくさん出た後に「Webpacker successfully installed」が表示されれば成功です。
rails newはrubyのフレームワークであるrailsがWebアプリケーションに必要なファイル一式を作成してくれるコマンドです。

もしエラーが表示された場合は、
「bundle config --delete build.mysql2」
「bundle config --global build.mysql2 --with-opt-dir="$(brew --prefix openssl)"」
「cd ~(作成したアプリ名)」
「bundle install」と順番に入力すれば大丈夫だと思います。

cd (作成したアプリ名)を入力すればそのアプリのディレクトリに移動し、ライブラリの追加などを行えます。

その後、VSCodeなどで(作成したアプリ名)のconfig/database.ymlの14行目くらいに「encoding: utf8mb4」と記述されていると思います。
「utf8mb4」の「mb4」を消し、「encoding: utf8」にします。
ターミナルに移動し、rails db:createを入力すると
「Created database '(作成したアプリ名)_development'」
「Created database '(作成したアプリ名)_test'」の二つが表示されていると思います。
rails sと入力した後、webにて「localhost3000」と入力すると「Yay! You’re on Rails!」の下に、地球に乗った世界各国の人たちがいるイラストが表示されていたら成功です。

初学者なので間違いなどあればご指摘いただけるとありがたいです。

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

[プログラミング大全] §5 Rubyでレビュー管理アプリを作る

目的

 「プログラミングを学ぼう!!」と意気込んだものの、
プログラミングって難しそうだし、英語も読めないし、PC操作自体苦手だし、
昔に挫折したし、というあなたに向けて、
この記事を読み・PCを動かすだけで「なんだ!プログラミングって面白いじゃん!」
って思ってもらうのが目的です。

プログラミング大全というタイトルで連載化していきたいと考えています。

開発環境

  • Mac:macOS10.15.7(メインPC)
  • ブラウザ:Google Chrome
  • テキストエディタ:VSCode(Visual Studio Code)

準備

  1. デスクトップに「revew.rb」というフォルダを作ります。
  2. VsVodeを立ち上げて、「⌘+O」でrevew.rbを開く

完成形

まず、今回の完成形ですがターミナル上で以下の内容が確認できることです。

$ ruby review.rb #以下の内容が表示されれば成功です。
ジャンル:漫画
---------------------------
タイトル:ワンピース
---------------------------
感想:
国民的漫画。

毎週の連載が待ち遠しい。

伏線がすごい!

---------------------------

バックスラッシュ記法

バックスラッシュ記法とは\(バックスラッシュ)から始まる記法です。
以下の使い方が可能です。

 記法   意味 
 \n   改行 
 \t   タブ 
 \b   バックスペース 
 \ \   バックスラッシュ 

バックスラッシュ記法は""(ダブルコーテーション)の中で記述します!

\nの記述例です。

puts "①日本の都市は東京です。イギリスの首都はロンドンです"
puts "②日本の都市は東京です。\nイギリスの首都はロンドンです"

ターミナルでは以下の様に確認できます。

①日本の都市は東京です。イギリスの首都はロンドンです
②日本の都市は東京です。
イギリスの首都はロンドンです

では、\nを用いて本格的に実装を進めていきましょう!

STEP1:画面上に文字の表示

putsメソッドを用いて表記

まずは、putsメソッドを使って完成形を表記します。

review.rb
puts "ジャンル" + ":" + "漫画"
puts "---------------------------"
puts "タイトル" + ":" + "ワンピース"
puts "---------------------------"
puts "感想" + ":\n"
puts "国民的漫画。\n\n"
puts "毎週の連載が待ち遠しい。\n\n"
puts "伏線がすごい!\n"
puts "---------------------------"

*上記はあくまで記述方法の1つです。
ターミナルで確認します。

$ ruby review.rb #以下の様に表記されていれば成功です。
ジャンル:漫画
---------------------------
タイトル:ワンピース
---------------------------
感想:
国民的漫画。

毎週の連載が待ち遠しい。

伏線がすごい!

---------------------------

しかし、このソースコードではputsメソッドが大量に使われ非常に見にくいままです。
前回学習した変数を用いて読みやすくしましょう!

変数を用いて表記

以下の様に変数を用いて記述していきます。

review.rb
#変数
genre = "漫画"
title = "ワンピース"
review = "国民的漫画。\n\n毎週の連載が待ち遠しい。\n\n伏線がすごい!"
line = "---------------------------"

puts "ジャンル" + ":" + genre
puts line
puts "タイトル" + ":" + title
puts line
puts "感想" + ":\n"
puts review
puts line

*上記はあくまで記述方法の1つです。

式展開を用いて表記

ここまで文字連結は+を使って表記してきましたが、
式展開を使えばより綺麗にまとめることができます。

式展開

 文字列の中で式を使い、式によって得られる文字列に含めることができます。
書き方は#{式}です。

式展開をする場合は""(ダブルコーテーション)を記述することを忘れてはいけません。

式展開の記述例です。

num = "5"
city = "東京"

puts "3 + 2 の答えは#{num}です"
puts "の本の首都は#{city}です"

ターミナルでは以下の様に表示されます。

3 + 2 の答えは5です
の本の首都は東京です

では、review.rbを書き換えていきましょう!

review.rb
#変数
genre = "漫画"
title = "ワンピース"
review = "国民的漫画。\n\n毎週の連載が待ち遠しい。\n\n伏線がすごい!"
line = "---------------------------"

puts "ジャンル : #{genre}\n#{line}"
puts "タイトル : #{title}\n#{line}"
puts "感想: \n#{review}\n#{line}"

以上です!
最初のコードと比べかなり簡潔にまとめられました。

備考

───────────────────────────────
■著者おすすめの本
───────────────────────────────

「プロになるためのWeb技術入門」

「転職の思考法」

「ハイパワーマーケティング」

「嫌われる勇気」

「アウトプット大全」

───────────────────────────────
■著者おすすめの映画
───────────────────────────────

「マイ・インターン」

「シン・ゴジラ」

「ドラゴンボール超 ブロリー」

「School of Roc」

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

指定したいURLから直接ルーティングを作成する方法+α

こんばんは
アロハな男、やすのりです!

今日はポートフォリオ作成時にルーティングの記述方法について、悪戦苦闘してしまったので同じことで悩まれている方や、自分が忘れた時用の備忘録として書き留めておこうと思います。

長くなりましたので、先に結論だけ載せておきますね。

結論

検索用のボタンを押した際に移動するページのURLを、コントローラーの管理下にしたくない場合は、

config/routes.rb
Rails.application.routes.draw do

    get '/:name', to: 'コントローラー名#edit' 

end

で、大丈夫です!!

↓参考ページはこちら
Railsドキュメント ルーティング
【ルーティング設計】1つのアクションで複数のビューを切り替えて表示する方法

それじゃあ、下に詳しく書き連ねていきますね。

状況

トップページから『ホテル』と書かれたボタンを押すとホテルカテゴリーの検索ページへ遷移する機能を作成したかったんですが、URLをlocalhost:3000/hotelという形にしたかったので、まずはコントローラーをそれぞれ別に作成してルーティングに記述してみました。

config/routes.rb
Rails.application.routes.draw do

    resources :hotels, only [:index]

end

そうすると、
hotels GET /hotels(.:format) hotels#index
というルーティングが作成されました。

これだとURLは希望に近い形で実現はできましたが、項目が多くなればなるほど別途コントローラーを作成しないといけません。

と、いうことは呼び出されるコントローラーを変更すればいいんだ!と思い

config/routes.rb
Rails.application.routes.draw do

    resources :hotels, only [:index], controller: 'experiences'

end

こうすれば、アクセスした時にexperiencesコントローラーのindexアクションが呼び出される様になるので、viewファイルはテンプレートファイル等を利用することで表示することができると思いますが、この場合は何も記述のないhotelsコントローラーが出来上がってしまいます。
今回は1つで記述していますが、どんどん項目が増えればその分ルーティングの記述も多くなってファイルも増えていってしまいます。

どうしたものか...と思っていろいろ調べていると見つけました!!
まずは、URLを指定のものにしたいなら

config/routes.rb
Rails.application.routes.draw do

    get '/hotel', to: 'experiences#index'

end

と記載するだけで大丈夫でした!!

これは、Railsドキュメントのルーティングページに記載がされていました。

しっかりドキュメントを確認することの大切さを改めて実感しました...

さて、これだけでも当初の目標である『URLをlocalhost:3000/hotelにする』というのは完了していますが、今のままだとページが/hotelだけじゃなく他の項目も増えた時にどんどん記述が増えていってしまいますね。
せっかくなので、こちらも改善しちゃいましょう!!

改善後

experiencesコントローラーeditアクションというものを新たに定義してそこに全てのルーティングがいく様にまとめることができるんです!!

controllers/experiences_controller.rb
class ExperiencesController < ApplicationController

  def edit
    render "/#{params[:name]}"
  end

end

config/routes.rb
Rails.application.routes.draw do

    get '/:name', to: 'experiences#edit'

end

また、URLの/:nameという部分では、リクエストの送信時にparams内のキーに:nameを設定して部分テンプレートのファイル名をバリューとして渡すことで、editアクション内のrenderメソッドで該当するビューファイルを表示させています。

今回の経験を経て

公式ドキュメントを読むことの大切さや、先人の方が残して下さった文献のありがたみが身に染みます...

これからも何か問題があれば、どんどん調べていきたいと思います!!
(他力本願な感じもするけど大丈夫かな...)

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

Rails学習 2日目

Ruby on Rails5速習実践ガイド chapter4

4-2-1 データ型

データベースのカラムにはそれぞれデータ型というものが必要になってくる。
データ型というのはその中に入る値を特定の条件付きで指定するものである。

データ型 説明
:boolean 真偽値
:integer 符号付きの整数
:float 浮動小数点数
:string 文字列(短い)
:text 文字列(長い)
:date 日付
:datetime 日時

それぞれのカラムに上記のデータ型を付け加えることで中に入るデータを区別する

4-2-2 NOT NULL制約

カラムは値のない場合NULLとして値を設定しテーブルとして保存するがNOT NULLを使うことによってカラムには必ず何らかの値が入ることを指定することができる。

・NOT NULL制約のかけかた
NOT NULL制約には2種類のかけ方がある。1つ目がテーブルを作成する時に制約をつける方法。2つ目がテーブルを作成し終わってから制約を付け足したい時の制約をつける方法である。

1.テーブルを作成する時に制約をつける方法
テーブルを作成するためのマイグレーションファイルにそのままNOTNULL制約をかけてしまってからdb:migrateしてテーブルを作成する方法

db/migrate/XXXXXXXXXX_create_tasks.rb
class CreateTasks < ActionRecord::Migration[5.2]
 def change
  create_table :tasks do |t|
   t.string :name, null: false
   t.text :description
...

nameの部分は何か値がないと困るのでnameの後ろにnullをつける。
その後ろにnull(空白)でもいいならtrue,空白が嫌(NOTNULL)ならfalseをつける

2.テーブルを作成し終わってから制約を付け足したい時の制約をつける方法

$ bin/rails g migration ChangeTaskNameNotNull

テーブルはもう作ってしまったのでマイグレーションファイルを変更しても意味がない。なので変更用のマイグレーションファイルを作りそこに変更用のコードを書く

db/migrate/XXXXXXXXXXXX_change_tasks_name_not_null.rb
class ChangeTaskNameNotNull < ActionRecord::Migration[5.2]
 def change
  change_column_null :tasks, :name, false
 end
end

できた変更用マイグレーションファイルにchange_column_null(カラムをnullにchangeする)を使ってタスクを変更する。
change_column_null :タスク名, :カラム名, :trueかfalseか(trueはnull、falseはnotnull),

文字列カラムの長さを指定する       (changeメソッド と upメソッドdownメソッド)

文字列の長さを指定するには上記の説明である通り、テーブル作成のマイグレーションファイルに情報を追加するか、情報が決まってしまったテーブルに情報追加のためのマイグレーションファイルを作るかのどちらかである。今回は情報が決まってしまったテーブルに情報追加のためのマイグレーションファイルを作る方法を見てみる。

class ChangeTasksNameLimit30 < ActionRecord::Migration[5.2]
 def up
  change_column :tasks, :name, :string, :limit: 30
 end
 def down
  change_column :tasks, name, :string
 end
end

今回はchangeメソッドの代わりにupメソッドとdownメソッドが書かれているところに注目する。本来changeメソッドは上のupメソッドとdownメソッドを合わせて作られるメソッドである。なぜ今回changeメソッドを二つに分けたかというと、答えは[change_column]にある。change_columnをchangeメソッドで使うと何かあった時に元に戻せなくなるのだ。バージョンを戻す時には上げたバージョン(upやchange)を見ながらそれと逆の操作をしてバージョンを戻す。しかしchangeメソッドだとそれがうまくいかないのである。

4-2-4 ユニークインデックスを作成する

ユニークインデックスも上記のようにテーブル作成のマイグレーションファイルか追加変更用のマイグレーションファイルに書かれる。

class AddNameIndexToTasks < ActiveRecord::Migration[5.2]
 def change
  add_index :task, :name, unique: true
 end
end

ユニークインデックスをつけると値(この場合はname)の重複が無くなる(被らなくなる)

4-3-6 オリジナルの検証コードを書く       (自分でvalidatesを作る)

app/models/task.rb
validate :validate_name_not_including_comma

まず自分で作ったvalidateの名前をvalidateに入れる。

app/models/tasks.rb
private

def validate_name_not_including_comma
  errors.add(:name,'にカンマを含めることはできません') if name&.include?(',')
end

自分の作ったvalidateの内容をprivateメソッドのなか(外部からいじられたらダメなので)で定義。
if name&.include?(',') もしカンマがついた名前があると普通に実行するがカンマがない名前になると結果はnilになりエラーが出てしまう。ぼっち演算子ならnilが出てエラーにならずにnilという言葉だけ出てくる。

4-5-1 セッション

セッションがあることによってどんなページへ何回とんでも自分が操作しているという状態は保たれる(ログイン状態になる)

session[user_id] = @user.id

@user.id = session[user_id]

上がセッションに情報を入れる操作。下がセッションの値を取り出す操作になっている。

4-5-2 Userモデルを作る(password-digest)

password-digestを使うとパスワードが暗号化されパスワード漏洩や不正アクセスの心配が無くなる
password-digestを対応させるにはhas_secure_passwordというコードを書くと使えるようになる。

app/models/user.rb
class User < ApplicationRecord
  has_secure_password
end

モデルにhas_secure_passwordをかく。そうするとpasswordカラムの下にpassword_confimationというカラムができる。これはパスワード確認のために2回入力させるためのやつ。この2つのパスワードがpassword-digestで暗号化された時に一致しているかどうかで判断する。

4-5-8 ログイン情報の取得を簡単にする

User.find_by(id:session[user_id])

今セッションしているidを探すというコードのなのでログインをしていればこのコードでログインしているユーザーを特定できる。
これをApplicationControllerのなかでメソッドとして定義してやるとどこのアクション内でもUser.find_by(id:session[user_id])が働き、ログインしているという情報がついてくる。
なので新しくメソッドを作る

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

 private

 def current_user
   @current_user||=User.find_by(id:session[user_id]) if session[:user_id]
 end
end

「もし@current_userが機能しているなら@current_userを、そうじゃない場合はもしuser_idがセッションしている状態ならそのセッションしているユーザーの情報を探して、それを変数@current_userとする」という動作をcurrent_userメソッドと定義する。このメソッドは外部から操作されてはいけないのでprivateメソッドのなかに入れる

4-5-9 ログアウト機能を実装する

ログイン状態はreset_sessionでログアウト状態になる

app/controllers/session_controller.rb
 def destroy
   reset_session
   redirect_to root_url, notice: 'ログアウトしました'
end

なのでreset_sessionはdestryコントローラーの中に定義する。

4-5-11-1 データベース上でUserとTaskを紐付ける

UserとTaskを紐づける上で重要になってくるのは【1対多】という関係。User一人に対しTaskは複数存在するといった状況のことである。具体的な紐付けについて説明する。

1.まずtaskのユーザー情報のuserカラムがNOTNULLな状態にならなければいけない。

db/migrate/XXXXXXXXXX_AddUserIdToTasks.rb
class AddUserIdToTasks < ActiveRecord::Migration[5.2]
 def up
   execute 'DELETE FROM tasks;'
   add_reference :tasks, user, null: false, index: true
 end

 def down
   remove_reference :tasks, :user, index: true
 end
end

remove_reference:カラムの中の制約を付けたい時にreferenceを使う。
remove_reference :tasks, :user, index: true←このデータを
add_reference :tasks, user, null: false, index: true←userがnull:falseのなるように制約を付け加えた。
execute 'DELETE FROM tasks;'←制約をつける前にuserがnull:falseだったデータがあるかもしれない、もしあったらエラーになる。なのでこのコードを使いテーブルにあるデータを全削除した。

2.1対多の関係を表すhas_many :tasksとbelongs_toを使って関係性を構築する。

app/models/user.rb
 has_many :tasks
end
app/models/task.rb
 belongs_to :user
end

データベース間の関係はモデルが行うのでモデルに記入。
user has many tasks
tasks belongs to user
の関係になるので
userモデルにhas_many :tasks
tasksモデルにbelongs_to :user
を加える。

4-5-11-3 ログインしているユーザーのTaskデータの登録

ログインするためのcreateアクションは以下のようになっている

app/controller/tasks_controller.rb
 def create
   @task = Task.new(task_params)
  ・
  ・
  ・
  ・
  ・
 private

 def task_params
   params.require(:task).permit(:name, :descrition)
 end
end

このままだと@taskで新規タスクは作られるがログイン中のユーザーのタスクだということがわからなくなる。なので上のコードを書き換える

app/controller/tasks_controller.rb
 def create
   @task = current_user.task.new(task_params)
  ・
  ・
  ・
  ・
  ・
 private

 def task_params
   params.require(:task).permit(:name, :descrition)
 end
end

current_userがつくことによって「現在ログイン中の」という意味のtaskになる。
つまり先頭にcurrent_userをつけると何でも「ログイン中の」という意味がついてくる。
例えば
Task.find(params[:id])→指定したidのタスクを取ってくる
current_user.tasks.find(params[:id])→ログイン中の人のタスクの中から指定したタスクを取ってくる。

4-8 scopeを活用する

order(created_at: :desc)などはscopeを使うともっとシンプルな名前に変えることができる。

scope :recent, -> {order(created_at: :desc)}

このコードでorder(created_at: :desc)はrecentに書き換えることができる。

その他勉強になったこと

task.errors.full_messages

taskのエラー情報が表示される

task.persisted?

taskがデータベースへ登録済みかどうか確認できる。

if task.errors.present?
  ul#errors_explanation
   -task.errors.hull_messages.each do |message|
      li= message

errors.present?でエラーがあるかないかを判断する。

if user&.authenticate(session_params[:password])

private
 def session_params
   params.require(:session).permit(:email, :password)
 end

本来はuser(session_params[:password])だがpassword-digestで暗号化した場合は
user&.authenticate(session_params[:password])になる。

if current_user.admin?

adminでユーザー管理権限を持っているかを確認することができる。そこにcurrent_userが加わり、「ログインしている人はそのユーザーの管理権限を持っているのか?」というif文になる。

@task = current_user.task.order(created_at: :desc)

orderは指定した基準で一覧を並び替える操作
今回はcreated_at(作成日時)を基準で並ぶ順番が変わっている

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

ソフトウェアやパッケージとバージョン管理に関するセンテンス

PATH

PATHとは、「環境変数」と呼ばれるOS用の変数のこと。PATHには、複数の絶対パスの情報が保存されています。
コマンドが入力されたときに、シェルはPATHに記述されたパスのディレクトリ内のファイルを検索します。つまり、PATHに絶対パスを保存してアプリケーションのありかを示せば、どこからコマンドを実行してもアプリケーションのコマンドを打つことができます。

# rbenvのパスを通す
% echo 'eval "$(rbenv init -)"' >> ~/.zshrc

# MySQLのパスを通す
% echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.zshrc

echoコマンドは、>>に続けてファイル名を指定することで、ファイルに文字を追加できるLinuxコマンドです。.zshrcにrbenvの設定を反映するためのコマンドを記述することで、PATHを通しています。

コマンドとアプリケーションの関係

コマンドが実行されると、シェルがそれを読み取ってOSに指示を出す。
OSに初めから入っていてすぐに動作できるアプリケーションとは別に、後からPCに追加する必要があり、よく利用されるアプリケーションは、コマンドラインツールとしてまとめられています。

コマンドラインツール

コマンドで操作するアプリケーションのまとまりです。
コマンドラインツールを導入することで、OSが初めからコマンドで操作できるアプリケーション以外のアプリケーションをPCにインストールできます。

Command Line Tools

macOS専用のコマンドラインツールのことです。
macOSでは、元々Linuxコマンドで操作できるアプリケーションや機能を標準搭載しています。Linuxコマンド以外で操作するアプリケーションの多くはCommand Line Toolsのインストールによって、まとめてPCに導入できます。

パッケージとバージョンの管理

パッケージ管理

パッケージとは、プログラムや処理をひとまとめにしたもののことです。ライブラリとも言えますが、パッケージは複数のライブラリをまとめていることもあります。
パッケージ管理とは、パッケージやパッケージが持つライブラリなどの依存関係を考慮してインストールやバージョンアップを行う管理のことです。
1つのパッケージを利用したい場合、そのパッケージと依存関係にあるパッケージも合わせてインストールしてくれます。

パッケージ管理ツール

Homebrew(macOSのパッケージ管理ツール)
Yarn(JavaScriptのパッケージ管理ツール)

パッケージ

Gem(Rubyのパッケージ)
Node.js(サーバーサイドで利用できるJavaScriptのパッケージ)

バージョン管理

rbenv(Rubyのバージョン管理ツール)

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

[ruby + excel] SaveAsでの注意点

rubyではwin32oleを使えばエクセルを操作することができます。
SaveAsのところでエラーが出てしまったので、注意点をメモします。
method_missing: (in OLE method 'saveas')(WIN32OLERuntimeError)みたいなエラーでした。

結論

指定したディレクトリに保存する場合
- 絶対パスにする。
- パスの区切りは/ではなく\にする。

require 'win32ole'

app = WIN32OLE.new('Excel.Application')
book = app.workbooks.add
out_path = File.expand_path('test.xlsx').gsub('/', '\\')
book.saveas filename: out_path
book.close savechanges: false
app.quit

SaveAsで指定するパスについて

  1. 相対パスではエクセルが持っているローカルが基準になります。
  2. パスの区切り文字は/ではなく\にしてあげます。
  3. 名前付き引数はシンボルで指定してあげます。

1. エクセルが持っているカレント

rubyでは相対パスが利用できます。
エクセルでも相対パスが使えますが、「カレント」が指す場所はエクセルで設定されているローカルフォルダになります。
オプションの「規定のローカル ファイルの保存場所」に書かれている場所です。
なので、rubyが実行している場所をカレントとするために絶対パスにしてあげます。

out_path = File.expand_path('test.xlsx')

2. パスの区切りは/ではなく\で。

rubyのパスでは、階層の区切りに/(スラッシュ)が使われます。
どうやらこのままでは保存できなかったので区切り文字を(バックスラッシュ)に置き換えます。

out_path = File.expand_path('test.xlsx').gsub('/', '\\')

3. 名前付き引数の指定

名前付き引数はシンボルで指定できます。
VBAでは「:=」を使いますが、下記のように書きます。

workbook.saveas filename: path

なぜできるのかは未検証です。引数をハッシュで渡しているから?

余談

rubyの基本のようですが、

p out_path

では文字列が""で囲まれ、\が\\とエスケープされて表示されます。
(\\じゃなくて、一つにしたい!と、いろいろやって数時間。。)
あくまでもプロンプトの表示の問題で、実際には\はひとつです。

puts out_path

とすればよかったのでした。

ruby初心者のため、間違った記述があるかもしれません。
コメント等でご指摘いただければ幸いです。

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

【Rails】Rake taskでバッチ処理を実装してみた

はじめに

環境

Rails: 5.2.3
Ruby: 2.6.3
MySQL: 5.6.40

内容

  • usersテーブルのquestion_countカラムが更新されていないバグがあり、 バッチを作成し、一括で正しい値に更新できるようにしました。
  • 既存のメソッドを使用しているため分かりにくい箇所があるかもしれませんがご容赦ください。
user.rb
has_many :questions, dependent: false
has_many :only_questions_visible_to_user, -> { where(question_id: nil).visible_to_user }, class_name: 'Question', dependent: false

scope :visible_to_user, -> { where(is_invalid: false).where(deleted: false) }

def update_question_count!
  update!(question_count: count_questions)
end

private

# question_count を更新する時の集計に利用するメソッド
#
# @return [Integer]
def count_questions
  only_questions_visible_to_user.size
end

question.rb
belongs_to :user, optional: true

実装したコード

  • ログを出力して途中経過、更新に失敗したもの認識しやすいようにしてみました。
  • 一度のみの実行で、以降は必要なくなるため、one_shotディレクトリ配下に置いて実行後に削除します。
lib/tasks/one_shot/update_users_question_count.rake
# frozen_string_literal: true

namespace :user do
  desc 'Update users_question_count'
  task update_question_count: :environment do |_task|
    index = 0
    updated_question_counts = 0
    user_count = User.count
    logger = Logger.new($stdout)
    logger.info 'Start'

    User.find_each do |user|
      begin
        if user.question_count != user.only_questions_visible_to_user.size
          user.update_question_count!
          updated_question_counts += 1
        end
      rescue ActiveRecord::RecordInvalid => e
        logger.info "Failed to update user_id: #{user.id}"
        logger.info("#{e.class}: #{e.message}")
        next
      end

      index += 1
      case index
      when 4000, 8000, 12_000, 16_000
        logger.info "Progress: #{index}/#{user_count}"
      end
    end
    logger.info "Updated User Count: #{updated_user_counts}"
    logger.info 'Finished'
  end
end

バッチ実行

bundle exec rake user:update_question_count

  • 約19,000レコードの更新処理で45secほどかかりました。
  • 更新に失敗したカラムが表示されるので別途対応が容易になりました。 スクリーンショット 2020-10-26 午後2.36.25.png
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】論理削除(退会機能)

目標

画面収録 2020-10-25 21.31.39.mov.gif

開発環境

ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

前提

流れ

1 カラムの追加
2 modelの編集
3 controllerの編集

カラムの追加

ターミナル
$ rails g migration AddIsValidToUsers is_valid:boolean

default: true, null: falseを追加。
booleanを使用することにより、ture、falseで退会しているかどうかを判断します。
下記の場合は初期値をtrueに設定しますので、退会済みの場合はfalseとなります。

db/migrate/xxxxxxxxxxxxx_add_is_valid_to_users.rb
class AddIsValidToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :is_valid, :boolean, default: true, null: false
  end
end
ターミナル
$ rails db:migrate

controllerの編集

退会画面と退会処理のアクションを作成

app/controllers/homes_controller.rb
  def unsubscribe
    @user = User.find_by(name: params[:name])
  end

  def withdraw
    @user = User.find_by(name: params[:name])
    @user.update(is_valid: false)
    reset_session
    redirect_to root_path
  end

退会後のログインを阻止する記述。

app/controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
  before_action :reject_inactive_user, only: [:create]

...

  def reject_inactive_user
    @user = User.find_by(name: params[:user][:name])
    if @user
      if @user.valid_password?(params[:user][:password]) && !@user.is_valid
        redirect_to new_user_session_path
      end
    end
  end
end

routesの編集

config/routes.rb
get 'unsubscribe/:name' => 'homes#unsubscribe', as: 'confirm_unsubscribe'
patch ':id/withdraw/:name' => 'homes#withdraw', as: 'withdraw_user'
put 'withdraw/:name' => 'users#withdraw'

viewの編集

app/views/homes/unsubscribe.html.erb
<div>
  <h2>本当に退会しますか?</h2>
  <div>
    <p>退会する場合は、『退会する』をクリックしてください。</p>
  </div>
  <div>
    <%= link_to '退会しない', mypage_path(@user) %>
    <%= link_to "退会する", withdraw_user_path(@user), method: :patch %>
  </div>
</div>

参考

PUT か POST か PATCH か?

まとめ

論理削除のメリット、デメリットは色々あると思いますが、
サービスを運営する場合、顧客情報は大切になりますので、
物理削除ではなく、論理削除で退会にしたほうが、
復活の手段にもなるためおすすめです。

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

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

Railsで複数画像アップロード機能とその投稿に対して複数画像をスライドできるように実装してみた

1.複数画像アップロード機能を実装

carrierwaveを使用して複数枚の画像をアップロードできるように実装してみた。

carrierwaveとは?

carrierwaveとは、Railsアプリケーションから画像アップロード機能を簡単に実装できるライブラリ。今回は、carrierwave ver2.1.0を使用しました。

どのように使用したか?

まずは、下のGemをインストールする。

自分のアプリ/Gemfile

gem 'carrierwave'
gem 'mini_magick'

アップローダーを生成する。

rails g upload image

これにより次のファイルが生成される。このファイル内でカスタマイズしたいときは処理を加える。

app/upload/image_upload.rb

なので、自分は下のように設定を行いました。

自分のアプリ/app/upload/image_upload.rb

class ImageUploader < CarrierWave::Uploader::Base

    include CarrierWave::MiniMagick

    process resize_to_fill: [1000, 1000]

    version :thumb do
        process resize_to_fit: [223,223]
    end

    version :swiper do
        process resize_to_fit: [400, 400]
    end

    version :thumbnil do
        process resize_to_fit: [100, 100]
    end

    storage :file

    def store_dir
        "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
    end

     def extension_whitelist
        %w(jpg jpeg gif png)
     end

 end

どのように設定を加えていったかというと、、、

include CarrierWave::MiniMagick

アップロード時に画像のリサイズを行いたかったので、minimagickをインストール。image_upload.rb生成時にコメントアウトで記載してあるので#を消して処理コードとして記載。minimagickとは、CプログラムであるimagemagickのRubyのインターフェース。これによって、画像リサイズ用のメソッドを使用することが出来る。

下の処理は、アップロードされるとと、1000×1000pxで切り抜きを行い、次にthumbと呼ばれるバージョンが作成され、223×223pxに拡大縮小される。同じように、swiper、thumbnilと呼ばれるバージョンが作成され、各々のバージョンに拡大縮小される。
※ただし、チーム開発によってはあまりバージョンを増やすのは好ましくないとのこと。

process resize_to_fill: [1000, 1000]


version :thumb do
    process resize_to_fit: [223,223]
end

version :swiper do
    process resize_to_fit: [400, 400]
end

version :thumbnil do
    process resize_to_fit: [100, 100]
end

これは、画像がアップロードした時に保存される場所である。デフォルト記載されている。「public/uploads/指定したモデル名/指定したモデルのカラム名/モデルID/画像と各バージョンで作成した画像」のように置かれている。変更した場合は、オーバライドして記載すれば良い。

def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end

これもデフォルトでコメントアウトで記載されているので処理出来るように記載。許可される拡張機能のホワイトリストを指定することが出来る。jpg、jpeg、gif、png以外の拡張子をアップロードするとレコードが無効になる。

def extension_whitelist
    %w(jpg jpeg gif png)
end

ここまでで設定の説明は終わりにして、次に親となるpostテーブルと子のimageテーブルを作成する。
postとimageでテーブルを分けたのは、複数投稿に対応する為。

posts
content
images
url
post_id
$rails g model Post content:text 

$rails g model Image url:string post:reference

ここでつまずいたのが、自分の場合はimageモデル作成の際にjson型を扱ったことです。 もともと、postテーブル内でimageカラムを作成して複数投稿できる仕様にしようと思ったのですが、新しいimageテーブルを作成して保存するよう変更したため、わざわざjson型にしなくても良いということを後になって気づきました。なので、ここで一つのテーブルで複数画像を扱うならjson型にして、一つのオブジェクトレコードに複数画像を扱えるように設計するのもいいと思います。自分の場合は、別のテーブルを作成してjson型のままにしていますが、特に理由がないのならstring型で作成することをお勧めします。

マイグレーションファイルを作成して、データベースを更新する。

$rails db:migrate

モデルファイルに以下の記述を加える。

自分のアプリ/app/model/image.rb

class Image < ApplicationRecord
    belongs_to :post
    mount_uploader :url, ImageUploader #アップロード機能を使いたいデータにマウントする。
end

自分のアプリ/app/mode/post.rb

class Post < ApplicationRecord
    validates :content, presence: true, length: { maximum: 1000 }
    has_many :images, dependent: :destroy
    accepts_nested_attributes_for :images #postを投稿するとimageも同時に投稿できるようになる
end

ここで注意しなければならないのは、accepts_nested_attributes_forを使うときは、ストロングパラメータにimages_attributesカラムを追記しなければならないこと。以下のようになります。

自分のアプリ/app/controller/post_controller.rb

  def new
    @post = Post.new
    @image = @post.images.build
  end

  def create
    @post = current_user.posts.new(post_params)
    if @post.save
      redirect_to posts_path, success: "投稿しました"
    else
      flash[:danger] = "投稿に失敗しました"
      render :new
    end
  end

  private

  def post_params
    params.require(:post).permit(:content, images_attributes: [:url])
  end

これで複数画像をパラメーターとして渡せるように設定できました。
続いて、viewで画像をどのように複数投稿できるようにするか考えていきます。
ここで、自分は色々ハマまりました。fields_forメソッドでは、第2引数にmultiple: trueを記述することで複数投稿できるとのことですが、うまくいかず、、、。なので別の方法として、javascriptで複数投稿できるように実装しました。この記事がとてもよく書かれていたので参考にさせていただきました。→Qiita この記事の通りに設定すれば、javascriptが起動して、アップロードするたびにプログラムが動いてくれるはずです。

2. swiperで1つの投稿に対して複数画像をスライドできるように実装

swiperとは?

ざっくりというと、スライド機能の実装が簡単にできるフレームワーク。

どのように使用したか?

 まずは、アプリケーション内でswiperを使えるように設定します。いくつか方法があるのですが、私はyarnを利用して導入しました。こちらの記事のyarnでの導入方法や内容がとても分かりやすかったので参考にさせていただきました。
Qiita

swiperをyarnで導入します。

$yarn add swiper

$yarn install

導入できたか確認するには、packege.json を確認してください。もしyarnを導入していないのであれば、下記のコマンドでyarnを導入してください。(macをお使いの場合)

$brew installl yarn

導入したら、application.js、application.scssに下記のように記載します。

自分のアプリ/app/assets/stylesheets/application.scss

@import "swiper/swiper-bundle";

自分のアプリ/app/assets/javascript/application.js

 //= require swiper/swiper-bundle.js
 //= swiper.js

swiper.jsファイルを作成し、下記のように記述してください。swiperでは、swiperで加えたい種類のスライド方法を自分で記述し作成する必要があります。swiperのデモから自分のお好みのスライド方法を選び、ソースコードから!-- Initialize Swiper --より下のスクリプト内のjsのコードをコピペしてください。スクリプトタグは記載する必要はありません。私の場合は、ページネーション/動的弾丸でのスライドにしたので下記のようになります。このjsファイル名はswiper.jsでなくても構いません。ファイル名を変更したい場合は、applicaion.js内で記載したファイル名も変更してください。デモ

自分のアプリ/app/assets/javascript/swiper.js

var swiper = new Swiper(".swiper-container", {
pagination: {
    el: ".swiper-pagination",
    dynamicBullets: true,
    },
});

これで準備は整ったので、viewで実際に実装してみます。
ページネーション/動的弾丸での実装例なので他のスライド方法を選んだ方は、ソースコードを確認してください。

自分のアプリ/app/views/posts/index.html.slim

 .swiper-container.top-carousel
    .swiper-wrapper(style="transform: translate3d(0px, 0px, 0px)")
        - @post.images.each do |img|
            .swiper-slide(style="width: 400px;")
                = link_to post do
                = image_tag img.swiper.url, class: "card-img-top"
     .swiper-pagination

~省略~

= javascript_include_tag "application"  

ここで大事なのは、= javascript_include_tag "application"を一番最後に記述することです。これを書き忘れるとswiperが起動してくれません。application.html.slimに書くという方法もありますが、自分はswiperを必要とするページの部分だけに記述してます。また、このimg.url.swiper.urlは、carrierwaveで作成したswiperバージョンの画像を呼び出しています。

これで、自分の場合はswiperを実装することができました。

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

Railsで問い合わせフォームを実装する

RailsでGmailを利用した問い合わせフォームを実装しました。

ルーティングの設定

まず、ルーティングを設定します。
問い合わせフォームのページで問合せ内容を入力→送信したら送信完了ページに遷移するという想定です。

config/routes.rb
Rails.application.routes.draw do
  resource :contacts, only: [:new, :create] do
    get "/thanks" => "contacts#thanks"
  end
end

モデルの作成

問合せフォームで入力する内容は、お名前、メールアドレス、問合せ内容の3点としました。

$ rails g model contact name:string email:string content:text
$ rails db:migrate

コントローラの作成

$ rails g controller contacts
app/controller/contacts_controller.rb
class ContactsController < ApplicationController
  def new
    @contact = Contact.new
  end

  def create
    @contact = Contact.new(contact_params)
    if @contact.save
      ContactMailer.contact_mail(@contact).deliver
      redirect_to thanks_contacts_path
    else
      render :new
    end
  end

  def thanks
  end

  private
  def contact_params
    params.require(:contact).permit(:name, :email, :content)
  end
end

ビュー(お問い合わせフォーム)の作成

私が作成したサイトのテイストに合わせて一部ひらがなにしている箇所がございますが気にしないでください。

app/view/contacts/new.html.erb
<h3>おといあわせ</h3>
<%= form_with(model: @contact, local: true) do |f| %>
  <%= f.label :name, "おなまえ" %>
  <%= f.text_field :name %>
  <%= f.label :email, "メールアドレス" %>
  <%= f.email_field :email, autocomplete: "email" %>
  <%= f.label :content, "ないよう" %>
  <%= f.text_field :content %>
  <%= f.submit "おくる" %>
<% end %>

ビュー(送信完了画面)の作成

app/view/contacts/thanks.html.erb
<h3>おといあわせ、ありがとうございました。</h3>

メーラーの作成

$ rails g mailer ContactMailer

メール送信処理を記載

app/model/contact_mailer.rb
class ContactMailer < ApplicationMailer
  def contact_mail(contact)
    @contact = contact
    mail to:"自分のメールアドレス", subject: "お問い合わせ"
  end
end

メール文の作成

app/view/contact_mailer/contact_mail.html.erb
<p>ユーザーネーム:<%= @contact.name %></p>
<p>メールアドレス:<%= @contact.email %></p>
<p>お問い合わせ内容:<%= @contact.content %></p>

Gmailサーバーの設定

config/environments/development.rb
Rails.application.configure do
  config.action_mailer.perform_deliveries = true
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    address: 'smtp.gmail.com',
    domain: 'gmail.com',
    port: 587,
    user_name: '自分のメールアドレス',
    password: ENV["GMAIL_KEY"],
    authentication: 'plain',
    enable_starttls_auto: true
  }
end

パスワードはGitHubに上がってしまわないように、.envファイルに記載することにします。

Gmailキーの設定

アプリケーションディレクトリ直下の.envファイル(ない場合は作成)に以下を記載します。

GMAIL_KEY=パスワード

ここに入力するパスワードはGoogleアカウントにアクセスし生成したアプリパスワードを入力します。

セキュリティ→Googleへのログインの欄
2段階認証を設定していない方は、まず設定をした上で、アプリパスワードを生成します。
ここで生成したパスワードを入力します。

こちらで実装は完了です。

これで問合せフォームからメールを送信すると
スクリーンショット 2020-10-25 23.32.31.png

無事、送受信ができました。

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

Docker × Rails × RSpecで開発環境で’Could not find ’****’ in any of the sources’が出た時の対処方法

【Rails】Docker × Rails × RSpecの開発環境で’Could not find ’****’ in any of the sources’が出た時の対処方法

Gemfile
group :development, :test do
  ~ 以下追加 ~
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end

Gemfileを更新したのでdockerコマンドでbundle install実行

$ docker-compose run web bundle exec rails g rspec:install

エラーメッセージ

Could not find diff-lcs-1.4.4 in any of the sources
Run `bundle install` to install missing gems.

色んな記事を参照させてもらって実行してみるもなかなかうまくいかず・・・

解決方法

いろいろググっている内にキャッシュで bundle install が実行されないていない場合がある?という記事を見させていただき、早速実行しました

$ docker-compose build --no-cache

実行結果

$ docker-compose run web bundle exec rails g rspec:install
Creating app_run ... done
Running via Spring preloader in process 64
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb

見事クリエイトに成功

原因

docker-compose build しても cache が有効になっていて設定変更が反映されてうまく動作しないことがあるので、開発中にGemfileを更新した時は

$ docker-compose build --no-cache

で実行する方がいいとのことです

まとめ

spring stop関連の記事が多かったため解決するのに時間がかかってしまった点が反省点。でも初学者だからこそこの積み重ねが大事とも感じました

参考

以下の記事参考にさせていただきました!ありがとうございました!

Dockerでコンテナ内にbundle installされない問題の解決法
docker をキャッシュを使わないでビルドする

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

thinreportsで中国語(韓国語)のPDFを表示したい

カスタムフォントが選択できない

Screen Shot 2020-10-26 at 11.12.08.png

現状フォントは固定で、持ち込みのフォントは指定できない様子。
このまま中国語(韓国語でも)を入れようとすると、PDFの状態で文字化けを起こす。

解決方法

韓国語や中国語のテキストをPDFで表示できない

Railsであれば、ここにあるようにinitializerをつくってやる。

config/initializers/thinreports.rb
Thinreports.configure do |config|
  config.fallback_fonts <<
    Rails.root.join("app/thinreports/NotoSansCJKsc-Regular.ttf").to_s
end

ここで重要なのはttfフォントで、NOTOフォントを使う必要がある。
(□表示は英語圏ではTOFUと呼ばれ、もう豆腐表示はうんざり - no more tofu - NOTO らしい 、ついでにtofulearn.com

最初は「CJK」なんだからフォントファイル一個でChineseJapaneseKorean全部表示できるんでしょ?って思ってたけど、どうやら違う。適当にダウンロードしてきたNotoCJKファイルは日本語バージョンだったため引き続き中国語の表示ができなかった(□になる部分がPDFでは空白表示だった)。

よくよく調べるとCJKでも各地域ごとのフォントバージョンがあるらしい。

  • Simplified Chinese (SC)
  • Traditional Chinese (TC)
  • Japanese (JP)
  • Korean (KR)

最初に使ってたファイルはよくよく見るとNotoSansCJKjp-Regular.ttfだった。なので、NotoSansCJKsc-Regular.ttfを適当に探してみて、当ててみたらバッチリだった。

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

Heroku CLI 操作(コマンド)

あくまでもコマンド一覧です。デプロイする時の順番ではないのでご注意
railsアプリケーションをHerokuにデプロイする為、gemファイルに記述
ruby:Gemfile
 group :production do
   gem 'rails_12factor'
  end

rails_12factorは、開発環境ではなく本番環境で使用するGem,productionは本番環境で使用できる様にする為
コマンド一覧


herokuにログイン

heroku login --interactive

Heroku上に公開するためのアプリケーションを作成

heroku create アプリ名

アプリケーションが反映されているか

git config --list | grep heroku

heroku上でmy sqlの作成(ClearDBアドオン)

heroku addons:add cleardb

Ruby on Railsを使う場合は、 MySQLに対応するGemに変更

heroku_cleardb=heroku config:get CLEARDB_DATABASE_URL

自身のmysqlのバージョンに変更(URL)

heroku config:set DATABASE_URL=[自身のmysql]${heroku_cleardb:5}

credentials.yml.encをmaster.keyによって復号し、中身を確認したい時

EDITOR="vi" bin/rails credentials:edit

 
Heroku上で環境変数の設定

heroku config:set RAILS_MASTER_KEY=cat config/master.key

Herokuの環境変数一覧を表示

heroku config

herokuにアプリ反映

git push heroku master

heroku上でマイグレーションの反映

heroku run rails db:migrate
 
heroku runはheroku上で操作したい時に使用する

Herokuにデプロイされたアプリケーションの情報を参照したい時

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

【Rails】deviseのヘルパーメソッド

1.初めに

deviseを導入した際に使える便利なヘルパーメソッドをメモします。

2.ヘルパーメソッド

メソッド 機能
before_action :authenticate_user! ログイン済ユーザーのみにアクセスを許可する
current_user 現在ログインしているユーザーを取得する
user_signed_in? ユーザーがサインインしているかどうかを判定する
user_session ユーザーのセッション情報にアクセスする

※「user」の部分はモデル名になるので、モデル名に応じて「user」部分を書き換えます。

3.before_action :authenticate_user!

ログイン状態によって表示するページを切り替えるメソッドです。
ユーザーがログインしていなければ、そのユーザーをログイン画面に遷移させます。
before_actionで呼び出すことで、アクションを実行する前にログインしていなければログイン画面に遷移させられます。

app/controllers/application_controller.rb
class ArticlesController < ApplicationController
  before_action :authenticate_user!

  def index
  end

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

コピぺで使える簡易的なスロットマシーン実装

コピぺで使える簡易的なスロットマシーン実装

51dfdc85977ada043ac57c858b1ee611.png

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>スロットマシーン 1</title>
<style>
input {
    width:40px;
    font-size:30px;
    text-align:center;
}
button {
    width:50px;
}
.x1 {
    padding:10px 0;
}
.x1 div {
    float:left;
    width:60px;
    text-align:center;
}
</style>
<script>
window.onload = function() {
    var a = document.getElementById('a');
    var b1 = document.getElementById('b1');
    var b2 = document.getElementById('b2');
    var b3 = document.getElementById('b3');
    var c1 = document.getElementById('c1');
    var c2 = document.getElementById('c2');
    var c3 = document.getElementById('c3');
    var t1 = null;
    var t2 = null;
    var t3 = null;

    function start() {
        if (t1) {
            clearInterval(t1);
        }
        if (t2) {
            clearInterval(t2);
        }
        if (t3) {
            clearInterval(t3);
        }
        c1.value = Math.floor(Math.random() * 10);
        c2.value = Math.floor(Math.random() * 10);
        c3.value = Math.floor(Math.random() * 10);
        t1 = setInterval(function () {
            c1.value = (+c1.value + 1) % 10;
        }, 200);
        t2 = setInterval(function () {
            c2.value = (+c2.value + 1) % 10;
        }, 200);
        t3 = setInterval(function () {
            c3.value = (+c3.value + 1) % 10;
        }, 200);
    }

    function stop1() {
        if (t1) {
            clearInterval(t1);
            t1 = null;
        }
        check();
    }

    function stop2() {
        if (t2) {
            clearInterval(t2);
            t2 = null;
        }
        check();
    }

    function stop3() {
        if (t3) {
            clearInterval(t3);
            t3 = null;
        }
        check();
    }

    function check() {
        if (!t1 && !t2 && !t3) {
            if (c1.value == c2.value && c1.value == c3.value) {
                alert('あたり!');
            } else {
                alert('はずれ!');
            }
        }
    }

    a.addEventListener('click', start);
    b1.addEventListener('click', stop1);
    b2.addEventListener('click', stop2);
    b3.addEventListener('click', stop3);

    start();
}
</script>
</head>
<body>
    <button type="button" id="a">start</button>
    <div class="x1">
        <div>
            <input type="text" id="c1">
            <button type="button" id="b1">stop</button>
        </div>
        <div>
            <input type="text" id="c2">
            <button type="button" id="b2">stop</button>
        </div>
        <div>
            <input type="text" id="c3">
            <button type="button" id="b3">stop</button>
        </div>
    </div>
</body>
</html>

現場からは以上です!

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

[Rails] form_with の2種類の書き方

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

form_withとは

  • 情報を送信するためのヘルパーメソッドです。
  • 入力に必要なHTMLを表示してくれます。
  • form_withには2つの書き方があります。
  • 1つ目は、入力された情報をデータベースに保存する場合、2つ目は入力された情報をデータベースに保存しない場合です。

データベースに保存する時

  • model:に続けてモデルクラスのインスタンスを記述します。
  • f.text_fieldでテキストボックスを作成します。
<%= form_with model: @book, local: true do |f| %>  
    <%= f.text_field :keyword, placeholder: "keyword", class: "search-input"%>
    <%= f.submit "search", class: "search-btn" %>
<% end %>

データベースに保存しない時

  • url:に続けて情報送信先のパスを記述します。
<%= form_with url: search_path, local: true do |f| %>
   <%= f.text_field :keyword, placeholder: "keyword", class: "search-input"%>
   <%= f.submit "search", class: "search-btn" %>
<% end %>

ルーティングでネストしている場合

  • 例えばpostコントローラーにcommentコントローラーのルーティングがネストしているとしましょう。
  • その場合、コードはこんな感じになります。
  • モデルクラスのインスタンスを親クラスと子クラスの順で2つ記述すれば良いのですね。
<%= form_with model: [@post, @comment] do |f| %>
  <%= f.text_field :comment%>
  <%= f.submit %>
<% end %>

参考

https://pikawaka.com/rails/form_with
https://qiita.com/hmmrjn/items/24f3b8eade206ace17e2

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