20200803のRailsに関する記事は17件です。

rails 本番環境に開発環境の変更を反映させる

この記事について

リポジトリから本番環境にpullをすれば変更が反映されると思ってたけど、どうやら違っていたようなので備忘録メモとして投稿!!!

なぜpullしても反映されないのか?

自動反映の仕組みはパフォーマンスに影響を与えるのでdevelopment以外ではデフォルトではオフになってるみたい。
cache_classesという設定値があって、自動反映の仕組みは毎回リクエストが来るタイミングでソースコードを都度読むことで実現している(逆にproductionなどでは一度読み込んだコードをメモリ上に保持することでリクエストごとに発生していたファイル読み込みのステップが不要になり早くなる)

変更を反映させるには?

アプリケーションサーバーをkillしてもう一度立ち上げてあげるか、rails restratコマンドで変更を反映してあげるとよい。

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

active_hashを使って疑似モデルを作ろう 〜都道府県データ〜

某メルカリコピーサイト作成中

active_hash

データベースを作ることなく擬似的にモデルを作成しデータを入れることができる

とのことなので active_hash なるgemを使ってみます

まずGemfileにactive_hashを追加

gem 'active_hash'

bundle install します

Model

でモデルファイルを作っていくんですが
今回は rails g model では作成しない様

普段はApplicationRecordを継承してるけど、
active_hashを使用するモデルはActiveHash::Baseを継承する必要があるからみたい

なので直接 app/models/ に作成していきます

prefecture.rb
class Prefecture < ActiveHash::Base

end

こんな感じで ActiveHash::Base を継承します

データの雛形はこんな感じ

prefecture.rb
class Prefecture < ActiveHash::Base

  self.data = [ ]

end

この中にデータを入れていきます

prefecture.rb
class Prefecture < ActiveHash::Base

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

end

この様にハッシュ形式で入れていきます


次にアソシエーション

product.rb
class product < ApplicationRecord

  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to_active_hash :prefecture

end

今回はproductテーブルと紐付けるのでproduct.rbに記述します

通常はbelongs_toですがactive_hashの場合はbelongs_to_active_hashになります

prefecture.rb
class Prefecture < ActiveHash::Base

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

  include ActiveHash::Associations
  has_many :users

end

prefecture側はこの様に

あとは表示させるだけ!!

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

AWS Elastic Beanstalk + Rails環境でnginxのconfがうまく反映されない場合

■方法
公式ドキュメントの通り、[.platform]配下にファイルを配置すれば反映されると思います。

~/workspace/my-app/
|-- .platform
|  `-- nginx
|    `-- conf.d
|      `-- myconf.conf
`-- other source files

■公式ドキュメント
・Elastic Beanstalk Linux プラットフォームの拡張
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/platforms-linux-extend.html

■おまけ
どうして公式に記載されている内容をわざわざ投稿したのかというと、全然検索に引っかからないからです。
[413 Request Entity Too Large]エラー対応でconfを編集する必要があり、
調べると2通りの記述方法が引っかかりました。

  1. [.ebextensions]配下に[nginx]を置く
  2. [.ebextensions]配下に[01_XXX.config]みたいなファイルを置く

この二つを延々試してたんですがウンともスンとも言わず、調べても他の方法が全然引っかからず・・・
デプロイ中にドキュメントを眺めてたら上記の内容を見つけた次第です。

JavaやGoの場合は[.ebextensions]に配置する方法が書かれており、
「Railsでも同じ形でいけるよ!!」って記事が上位に引っかかるのもハマりやすいポイントかと思います。(めちゃくちゃハマりました。)
・Increasing client_max_body_size in Nginx conf on AWS Elastic Beanstalk
https://stackoverflow.com/questions/18908426/increasing-client-max-body-size-in-nginx-conf-on-aws-elastic-beanstalk

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

Rails + postgres で jsonb の中の Array をクエリする方法

難しかったのでメモ

データの形

こんな感じのが jsonb のカラムの中に保存されている。

{
  hoge: String,
  items: String[]
}

やりたいことと解決策

それでやりたいのは items の中に特定の文字列 ["a", "b", "c"] のいずれかが含まれているものをクエリすること。

結論としては次のようなコードでいけた。

items_to_query = ["a", "b", "c"]
Model.where("jsonbColumnName -> 'items' @> ?", items_to_query.to_json)

参考

https://stackoverflow.com/questions/35737931/rails-postgres-query-with-jsonb-array
https://www.postgresql.org/docs/9.4/functions-json.html

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

Graphql-rubyでのエラーハンドリング

はじめに

最近、graphql-rubyでAPIを実装しています。
そこで、graphqlでのエラーハンドリングについて、ベストプラクティスを模索してみました。
まだ始めたばかりなので、もっといい方法あるよ!っていうコメント募集中です。

エラーの分類

エラーハンドリングの実装に移る前にエラーにはいくつか種類があるので、紹介します。
以下の記事が非常にわかりやすく、まとまっていたので参考にしています。

Railsアプリケーションにおけるエラー処理(例外設計)の考え方

ここでは、以下のように異常系と準異常系の2つに分類します。

  • 異常系:nwエラーや、プログラムのエラー(システムエラー)
  • 準異常系:作り手が予期できるエラー(業務エラー)

この2種類のエラーに対して、以下のような要件があります。

  • 異常系:フロント側でテンプレートメッセージを表示 & 開発者に通知
  • 準異常系:エラー内容や回避方法をフロント側(この辺りは要件によって変わってくるかもしれません)

肝となるのは、異常系は決まったテンプレートのメッセージを表示するが、準異常系はAPIからメッセージを送るというところです。この要件をどのように実装させるかが本題となります。

Graphql-rubyの仕様

graphql-rubyでは、エラーの場合以下のようなerrorsをkeyにしたjsonが返ってきます。

"errors": [
    {
      "message": "error message",
      "locations": [],
      "extensions": {
        "code": "ERROR_CODE"
      }
    }
  ]

このエラーメッセージは、主にインターフェイスでバグがあったりすると発生します。
例えばフロント側で渡す引数にnullが入ってるとき等です。

上のようなエラーは以下のように直接コードを書いて発生させることもできます。

sample.ruby
raise GraphQL::ExecutionError.new('error message', extensions: {code: "ERROR_CODE"})

実装

上記の仕様から異常系のエラーはerrorsが戻り値で返ってくることがわかります。
では準異常系はどうでしょうか?準異常系の要件は以下です。

  • 画面に表示するエラーメッセージを渡す
  • フロントが準異常系エラーと判断できる

まず1つ目の要件は上記のgraphqlエラーをraiseする方法でエラーメッセージを渡せるのでokです。しかし、そのままではフロント側で異常系のエラーと区別ができません。

そこで以下のようにjsonをカスタマイズすることにしました。

sample.ruby
raise GraphQL::ExecutionError.new('error message', extensions: {customCode: "ERROR_CODE"})

code->customCodeとなっています。フロント側ではcustomCodeがkeyとして存在すれば、そのままerror messageを表示。それ以外はテンプレートのメッセージを表示させることで、異常系と準異常系の処理を切り分けることができます。

参考資料

graphql-ruby公式
GraphQLにおけるエラーハンドリングの仕方

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

No template for interactive requestの対処法

アプリ作成中にNo template for interactive requestが発生した。

エラー

私の場合は
No template for interactive request
PagesController#index is missing a template for request formats: text/html

であった。

routes.rb
Rails.application.routes.draw do
  resources :pages
  root 'pages#index'
end
pagescontroller
class PagesController < ApplicationController

  def index
  end
end

ビューファイルもしっかりapp/view/pagesにindex.html.hamlで作成していたので、原因がわからず解決できなかった。

原因

PagesController#index is missing a template for request formats: text/htmlとエラー文ではhtml文を呼んでいたが、自分はhamlファイルを生成してしまっていた。

解決法

ファイル名をindex.html.hamlからindex.html.erbに変更

これで解決する事ができた

hamlでのビューファイルを呼び出すために

投稿者はhamlを利用したかったが、hamlを使うには haml-railsというgemをインストールしなければならなかったらしい。 

gemfile
gem 'haml-rails'

これで、hamlファイルを呼び出す事ができた。

反省

この解決だけで1時間ほど時間を食ってしまったのが辛かったので、もっと速い間隔で試行錯誤を行うことを心がける。

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

ターミナルでコマンドを実行した際にOperation not permitted が表示された場合の対処法

rails中級チュートリアルアプリ作成

の最中にトップページへのルーティング、コントローラー作成をし、rails sを実行しようとしたところ、

ターミナル
Operation not permitted 

と、エラー文が表示されてしまった。

解決法

システム環境設定→セキュリティとプライバシー→プライバシー→左に並んでいる中からフルディスクアクセスを選択→ターミナルにチェックを入れる。

これでターミナルを再起動すると解決する事ができた。

参考サイト

https://gori.me/mac/mac-tips/112082

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

rails sを実行したら Address already in use と表示された時の対処法

アプリ作成中にこのエラーに遭遇したため記録しておく

解決したい事

rails sを行うと

Address already in use - bind(2) for "127.0.0.1" port 3000 (Errno::EADDRINUSE)

とターミナルに表示されてしまいrails sを実行できない

解決法

すでにrails sが他のターミナルなどで実行されているかを確認。

rails sが実行されているのが確認できなければ

ターミナル
% ps ax | grep rails

を打ち込み出てきたプロセス番号を

ターミナル
% kill -9 プロセス番号

でプロセスを止めることで解決する事ができる。

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

【Rails】SNS認証の登録手順(Twitter、Facebook、google)

deviseを用いた、Twitter、Facebook、googleでのログイン認証を目的にした、アカウント登録〜Key取得までの備忘録です。

Google API の登録

Google Cloud Platformにログインし、プロジェクトを作成。

今回は、「ユーザー認証」のみなので、使わないAPIは無効にしとく( 最低限の Google+ API だけ有効)。
Alt text
Alt text
OAuth 同意画面で設定後、認証情報をクリック(OAuth 同意しないと、認証情報を追加できない)。
Alt text
KeyとSecretが自動生成されるので、メモっとく。コールバック のURIを設定する。
(例:ローカルの場合)
http://localhost:3000/users/auth/google_oauth2/callback
http://localhost:3000/users/auth/google/callback
Alt text

Facebook API の登録

Facebook developersで、ログインし、アプリを作成すると、マイアプリ(KeyとSecret)が自動生成される。
Alt text
Alt text
ローカルなら、 http://localhost:3000 でok。
Alt text
ダッシュボードに行く。
Alt text
App IDとSECRETをメモっとく。
Alt text
コールバック用のURIを追記。ローカルなら、 https://localhost:3000/users/auth/facebook/callback。
Alt text

Twitter API の登録

アカウント作成 → API登録申請 → 確認メール → 作成するアプリに関する設定

API 登録申請

Twitter Developer のアカウント作成

Twitter Developerにログイン。
Alt text
Alt text
Alt text
Alt text
携帯番号を入力して、 Next。認証コードを入力。

Alt text
Alt text
Alt text
内容を確認し、 Looks Good! 次に、利用規約に同意のチェックを入れ、 Submit Application をクリック。

完了画面が表示され、メールが届くので、 Confirm your email をクリックで完了。

Twitterの API_KEY、 API_SECRET取得

developer accountにアクセスし、アプリ名を入力(一意性)。作成された、API_KEYとAPI_SECRETをコピーしとく。

コールバックurlの設定。

・ permission: read only
・ Request email addresses from usersにチェック
・ Enable Sign in with Twitter(Twitter認証を使用するか): ONにする
・ Website URL(自分のwebサービスのURL)
・ callback urls(Twitter認証後に遷移するURL): ローカル/本番環境など、複数設定が可能。
(例)
http://localhost:3000/users/auth/twitter/callback (ルーティングの確認)
http://localhost:3000/users/omniauth_callbacks (コールバック用コントローラのURL、認証後の遷移)
・ privacy policy, terms of serviceも何でもいいので埋める。

アプリ側の設定:gemとテーブルの準備

Gemfile
gem 'omniauth-facebook'                  # Facebook認証
gem 'omniauth-twitter'                   # Twitter認証
gem 'omniauth-google-oauth2'             # Google認証
gem 'omniauth-github'                    # GitHub認証
gem 'dotenv-rails'                       # 環境変数の管理
# gem 'omniauth-rails_csrf_protection'   # 脆弱性の対策用。。入れたら認証エラー!になったので、アンインストール。

# ターミナルでインストール
% bundle install --path vendor/bundle

必要なカラムをuserテーブルに追加。

ターミナル
% rails g migration AddOmniauthToUsers provider:string uid:string
% rails db:migrate

公開しない情報をpushしないにように設定する

  • API_KEYとAPI_SECRET を環境変数にする(gem(dotenv-rails))。
  • .env ファイルを「Gemfile」と同じ階層に手動で作成し、.gitignoreに追加する。
.gitignore
/.env
  • .env ファイルに、上でメモったKeyを環境変数に設定。
.env
TWITTER_API_KEY = 'API key を記述'
TWITTER_API_SECRET = 'API secret key を記述'

FACEBOOK_KEY = 'API key を記述'
FACEBOOK_SECRET = 'API secret key を記述'

GOOGLE_CLIENT_ID = 'API key を記述'
GOOGLE_CLIENT_SECRET = 'API secret key を記述'
  • 環境変数を使って、omniauth用を設定。
config/initializers/devise.rb
  config.omniauth :facebook, ENV['FACEBOOK_KEY']
  config.omniauth :twitter, ENV['TWITTER_API_KEY'], ENV['TWITTER_API_SECRET']
  config.omniauth :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET']

ルーティングの設定

routes.rb
devise_for :users, controllers: {
  omniauth_callbacks: 'users/omniauth_callbacks'
}

後は、モデルとコントローラーでメソッドを記述し、呼び出せるようにする。

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

docker rails db:migrateにてエラー(StandardError: An error has occurred, all later migrations canceled:)

Qiita初投稿となります。よろしくお願いします。

環境

  • image: mysql:5.7
  • FROM ruby:2.6.3
  • Rails 5.2.4.3

エラー

docker環境で構築したrailsにて、docker-compose exec web rails db:migrateとしたところ、以下エラー

rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Invalid use of NULL value: ALTER TABLE `tasks` CHANGE `name` `name` varchar(255) NOT NULL
....以下省略

原因

完全な特定には至らなかったが、以前行ったマイグレーションの処理がうまくいっていない可能性がある。テーブル作成周りでエラーが出ていた。
エラーのMysqlに関しては修正しているはず・・・。

解決方法

データベースのリセットを行う。

$ docker-compose exec web rails db:migrate:reset

再度マイグレーション

$ docker-compose exec web rails db:migrate

これで修復できました。確認の為、コンソールから正しくDB周りが動いてるか見るといいと思います。

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

ActiveModelで生成したオブジェクトのdeep copy

やりたいこと

タイトルのまま。ActiveModel::Modelで生成したオブジェクトをattribute含めて全て別のオブジェクトとして複製したい。

ActiveSupportのdeep_dupを試してみた

結論を書くとattributeまで複製されなかったので失敗。

class Test
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :name, :string
  attribute :age, :integer
end

original = Test.new(name: "Abe", age: 65)
clone = original.deep_dup

# 表面のオブジェクトは別物が生成
original.object_id # => 33487180
clone.object_id    # => 33536560

# でも属性は同じものを指している
original.name.object_id # => 33576180
clone.name.object_id    # => 33576180

Marshalしかないのか

オブジェクトの中身を全てダンプで吐き出して、それを再オブジェクト化するというワザ。これなら要素も複製できた。

original = Test.new(name: "Abe", age: 65)
clone = Marshal.load(Marshal.dump(original))

# 要素も異なるオブジェクトIDになっている。
original.name.object_id # => 34629860
clone.name.object_id    # => 34628880

他に方法があれば誰か教えて下さいm(_ _)m

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

Dockerでwheneverを扱う時No such file or directory - crontabが出る

簡単に定時処理が書ける便利なgem「whenever」

dockerでアプリ作成時、wheneverを使った処理をしようとしたが、つまづいてしまったので忘備録として記述しておきます。

環境

Ruby 2.5.1
Rails 5.2.4.3

やりたいこと

今回はpostというモデルを用意し、wheneverを使って1分事にpostを作成してみる。
dockerの環境構築は終わっているものとしてスタート。

modelとcontrollerを作成

docker上で

root@6181bdf78fa7:/myapp# bundle exec rails g model post name:string 
root@6181bdf78fa7:/myapp# bundle exec db:migrate
root@6181bdf78fa7:/myapp# bundle exec rails g controller posts

wheneverの設定

まずはgemをインストール

Gemfile
gem 'whenever', require: false

buildし直してgemをインストールしたらコマンドを実行してファイルを作成

root@6181bdf78fa7:/myapp# bundle exec wheneverize .
[add] writing `./config/schedule.rb'
[done] wheneverized!

作成されたschedule.rbに処理をかいていきます。

schedule.rb
require File.expand_path(File.dirname(__FILE__) + "/environment")
set :environment, :development
set :output, 'log/cron.log'
ENV.each { |k, v| env(k, v) }

every 1.minutes do
  runner "Post.create"
end

ここまできたら、cronに設定を反映させる

root@6181bdf78fa7:/myapp# bundle exec whenever --update-crontab
bundler: failed to load command: whenever (/usr/local/bundle/bin/whenever)
Errno::ENOENT: No such file or directory - crontab
  /usr/local/bundle/gems/whenever-1.0.0/lib/whenever/command_line.rb:77:in `popen'
  /usr/local/bundle/gems/whenever-1.0.0/lib/whenever/command_line.rb:77:in `write_crontab'
  /usr/local/bundle/gems/whenever-1.0.0/lib/whenever/command_line.rb:38:in `run'
  /usr/local/bundle/gems/whenever-1.0.0/lib/whenever/command_line.rb:6:in `execute'
  /usr/local/bundle/gems/whenever-1.0.0/bin/whenever:44:in `<top (required)>'
  /usr/local/bundle/bin/whenever:23:in `load'
  /usr/local/bundle/bin/whenever:23:in `<top (required)>'

エラーが出ましたね。
cron初心者の自分はここでつまづいてしまいました。

cronをインストール

どうやらdocker環境にcronをインストールしないといけないので、インストールに必要な処理をdockerfileに記述。
今回はこんな感じで1行追記しました。

FROM ruby:2.5.1
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN apt-get install -y cron  #この行を追記
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
root@6710f08a3504:/myapp# bundle exec whenever --update-crontab
[write] crontab file updated

無事updateされてcronに反映されました。
これで自動処理が始まってると思い、しばらく待ってみます…

…どうやら動いてないですね。
wheneverが作動していればclog/cron.logが作成されるはずなので。

cronを起動させる

cronが動いていないので状態を確認します。

root@827fe138767f:/myapp# service cron status
[FAIL] cron is not running ... failed!

やはり動いていませんでした。
起動しましょう。

root@827fe138767f:/myapp# service cron start 
[ ok ] Starting periodic command scheduler: cron.

1分後…

cron.log
Running via Spring preloader in process 122

ついにcron.logが生成されlogが書かれました。
rails consoleで確認します。

root@827fe138767f:/myapp# bundle exec rails c
Running via Spring preloader in process 135
Loading development environment (Rails 5.2.4.3)
irb(main):001:0> Post.all.count
   (4.5ms)  SELECT COUNT(*) FROM "posts"
=> 1

データが生成されたのがわかりますね!

課題

しかしcronの起動は手動で毎回行うのは面倒なので、できればdockerfileに記述して自動で起動されるようにしたいところです。
今後その方法も追記していきたと思います。

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

Dockerでwheneverを扱う時No such file or directory - crontabとなる

簡単に定時処理が書ける便利なgem「whenever」

dockerでアプリ作成時、wheneverを使った処理をしようとしたが、つまづいてしまったので忘備録として記述しておきます。

環境

Ruby 2.5.1
Rails 5.2.4.3

やりたいこと

今回はpostというモデルを用意し、wheneverを使って1分ごとにpostを作成してみる。
dockerの環境構築は終わっているものとしてスタート。

modelとcontrollerを作成

docker上で

root@6181bdf78fa7:/myapp# bundle exec rails g model post name:string 
root@6181bdf78fa7:/myapp# bundle exec db:migrate
root@6181bdf78fa7:/myapp# bundle exec rails g controller posts

wheneverの設定

まずはgemをインストール

Gemfile
gem 'whenever', require: false

buildし直してgemをインストールしたらコマンドを実行してファイルを作成

root@6181bdf78fa7:/myapp# bundle exec wheneverize .
[add] writing `./config/schedule.rb'
[done] wheneverized!

作成されたschedule.rbに処理をかいていきます。

schedule.rb
require File.expand_path(File.dirname(__FILE__) + "/environment")
set :environment, :development
set :output, 'log/cron.log'
ENV.each { |k, v| env(k, v) }

every 1.minutes do
  runner "Post.create"
end

ここまできたら、cronに設定を反映させる

root@6181bdf78fa7:/myapp# bundle exec whenever --update-crontab
bundler: failed to load command: whenever (/usr/local/bundle/bin/whenever)
Errno::ENOENT: No such file or directory - crontab
  /usr/local/bundle/gems/whenever-1.0.0/lib/whenever/command_line.rb:77:in `popen'
  /usr/local/bundle/gems/whenever-1.0.0/lib/whenever/command_line.rb:77:in `write_crontab'
  /usr/local/bundle/gems/whenever-1.0.0/lib/whenever/command_line.rb:38:in `run'
  /usr/local/bundle/gems/whenever-1.0.0/lib/whenever/command_line.rb:6:in `execute'
  /usr/local/bundle/gems/whenever-1.0.0/bin/whenever:44:in `<top (required)>'
  /usr/local/bundle/bin/whenever:23:in `load'
  /usr/local/bundle/bin/whenever:23:in `<top (required)>'

エラーが出ましたね。
cron初心者の自分はここでつまづいてしまいました。

cronをインストール

どうやらdocker環境にcronをインストールしないといけないので、インストールに必要な処理をdockerfileに記述。
今回はこんな感じで1行追記しました。

FROM ruby:2.5.1
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN apt-get install -y cron  #この行を追記
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
root@6710f08a3504:/myapp# bundle exec whenever --update-crontab
[write] crontab file updated

無事updateされてcronに反映されました。
これで自動処理が始まってると思い、しばらく待ってみます…

…どうやら動いてないですね。
wheneverが作動していればclog/cron.logが作成されるはずなので。

cronを起動させる

cronが動いていないので状態を確認します。

root@827fe138767f:/myapp# service cron status
[FAIL] cron is not running ... failed!

やはり動いていませんでした。
起動しましょう。

root@827fe138767f:/myapp# service cron start 
[ ok ] Starting periodic command scheduler: cron.

1分後…

cron.log
Running via Spring preloader in process 122

ついにcron.logが生成されlogが書かれました。
rails consoleで確認します。

root@827fe138767f:/myapp# bundle exec rails c
Running via Spring preloader in process 135
Loading development environment (Rails 5.2.4.3)
irb(main):001:0> Post.all.count
   (4.5ms)  SELECT COUNT(*) FROM "posts"
=> 1

データが生成されたのがわかりますね!

課題

しかしcronの起動は手動で毎回行うのは面倒なので、できればdockerfileに記述して自動で起動されるようにしたいところです。
今後その方法も追記していきたと思います。

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

[rails]redirect_toとrenderの違い

redirect_toとrenderの違い

初めの頃は違いなんて理解せずに使ってました。
処理の流れが違ったんですね。

redirect_toの場合

①controller(redirect_to) → ②HTTPリクエスト → ③ルーティング → ④controller → ⑤view

renderの場合

①controller → ②view

僕の感覚ではあるんですが、基本的にrenderは部分テンプレート以外であまり使わない気がします。

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

link_toの下線を消す

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

2020年8月3日 Progate Lv.226
aタグと同じようにlink_toの下線を消す。(メモ)
HTMLのリンクについてはこちらの記事で扱っている

方法

 1.link_toにクラスを付ける。

layouts/application.html.erb
<li>
  <%= link_to("User List", "/users/index", class:"userList") %>
</li>

 2. scssファイルまたはcssファイルで下線を消す処理をする

stylesheets/application.css
.userList{
  text-decoration: none;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

バリデーションを設定

バリデーションとは

パラメーターを受け取った時に該当カラムにデータが入っているか確認する機能です。

以下の例の場合、nameカラムがnil(データがない)であるかどうかを確認します。
nilだと保存されません。

app/models/user.rb
class User < ApplicationRecord

  validates :name, presence: true

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

[rails]バリデーションを設定

バリデーションとは

パラメーターを受け取った時に該当カラムにデータが入っているか確認する機能です。

以下の例の場合、nameカラムがnil(データがない)であるかどうかを確認します。
nilだと保存されません。

app/models/user.rb
class User < ApplicationRecord

  validates :name, presence: true

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