20190701のRailsに関する記事は23件です。

Python on Djangoで基本的なCRUDとAuthを備えた家計簿を作る

リンク

https://github.com/ItoYo16u/django_crud

自分用メモ+α: 余裕があるときに追記します。

Djangoの構成

Djangoはプロジェクトレベルとアプリケーションレベルの層がある。

プロジェクトの中に家計簿のCRUDを実装したcrudアプリケーション、ユーザー認証機能を実装したaccountsアプリケーションをつくる。

追記したプロジェクト内のアプリケーションはmanage.pyと同じ階層にあるsettings.pyのINSTALLED_APPS内に追記する。

 Hello World

$ django-admin startproject <project_name>

gitignoreをmanage.pyと同じ階層に追加

.gitignore
*.pyc
*~
__pycache__
myvenv
db.sqlite3
/static
.DS_Store
$ git init
$ python3 manage.py createapp <app_name>
$ python3 manage.py migrate
$ python3 manage.py createsuperuser

python manage.pyとしている記事もあるが、Syntax errorになるのでpython3 manage.py...としている。

以下を追加

urls.py
from app_name import views

urlpatterns =[
  path('',views.index,name="index"),
  #.............省略............
  #.............省略.............
  path('app_name/',include('app_name.urls'))
]
app_name/urls.py
from django.urls import path
from . import views
app_name='app_name'
urlpatterns=[
  path('',views.index,name="index"),
# nameを指定しておくことでtemplates側から
# "{% url 'app_name:name'  %}"で呼び出せる。
# railsの場合、controller_name_method_name_pathが自動で設定される。便利。
]
views/index.py
def index(request):
  return HttpResponse("Hello, world.")
$ python3 manage.py runserver
GET localhost:8000/

基本的なCRUD

Create, Read, Update, Delete機能を作る。

Create

formのレイアウト設定がややめんどくさい。Railsの場合は、formのクラスやスタイルをviews(Djangoのtemplates)で指定できるが、Djangoの場合、forms.pyで設定しないといけないのでbootstrapなどのCSSフレームワークが使いづらい。

Read

views(Railsでいうコントローラ)内のメソッドにパラメタをリクエストと一緒に渡す。

views.py
def show(request,id=None):
    target= get_object_or_404(TargetModel.objects,pk=id)
    return render(request,"app_name/show.html",{'rec':rec})
# renderで変数をテンプレートに渡して、htmlをレンダリングして、返す。

Djangoはそんなに好きじゃないけど、get_object_or_404()はそこそこ便利


以下はRuby on Railsの場合

hoge_controller.rb
def show
  @target= TargetModel.find(params[:id]) #request parameterはparams[:params_name]で取得できる
  #あとは自動で、hoge/show.html.erbがレンダリングされて返される。
  # html以外を返す場合などは、renderメソッドを使って明記する
end

Update

Delete

Railsはlink_toにmethod: :DELETEを付与できるが、Djangoではできない。HTMLと同様にGETかPOSTしか送れない。
(ライブラリを使えばできるらしい)
DjangoのCRUDについて調べているとDELETEにGETを使っている記事がいくつか見つかるが、なるべくPOSTを使うべき。


※Railsの場合、

=link_to "hoge",foo_bar_path,method: :delete
routes.rb
DELETE 'foo/bar' ,to: 'foo#bar'
foo_controller.rb
def bar
  # 処理内容
end

と直感的に書けるが,Djangoの場合はそうはいかないようだ。


基本的なAuth

Djangoにデフォルトで搭載されているUserモデルとAuthを使う。

Ruby on Railsの場合、デフォルトでは認証機能はないのでdeviseというgemを導入して、devise:installなどのコマンドをうったり、ルーティング設定したりしないといけないのでややめんどくさい。
基本のユーザーは

from django.contrib.auth.models import User

で呼び出せる。

今回は家計簿なのでモデルは

  • User has many 家計簿
  • 家計簿 belongs to User

の関係にある。

Djangoのデフォルトの認証viewsのメソッドが用意されているが、SignUpだけは用意されていないので、自前で作る必要がある。

sign up用のviewをつくる

アクションを認証済ユーザーに制限する

@login_required #をアクションの直前につける

3.リダイレクトを設定する

@login_required #がついている場合,自動でリダイレクト
# リダイレクト先はsetting.py LOGOUT_REDIRECT_URL で指定する
# 2と3はRuby on Railsの場合こう書ける
before_action :authenticate_user! #オプション,only: [:method_name],except: [:method_name],....

共通部分のpartial化

header, footerなどの共通部分は、Railsと同じようにpartial化できる。(Djangoの場合、partialというよりも、継承といったほうが正しいが、、、)

PythonAnywhereにデプロイする

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

$ rails g controller で作られたはずのコントローラが見つからない

3行で

  • なぜかゴミ箱の中の同名アプリの中に作られていた
  • 一度削除したアプリと同じ名前のアプリだとエラーになるっぽい
  • ゴミ箱を空にして $ spring stop を実行してから作ることができた

( ´∀`)<詳しく書きますね

コントローラを作ったけど

railsでコントローラを作成するためには、ターミナルで下のコマンドを入力しますね

$ rails g controller コントローラ名

すると、たしかに

  create  app/controllers/コントローラ名.rb

という結果が返ってくるんですが、ディレクトリを見ても作られたはずのコントローラが見つかりません。

同じ状況の人がいないか検索した

こちらの記事を見つけました。

rails generateコマンドでモデルを生成したはずなのにファイルがない
https://teratail.com/questions/8672

「まさか」と疑いつつ、自分のゴミ箱を見ると、現在作成中のアプリケーションと同名の、過去に消したアプリケーション(なんらかの事情で作り直すつもりで消しました)の app/controllers/ ディレクトリから、上記で作成したコントローラが出てきました(理由はわかっていませんが、知ってる方がいたら教えていただきたいです)。

試み 1

かといってゴミ箱のアプリのディレクトリからそのコントローラのみを持ってくるのはよくないと思いました。なぜなら $ rails g controller コントローラ名 によって作られるのはコントローラだけではないからです。あなたもぼくと同じく、Railsの中身についてよくわかっていないのならば、なおさらやめたほうがいいでしょう。
まず、ゴミ箱を空にしてから、再度ターミナルでコマンドを実行することにしました。

$ rails g controller コントローラ名

すると、ターミナルが固まってしまい、強制終了コマンドなども受け付けない状態になってしまいました。
あまりやりたくはないのですが、仕方がないのでターミナルのウインドウの✗ボタンを押して終了させました。

試み 2

『rails g controller フリーズ』で検索し、参考になりそうなものを探しました。その中からひとつだけピックします。

rails generateがハングアップする
https://qiita.com/mom0tomo/items/b3f6c34f48c5dcaef78b

いくつかの記事にも「 ctrl + c で強制終了すると下記のエラー文が現れた」とありましたが、ぼくの場合は ctrl + c が効かなかったので、エラー文が現れることはありませんでした。

もう一点共通しているのは、どうも spring というものが影響している、ということでした。これを止めてみることにします。
ターミナルで下記のコマンドを入力します。

$ spring stop

その後、あらためて

$ rails g controller コントローラ名

を入力すると、無事、現在作業中のアプリケーションの app/controllers/ にコントローラが作成されました。
ちなみに

$ spring status

と入力すると

Spring is running:

となっているため、ストップを解除してあげるといった作業は必要無さそうです。

まとめ

やみくもに試みて直した感じもあるので、正攻法とは言えないのかもしれません(記事どおりの再現でも無かったですし)。
spring がなんなのかも正直よくわかっていませんが、ぼくと同じく作り直しグセのある初学者の方にワラのようでも助けになれば幸いです。

( ´∀`)<読んでくれてありがとう

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

【Rails】カラムの合計値を求める!

やりたいこと

保存されているデータの特定のカラムの合計値を出したい!と思いました。
最初考えたのは、

①取得したいカラムのモデルをeach文で1件ずつ取得し、そのデータのカラムを一度配列にする
②↑の配列に対してsumメソッドで合計を求める

これでも全然問題なかったのですが、
sumメソッドの引数で直接カラム名を指定し、合計値を求めることも出来ると知ったのでまとめます!

カラムの合計を求める方法①

これは私がもともと考えていたやり方です。

test.rb
#booksテーブルのpriceカラムの合計値を求めたい場合
array = [] #空の配列を用意し、
Book.all.each do |book|
  array << book.price 
  #bookテーブルのレコードを1件ずつ取り出し、priceカラムのデータを配列に入れる
end
array.sum #ここで合計を求める

カラムの合計を求める方法②

次に、もっと簡単な1行でできるやり方です。

test.rb
Book.all.sum(:price)

これだけでいけました。
sumメソッドの引数でカラムを指定できるとは知らなかったです!
とても楽ですね:relaxed:

また、さらにオプションを付けることもできます!
興味のある方はぜひこちらのサイトをご参考ください!
http://railsdoc.com/references/sum

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

GitHub リポジトリの作成方法(ローカル環境)

新規作成したアプリのリポジトリをGitHub上で作る

まずは、アプリの作成(今回はデータベースにポスグレを使用)

$ rails new (アプリ名) -d postgresql

GitHubにアクセス

①new repositoryボタンを押す。

②リポジトリ名を決めて、Create repositoryボタンを押す。

GitHubとローカルをSSH接続

SSHという認証技術を使用して、GitHubとローカルをSSH接続する。
⇨セキュリティの脆弱性の観点から、一般的には公開鍵認証方式を使用。
(ここで、公開鍵秘密鍵という概念が出てくるが、ここでは説明は割愛)

SSH keyの作成

$ ssh-keygen -t rsa -C "GitHubに登録した自分のメールアドレス"

Overwrite (y/n)?の箇所で、yを入力しEnterを押すと、秘密鍵と公開鍵が作成される。
id_rsaというファイルが秘密鍵で、id_rsa.pubが公開鍵。

公開鍵の登録とGitHubとの接続確認

公開鍵をGitHubに登録する。
catコマンドを使用するとファイルの中身が確認できるので…

$ cat ~/.ssh/id_rsa.pub

上記コマンドを実行すると、ssh-rsaから始まり、自分のメールアドレスで終わる長い文字の羅列が表示される。「ssh-rsa」からメールアドレスの末尾までをすべてコピー。

GitHub上に公開鍵を置く

①ヘッダ右上の自分の画像をクリックして、settingをクリック。

SSH and GPG keysをクリックし、さらにNew SSH Keyをクリック。

スクリーンショット 2019-07-01 22.30.46.png

keyのところにコピーした公開鍵の中身を貼り付ける。

スクリーンショット 2019-07-01 22.34.07.png

GitHubとの接続が正常にできているか確認

# 接続確認コマンド
$ ssh -T git@github.com
# 接続結果
Hi (GitHubの登録名)! You've successfully authenticated, but GitHub does not provide shell access.

このように表示されたら、基本的には接続成功!!!

GitHubのリポジトリにソースコードを送信する

GitHubリポジトリの送り先SSHプロトコルURLを取得

ローカル上で、送り先のSSHプロトコルURLをGitHubからコピー。
(SSHプロトコルURLは、git@から始まる。
httpsから始まるURLは、パスワード認証方式でアクセスすることになる。)

GitHubのリポジトリを登録する

ローカル上で、GitHubリポジトリの送り先SSHを登録する。
⇨git remote addコマンドを使用。

$ git remote add origin(=省略名) (コピーしたSSHプロトコルURL)
$ git remote -v
# 送り先SSHの確認例
origin  git@github.com:〜 (fetch)
origin  git@github.com:〜 (push)

git pushコマンドの利用

登録したリモートリポジトリ(GitHubリポジトリ)に、ソースコードを送信する。

$ git push origin(=省略名) ブランチ名

⬇︎こうするとmasterブランチへコードが送信される。

$ git push origin master

…以上が、ローカル環境下で書いたソースコードを、作成したリポジトリに送信する流れ

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

GitHub リポジトリの作成方法

新規作成したアプリのリポジトリをGitHub上で作る

まずは、アプリの作成(今回はデータベースにポスグレを使用)

$ rails new (アプリ名) -d postgresql

GitHubにアクセス

①new repositoryボタンを押す。

②リポジトリ名を決めて、Create repositoryボタンを押す。

GitHubとローカルをSSH接続

SSHという認証技術を使用して、GitHubとローカルをSSH接続する。
⇨セキュリティの脆弱性の観点から、一般的には公開鍵認証方式を使用。
(ここで、公開鍵秘密鍵という概念が出てくるが、ここでは説明は割愛)

SSH keyの作成

$ ssh-keygen -t rsa -C "GitHubに登録した自分のメールアドレス"

Overwrite (y/n)?の箇所で、yを入力しEnterを押すと、秘密鍵と公開鍵が作成される。
id_rsaというファイルが秘密鍵で、id_rsa.pubが公開鍵。

公開鍵の登録とGitHubとの接続確認

公開鍵をGitHubに登録する。
catコマンドを使用するとファイルの中身が確認できるので…

$ cat ~/.ssh/id_rsa.pub

上記コマンドを実行すると、ssh-rsaから始まり、自分のメールアドレスで終わる長い文字の羅列が表示される。「ssh-rsa」からメールアドレスの末尾までをすべてコピー。

GitHub上に公開鍵を置く

①ヘッダ右上の自分の画像をクリックして、settingをクリック。

SSH and GPG keysをクリックし、さらにNew SSH Keyをクリック。

スクリーンショット 2019-07-01 22.30.46.png

keyのところにコピーした公開鍵の中身を貼り付ける。

スクリーンショット 2019-07-01 22.34.07.png

GitHubとの接続が正常にできているか確認

# 接続確認コマンド
$ ssh -T git@github.com
# 接続結果
Hi (GitHubの登録名)! You've successfully authenticated, but GitHub does not provide shell access.

このように表示されたら、基本的には接続成功!!!

GitHubのリポジトリにソースコードを送信する

GitHubリポジトリの送り先SSHプロトコルURLを取得

ローカル上で、送り先のSSHプロトコルURLをGitHubからコピー。
(SSHプロトコルURLは、git@から始まる。
httpsから始まるURLは、パスワード認証方式でアクセスすることになる。)

GitHubのリポジトリを登録する

ローカル上で、GitHubリポジトリの送り先SSHを登録する。
⇨git remote addコマンドを使用。

$ git remote add origin(=省略名) (コピーしたSSHプロトコルURL)
$ git remote -v
# 送り先SSHの確認例
origin  git@github.com:〜 (fetch)
origin  git@github.com:〜 (push)

git pushコマンドの利用

登録したリモートリポジトリ(GitHubリポジトリ)に、ソースコードを送信する。

$ git push origin(=省略名) ブランチ名

⬇︎こうするとmasterブランチへコードが送信される。

$ git push origin master

…以上が、ローカル環境下で書いたソースコードを、作成したリポジトリに送信する流れ

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

Ruby on railsとは?

Railsの事前カリキュラム

どんな記事?

ruby on railsとはなんなのか?ということ自分の中でアウトプットするための記事です、どうか暖かく見守ってください

ruby on railsとは?

ruby on railsは簡単にいうとWebアプリケーション開発を開発するためのフレームワークです。

ここではそもそもフレームワークが何なのかとrailsで使われているコーディングをするシステム(MVCモデル)、rubyとの違いを勉強していきます。

フレームワーク

フレームワークとは、Webアプリケーションを機能させるために必要な共通部分を予め用意するものになります。

アプリケーションの開発者は独自に必要なHTML/CSSやRubyの記述に時間を割くことができるので、開発効率が向上します。

MVCモデル

Railsではユーザーからのリクエスト->ビュー->コントローラー→モデルの順番に処理が行われます。

このようにモデル(model)とビュー(view)とコントローラー(controller)を使用して処理を行なうシステムをそれぞれの頭文字を取ってMVCモデルと呼ばれています。

以下の図に処理の流れを簡単にまとめました。

MVC画像

rubyとruby on railsの違い

よく間違えられるのですがRuby on Railsはプログラミング言語ではないです。

プログラミング言語は、前テキストで学んでいただいたと思うのですが他にはpythonやJava,Cなどがありましてその名の通りプログラムを実装・実行するための言語です。

例えば、前テキストでRubyを使い足し算や掛け算などの計算、条件に合わせたプログラムの実行、配列作成などを行なったと思います。

一方でフレームワークであるRailsは足し算などをすることはできません。

ruby on railsでできること

webアプリケーション開発

インターネット上に公開されているWebサイトはRuby, Ruby on Railsを使って作ることが可能です。

RubyとRuby on Railsを使ってWebサイトを作るメリットはRuby on Railsというフレームワークによる開発スピードです。

Ruby on Railsは非常によく出来たフレームワークで、Webアプリケーションの開発をするために最適化されたツールになります。

ここではRuby, Ruby on Railsで開発されているwebサービスをいくつか紹介します。

クックパッド

クックパッド画像
引用元:クックパッド https://cookpad.com/

マネーフォワード

マネーフォワード画像
引用元:マネーフォワード https://moneyforward.com/

Airbnb

Airbnb画像
引用元:Airbnb https://www.airbnb.jp/

スマートフォンアプリ開発

iOSアプリの開発はobject-cやswift、Androidアプリの開発はJavaやKotlinが一般的です。

しかしRubyでも「RUBYMOTION」(http://www.rubymotion.com/jp/)

というソフトを使うことにより、AndroidアプリやiOSアプリを開発することが可能になります。

ruby on railsの特徴

初心者に優しい

ruby on railsが初心者に優しい理由は主に2つあります

1つはシンプルにコーディングできることです。

Railsはコードが短く、簡単な書き方ができます。

それによりコーディング量が少なくなり、短く速い開発を行うことができるメリットがあります。

また次に説明するDRYの原則により、同じコードを何度も繰り返して使うことなく、規約に従った開発を行うことにより自分で設定を行うことなくコーディングを行えます。

これはコードを読んだり書いたりすることの慣れていない初学者には大きなメリットになります。

2つ目はrubyが日本発祥の言語だということです。

これにより日本語の情報がオンラインで豊富に手に入ります。

また、コミュニティが活発で初心者でも非常に学びやすい環境が整っています。

例えばruby on railsを使ってオリジナルのアプリケーションを作っている中で遭遇したことのない様なエラーが出たとしても

そのエラーに遭遇している人をオンライン上で見つけることが簡単なので素早くエラーを解決しアプリケーション開発を行うことができます。

DRY (Don’t Repeat Yourself)原則

Ruby on Railsには、「Don’t Repeat Yourself(繰り返しを避けよ)」というDRY原則という原則があります。

DRY原則とは、自分でやった事を2度繰り返さないという意味です。

同じことをソースコードやファイルの中で何度も記述すると、アプリケーションの仕様変更などがあった時に、一部を変更し忘れてしまう可能性があります。

少しイメージがつきづらいと思うので例を出して説明していきたいと思います。

例えば今ここで

今hour時です       #hourは変数で中身は数字です

という文字列を100回出力したいとします、みなさんだったらどのようにコードを書くでしょうか?

まさかputsメソッドを使って100回出力しないですよね、基本的にはwhileやfor文を使って繰り返しをさせます。

ではなぜputsメソッドを使って100回出力させない方がいいのでしょうか?

例えば上記の文字列を

今hour時minutes分です       #minutesは変数で中身は数字です

に変更したいとしましょう、繰り返し構文を使っていないコードを変更するとしたら100回も変更を加えなければなりません。

ただ繰り返しの構文を使っているとしたらその中の文字列1行を変更するだけですみます。

このようにRuby on Railsでは、DRY原則を意識して開発することで、効率の良いアプリケーションを作成することができます。

直感的にデータベースを操作することができる

そもそもデータベースとは?

データベースとは一定の形式で整理されたデータの集まりです、現実世界にあるデータベースの例を出すとタウンページなどがわかりやすいと思います。

タウンページは基本的に場所名+電話番号が整理された形でずっと並んでいますよね。

コンピューターの中にもタウンページのようにデータが整理され集合がありましてそれをデータベースと言います。

一般的にデータベースを扱う場合、データベース言語「SQL」を書く必要があります。

SQL言語とはデータベースを操作するための言語です。

例えばTwitterなどを思い浮かべて見てください、Twitterにログインが成功した時には自分のユーザー情報が表示されますよね。

これはユーザーの情報が入っているデータベースに対してSQL言語を書くことによってユーザー情報を表示することができています。

ではこれを直感的に操作できるとはどういうことか

例えば、データベースのproductsテーブルからプロダクトIDが1のデータを取得する場合、SQLを使うと以下のように書かなければいけません。

 SELECT * FROM products WHERE id = 1

しかしRailsアプリケーションでデータベースを扱う場合は、SQLを書く必要がなく

@product = Product.find(1)

という1行を記述するだけで、データを取得することができます。

これから学習していくテキストの中でもデータベースを扱う場面が多々あると思うのですが

ruby on railsを使っていることで上記の様に直感的にデータベースを扱うことができるようになります。

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

TECH ~Day8~

学習内容
・ビュー(view)、コントローラ(controller)、ルーティング(routing)
・mysql
・Gem
・rails console

・ビュー(view)、コントローラ(controller)、ルーティング(routing)
ビュー(view)
ページの「見た目」を作るためのHTMLファイル。
ブラウザとRailsのやり取りの中で、Railsからビュイーが返され、ページが表示される。
ビューの内容がブラウザに表示されるもの。

コントローラ(controller)
コントローラはルーティングからビューへと処理を受け渡す役割を持つ。
ページを表示するときにRailsの中ではコントローラを経由してビューをブラウザに返す。
コントローラ内のメソッドを「アクション」と呼ぶ。

(例)
 class ~~~~~~~
  def top
  end
 end
!def~endまでの形を「アクション」と呼ぶ。

・mysql
mysqlとはデータベースの一種である。

・Gem
Railsはgemと呼ばれる便利なrubyライブラリをインストールし、利用することで、より簡単にアプリケーション開発できるようになる。
全てをゼロから作るよりもgemのライブラリも利用することでより効率的に開発できる。
gemの追加方法
 gemfileを編集し、ターミナルでbundle installコマンドを実行する。

・rails console
これはrubyコードを手軽に実行できる環境である!!!
(タ) $ rails console ←起動

学習八日目に入り、ついにrailsのカリキュラムに入りました。rubyの内容と似ているのかと思いきや、rubyのコードを書くまでの環境づくりや、rubyを混ぜ込んだrailsでの様々な書き方が新しく出てきたことによって、また色々な可能性が広がってきたように感じます。
ここからさらに学習し、様々なパターンの使い方を身に付けたいと思います。

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

pluckでテーブル間で重複したカラム名を指定する

リファレンス

http://railsdoc.com/references/pluck

pluckは便利

便利ですが、

  • table_atable_bname という同名のカラムがある
  • table_a, bを join する
  • 任意のテーブルのnameカラムを指定して取得したい(場合によっては両方)

この場合、どう指定すれば良いでしょうか?
リファレンスからは読み取りづらい状態です。

エラー例

TableA.join(:table_b).pluck(:name)

# Mysql2::Error: Column ‘name’ in field list is ambiguous: SELECT ...

結論

  • 名前が重複している場合、シンボルを使わずに、テーブル名.カラム名 で指定します。
  • シンボルを使うとうまくいかないです。
  • 名前が被っているのを両方指定しても大丈夫です。
Model.pluck('table_a.name', 'table_b.name')

参考

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

今日学んだ事(自分用)

7/1(月)

●UI(ユーザーインターフェース)

・ユーザーがPCとやりとりする際の入力や表示方法などの仕組み

●UX(ユーザーエクスペリエンス)

・サービスによってユーザーが得られる体験

───────

●アジャイル開発

・ソフトウェア開発のプロジェクトの進め方。短期間で開発を見直す手法。

●erb記法

・HTMLにRubyスクリプトを埋め込む

●スクリプト

・プログラムの流れ
1.プログラミング(人間の言葉でコンピュターへの命令を記述する)
2.コンパイル(1で書いた内容をPCがわかる言葉に翻訳する)
3. 2の内容にしたがってPCが仕事する
・スクリプト言語は2のコンパイルを飛ばし
プログラミング⇨PCが仕事する流れ

●eachメソッド

・要素を1つずつ取得し出力させる

オブジェクト.each do |変数|
例.
fruits = ["apple","orange","melon"]
 fruits.each do |a|
puts a
end

出力
apple
orange
melon

・このような繰り返しメソッドを、イテレートまたはイテレータという。

●order(順序)メソッド

・DBからデータの取得時にデータを並び変える事ができる
・DESC(降順)
・ASC(昇順)
コード

モデル名.order('カラム名 順序')

●limitメソッド

・データをいくつ取得するか指定するメソッド
コード

モデル名.limit('取得件数')

●orderメソッドとlimitメソッドを一緒に使う時

モデル名.order('カラム名 順序').limit(取得件数)

●find(見つける)メソッド

・引数に指定したidをもつ情報を1件だけ取得する
・作品の個別ページの移行の時などに使う

例.
User.find(1)

●rake routesコマンド

・HTPPアクションの一覧を見る事ができる
・リクエスト、パスに対してのコントローラ、アクション名が確認できる

ターミナル.
rake routes

以上

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

Jenkinsのジョブが長すぎてメモリリークした時の対処法

経緯

1時間半程かかるrspecのテストをJenkinsで実行したところ、途中でJenkinsが落ちてしまった。
再度テスト実行して落ちる寸前でfreeコマンドを確認したところメモリのusedが595(約0.5Gb)になっていたため、メモリが枯渇したのだと思いメモリ開放について調べてみた。

Tl; DR

slabキャッシュの開放

echo 2 > /proc/sys/vm/drop_caches

実行前

$ free -tm
             total       used       free     shared    buffers     cached
Mem:          7884       7289        595         37        474       1699
-/+ buffers/cache:       5115       2768
Swap:            0          0          0

実行後

$ free -tm
             total       used       free     shared    buffers     cached
Mem:          7884       4686       3198         37        475        289
-/+ buffers/cache:       3922       3962
Swap:            0          0          0

freeが595(約0.5Gb)->3198(約3Gb)になりました!
さらに定期実行できるようにcronに設定。

sudo su # rootで実行
crontab -e
# 毎時0分にキャッシュクリア
0  * * * * echo 2 > /proc/sys/vm/drop_caches

Jenkinsのメモリリークについて考察

jenkinsのジョブを実行し続けるとメモリの空きが減ってくる。
おそらくslabキャッシュというkernelがdentry等をキャッシュするために使うメモリ領域が多くなっているため。
slabキャッシュは以下コマンドで開放する。

echo 2 > /proc/sys/vm/drop_caches

参考

https://bacchi.me/linux/server-memory-troubleshoot/

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

active storage で単数から複数にした時に気をつけるべきポイント

N+1 問題を解決するためのスコープを複数形にする

.with_attached_image

.with_attached_images

受け取るパラメータを配列にする

params.require(:reports).permit(:content, :image)

params.require(:reports).permit(:content, images: [])

アソシエーションを複数形にする

has_one_attached :image

has_many_attached :images

バリデーションを複数形にする

こちらのバリデーションは下記のgemを使用した例です
activestorage-validator

validates :image, blob: { content_type: %w(image/png image/jpg image/jpeg) }

validates :images, blob: { content_type: %w(image/png image/jpg image/jpeg) }

番外編

Active Interaction で静的型付けをする場合、string ではなく array にする

デフォルトが nil だとエラーになるので注意してください

string :image, default: nil

array :images, default: []
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

記事を投稿・詳細表示・一覧表示・編集・削除するやり方について

環境

OS:MacOS Mojave 10.14.15
IDE:Cloud9
ruby:2.6.3
Rails:5.0.7.2

準備

routing作成

まずはルーティングを準備していきます。

routes.rb
resources :aritcles

正しく反映されているか、rails routesコマンドで確認してみましょう。

console
$ rails routes
Prefix Verb   URI Pattern                  Controller#Action

    articles GET    /articles(.:format)          articles#index
             POST   /articles(.:format)          articles#create
 new_article GET    /articles/new(.:format)      articles#new
edit_article GET    /articles/:id/edit(.:format) articles#edit
     article GET    /articles/:id(.:format)      articles#show
             PATCH  /articles/:id(.:format)      articles#update
             PUT    /articles/:id(.:format)      articles#update
             DELETE /articles/:id(.:format)      articles#destroy

正しく反映されていますね。
しかし、この状態でリクエストを送ろうとすると以下の画像のようにルーティングエラーが発生します。
スクリーンショット 2019-06-29 15.19.34.png

このエラーの原因は「リクエストを処理するためのコントローラーがないため」です。
なので、次はarticlesコントローラーを作成します。

articlesコントローラーの作成

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

console
$ rails g controller articles
Running via Spring preloader in process 9066
      create  app/controllers/articles_controller.rb
      invoke  erb
      create    app/views/articles
      invoke  test_unit
      create    test/controllers/articles_controller_test.rb
      invoke  helper
      create    app/helpers/articles_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/articles.coffee
      invoke    scss
      create      app/assets/stylesheets/articles.scss

articlesコントローラーが作成されました。
しかし、このままではarticlesコントローラーに対するアクションが作成されていないので、URLにリクエストを送っても、Unknow actionエラーが返されてしまいます。
なので、次はactionを指定します。(一旦、newアクションだけを指定していきます。)

/training/app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  def new

  end
end

/articles/newでアクセスしてみます。
すると、今度は以下のようなエラーが発生します。
スクリーンショット 2019-06-29 15.50.23.png

ArticlesController#missing a templateはarticlesコントローラーのnewアクションに対応するテンプレート、つまりビューがないために起こるエラーです。

なので、今度は対応するviewを作成します。

console
$ touch app/views/articles/new.html.erb

エラーは解消されたと思いますが、入力されたデータを送信して管理する場合は、モデルを作成してDBとやり取りする必要が生じてくるので、Articleモデルを作成していきます。

Articleモデルの作成

今回は、articlesテーブルにtitleカラムとcontentカラムを用意したいので以下のコマンドを実行してArticleモデルを作成します。

console
$ rails g model Article title:string content:text
Running via Spring preloader in process 4656
      invoke  active_record
      create    db/migrate/20190630012101_create_articles.rb
      create    app/models/article.rb
      invoke    test_unit
      create      test/models/article_test.rb
      create      test/fixtures/articles.yml

続いて、出来上がったマイグレーションファイルを実行していきますが、その前に作成したマイグレーションファイルに誤字等ないか確認します。

/training/db/migrate/hogehoge_create_articles.rb
class CreateArticles < ActiveRecord::Migration[5.0]
  def change
    create_table :articles do |t|
      t.string :title
      t.text :content

      t.timestamps
    end
  end
end

問題なさそうなことが確認できたので以下のコマンドでマイグレーションを実行していきます。

console
$ rails db:migrate
== 20190630012101 CreateArticles: migrating ===================================
-- create_table(:articles)
   -> 0.0060s
== 20190630012101 CreateArticles: migrated (0.0065s) ==========================

articlesテーブルが作成されたことが確認できたので、次からはそれぞれ機能ごとに必要な処理をモデル、コントローラー、ビューに実装していきます。
※ルーティングは既に揃っているので加えて作成する必要はありません。

記事を投稿・詳細表示する

articleコントローラーにnew,create,showアクションを追加していきます。

/training/app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  def new
    #空のArticleオブジェクトを生成
    @article = Article.new
  end

  def create
    @article = Article.new(article_params)
    if @article.save
      redirect_to @article #@articleはarticle_path(@article)と同義
    else
      #エラー時は再度、記事登録画面を表示させる
      render :new
    end
  end

  def show
    @article = Article.find(params[:id])
  end

  private
    #ストロングパラメータでpermitに渡された値以外を受け取らないようにする
    def article_params
      params.require(:article).permit(:title,:content)
    end
end

newアクション内で空っぽのArticleクラスのインスタンスを作る理由は、form_forメソッドに空のインスタンス渡された時は、submitした時にcreateアクションが実行されるように設定されているからです。
反対に、空でない場合はupdateアクションが実行されます。

まだこれだけだと、showアクションに対応するviewが足りていないのでそれを作ります。

console
$ touch app/views/articles/show.html.erb

続けてviewも登録した内容が分かるように書いていきます。

/training/app/views/articles/show.html.erb
<table>
  <tbody>
        <tr>
            <th>タイトル</th>
            <td><%= @article.title %></td>
        </tr>
        <tr>
            <th>内容</th>
            <td><%= @article.content %></td>
        </tr>
  </tbody>  
</table>

ここまで作ったら実際に記事登録画面(article/new)でtitleに「hoge」、contentに「hogehoge」と入力して送信ボタンを押してみましょう。

スクリーンショット 2019-06-30 15.43.07.png

↑こんな感じでDBに登録された値がうまく表示されていないでしょうか?

記事を一覧表示する

articleコントローラーにindexアクションを追加してallメソッドで登録されている値を全て取り出し@articlesに格納します。

/training/app/controllers/articles_controller.rb
class ArticlesController < ApplicationController



def index
    @articles = Article.all    
end
  private
    def article_params
      params.require(:article).permit(:title,:content)
    end
end

indexアクションに対応するviewがないので作成して、登録された値が全て確認できるようにviewを調整します。(次の「記事を編集する」で使用する編集リンクを先に実装しています。したがって、今はエラーが出ても問題ありません)

console
$ touch app/views/articles/index.html.erb
/training/app/views/articles/index.html.erb
<table>
  <tbody>
      <tr>
          <th>タイトル</th>
          <th>内容</th>
      </tr>
      <% @articles.each do |article| %>
      <tr>
          <td><%= article.title %></td>
          <td><%= article.content %></td>
          <td><%= link_to '編集',edit_article_path(article) %></td>
      </tr>
      <% end %>
  </tbody>  
</table>

適当に記事登録画面で何か追加してみて/articlesにアクセスするとこれまで作成したデータが一覧で表示されます。

スクリーンショット 2019-07-01 10.35.56.png

記事を編集する

articlesコントローラーにeditアクションとupdateアクションを追加し、それに対応するviewを追加していきます。

/training/app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
 ・
 ・
 ・
  def edit
    @article = Article.find(params[:id])
  end

  def update
    @article = Article.find(params[:id])
    if @article.update(article_params)
      redirect_to @article
    else
      render :edit
    end
  end
  
 ・
 ・
  private
    def article_params
      params.require(:article).permit(:title,:content)
    end
end

console
$ touch app/views/articles/edit.html.erb
/training/app/views/articles/edit.html.erb
<h1>編集画面</h1>
<%= form_for @article do |f| %>
  <p>
    <%= f.label :title, "タイトル" %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :content, "内容" %><br>
    <%= f.text_area :content %>
  </p>

  <p>
    <%= f.submit %>
  </p>
<% end %>

findメソッドで該当する記事をDBから取り出し、それを@articleに格納して、view(edit.html.erb)のform_forメソッドに渡します。
この時、form_forメソッドに渡されたインスタンス変数には空ではなく値が入っているため、送信ボタンを押下時にはupdateアクションが実行されます。

記事を削除する

articlesコントローラーにdestroyアクションを追加します。

/training/app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
 ・
 ・
 ・
  def destroy
    @article = Article.find(prams[:id])
    if @article.destroy
      redirect_to articles_path
    else
      redirect_to article_path(@article)
    end
  end
 ・
 ・
 ・
end

リンク押下時に削除できるように一覧画面のviewに削除リンクを追加していきます。

<table>
  <tbody>
      <tr>
          <th>タイトル</th>
          <th>内容</th>
      </tr>
      <% @articles.each do |article| %>
      <tr>
          <td><%= article.title %></td>
          <td><%= article.content %></td>
          <td><%= link_to '編集',edit_article_path(article) %></td>
          <td><%= link_to '削除',article_path(article),
                          method: :delete,data: {confirm:'削除してもいいですか?'}%></td>
      </tr>
      <% end %>
  </tbody>  
</table>

methodオプションでhttpメソッドをdeleteに指定してあげることで、確認ダイアログのOKボタンが押された時に、destroyアクションが実行されます。

補足

今回は、要点をまとめるために記事を作成したためArticleモデルにバリデーションやリレーションを追加したりや入力箇所(newやedit)の重複部分をパーシャルを使ってまとめたりはしておりません。
なので、その辺りは適宜カスタマイズしていただきますようよろしくお願いします。

最後に

誤っている箇所や追記した方が良い点等ございましたら
編集リクエストやコメントの方でご指摘していただけると幸いです。

参考
Railsを始めたばかりの人向け!Railsの仕組みを一から理解しながらブログを作成する

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

【Rails 備忘録】デプロイする時に定番で使うコマンド

はじめに

備忘録です。

デプロイで使うコマンド

前提条件として、
AWS EC2環境/var/www/app/ 配下でgit cloneさせます。

git clone

言わずもがなgit cloneです。

git pull

言わずもがなgit pullです。

bundle install

bundle install --path=vendor/bundle --without development test

assets precompile

bundle exec rails assets:precompile RAILS_ENV=staging

migrate

bundle exec rails db:migrate RAILS_ENV=staging

rails server起動

bundle exec rails s -e staging -d

rails server停止

ps aux | grep rails (rails s -e staging -d のプロセスidを見つける)
kill プロセスid

rails コンソール

bundle exec rails c -e staging

ちなみに

上記はstaging環境でのコマンドとなります。
production環境の場合、stagingproductionに変更すればOK。

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

modelの作成と削除、Railsで指定可能なデータ型

Railsのデータベースとのやりとりを担うmodel。その作成と削除方法、Railsで指定可能なデータ型についてまとめます。

1.modelの作成方法

ターミナルで次のコマンドを実行すると必要なファイルを自動的に作成することができます。

$ rails generate model モデル名 カラム名:データ型 カラム名:データ型 ・・・

データ型については、後述します。
以下のファイルがcreateされます。

  • app/models/モデル名.rb
  • db/migrate/yyyymmddhhmmss_create_モデル名.rb

この情報でデータベースを作成する(マイグレーション)には以下のコマンドを実行します。

$ rails db:migrate

2.modelの削除方法

手動で作成された2ファイルを削除することもできますが、作成したファイルをまとめて削除するには次のコマンドを実行します。

$ rails destroy model モデル名

これで先程generateで作成された2ファイルは削除されます。

3.Railsで指定可能なデータ型

カラムを作成するときのデータ型についてまとめました。

データ型 用途
binary バイナリデータ 画像、ファイルなど
boolean Boolean フラグ
date 日付 YYYY-MM-DD
datetime 日時 YYYY-MM-DD HH:MM:SS
decimal 固定小数点 1.000001
float 浮動小数点 1.00000234
integer 整数 1 , 10 ,9999
primary_key 主キー
string 文字列 255文字までの文字列
text 長い文字列 256文字以上の文字列
time 時間 HH:MM:SS
timestamp タイムスタンプ 1970-01-01 00:00:01 UTC
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails6 のちょい足しな新機能を試す43(ActiveRecord Cache編)

はじめに

Rails 6 に追加されそうな新機能を試す第43段。 今回は、 ActiveRecord Cache 編です。
Rails 6 では、 has_manybelongs_to などの関連がある model の reload 時の ActiveRecord のキャッシュに関連する動作が修正されています。 reload しているのに、データベースから読み直されず、キャッシュの古い値が取得されてしまう動作がなくなり、一貫性が感じられる動作になっています。

Ruby 2.6.3, Rails 6.0.0.rc1, Rails 5.2.3 で確認しました。Rails 6.0.0.rc1 は gem install rails --prerelease でインストールできます。

$ rails --version
Rails 6.0.0.rc1

プロジェクトを作る

$ bin/rails new rails6_0_0rc1
$ cd rails6_0_0rc1

モデルを作る

has_manybelongs_to の関係を作るため、 Author, Book, Edition の3つのモデルを作成します。

本 ( Book ) には1人の著者 ( Author ) がひもづき ( belongs_to )、複数の版 ( Edition ) が存在します。

$ bin/rails g model Author name
$ bin/rails g model Book title author:references
$ bin/rails g model Edition name book:references

has_many を追加する

AuthorBook にそれぞれ has_many を追加します。

app/models/author.rb
class Author < ApplicationRecord
  has_many :books, dependent: :destroy
end
app/models/book.rb
class Book < ApplicationRecord
  belongs_to :author
  has_many :editions, dependent: :destroy
end

db:migrate を実行する

一旦、ここで、 db:migrate をしておきます。

$ bin/rails db:create db:migrate

Controller と View を作る

Book controller と index View を作ります。

$ bin/rails g controller books index

初期データを登録するメソッドを定義する

BooksController に初期データを登録するプライベートメソッド initialize_data を作成します。
毎回同じデータでテストできるように、一旦、データを削除してから、 Author , Book , Edition のデータを作成するようにします。

app/controllers/books_controller.rb
class BooksController < ApplicationController
  ...
  private

  def initialize_data
    Author.first&.destroy
    author = Author.create(name: 'Dave Tomas')
    book = Book.create(title: 'Pragmatic Programer', author: author)
    Edition.create([{ name: '1st', book: book }, { name: '2nd', book: book }])
  end
end

model に値を修正するメソッドを追加する

各モデルにそれぞれの値を更新するメソッドを追加します。
普通にDBの値を更新すると、今回の事象が確認できないので、Threadを作って、Thread の中で更新します。
Thread#join を使って更新が終わるまで待つようにします。

Book モデルの title を更新するメソッドを追加します。

app/models/book.rb
class Book < ApplicationRecord
  ...
  def self.fix_title
    Thread.start do
      Book.where(title: 'Pragmatic Programer').update(title: 'Pragmatic Programmer')
    end.join
  end
end

同じように、Author モデルの name を更新するメソッドを追加します。

app/models/author.rb
class Author < ApplicationRecord
  ...
  def self.fix_name
    Thread.start do
      Author.where(name: 'Dave Tomas').update(name: 'Dave Thomas')
    end.join
  end
end

Edition モデルにも name を更新するメソッドを追加します。

app/models/edition.rb
class Edition < ApplicationRecord
  ...
  def self.fix_name
    Thread.start do
      Edition.where(name: '2nd').update(name: '20th Anniversary Edition')
    end.join
  end
end

book.reload のキャッシュの動作を試すメソッドを作る

book.reload のキャッシュの動作を試すプライベートメソッドを作ります。
book.reload の前に booktitle を更新します。

app/controllers/books_controller.rb
class BooksController < ApplicationController
  ...
  private
  ...
  # try book.reload
  def try_book_reload
    book = Book.first
    @old_title = book.title
    Book.fix_title
    @new_title = book.reload.title
  end
end

book.reload_author のキャッシュの動作を試すメソッドを作る

book.reload_author のキャッシュの動作を試すプライベートメソッドを作ります。
book.reload_author の前に authorname を更新します。
更新の前後で、 Author.find を呼び出します。

app/controllers/books_controller.rb
class BooksController < ApplicationController
  ...
  private
  ...

  # try book.reload_author
  def try_book_reload_author
    book = Book.first
    author_id = Author.first.id
    @old_author_name = Author.find(author_id).name
    Author.fix_name
    @reloaded_author_name = book.reload_author.name
    @new_author_name = Author.find(author_id).name
  end
end

book.editions.reload を試す

book.editions.reload のキャッシュの動作を試すプライベートメソッドを作ります。
book.editions.reload の前に editionname を更新します。

app/controllers/books_controller.rb
class BooksController < ApplicationController
  ...
  private
  ...

  # try book.editions.reload
  def try_book_editions_reload
    book = Book.first
    @old_editions = book.editions.reload.map(&:name)
    Edition.fix_name
    @new_editions = book.editions.reload.map(&:name)
  end
end

index メソッドを修正する

index メソッドを修正します。
これまで作ったプライベートメソッドを順に呼び出します。
index は GET メソッドなので、データを登録したり更新したりするのは RESTful ではないので、良くないです。
今回は動作確認のためなので、見逃してください。

app/controllers/books_controller.rb
class BooksController < ApplicationController
  def index
    initialize_data

    try_book_reload
    try_book_reload_author
    try_book_editions_reload
  end
  ...
end

View を作成する

Controller で求めた値を表示するように View を修正します。

app/views/books/index.html.erb
<h1>Books#index</h1>

<table>
  <thead>
    <tr>
      <th>variable</th>
      <th>value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>@old_title</td>
      <td><%= @old_title %></td>
    </tr>
    <tr>
      <td>@new_title</td>
      <td><%= @new_title %></td>
    </tr>
    <tr>
      <td>@old_author_name</td>
      <td><%= @old_author_name %></td>
    </tr>
    <tr>
      <td>@reloaded_author_name</td>
      <td><%= @reloaded_author_name %></td>
    </tr>
    <tr>
      <td>@new_author_name</td>
      <td><%= @new_author_name %></td>
    </tr>
    <tr>
      <td>@old_editions</td>
      <td><%= @old_editions %></td>
    </tr>
    <tr>
      <td>@new_editions</td>
      <td><%= @new_editions %></td>
    </tr>
  </tbody>
</table>

Rails 5 では

画面を表示すると以下のようになります。
データを更新していますが、 @new_author_name の値と @new_editions の値は変わっていません。
キャッシュが働いているためです。
rails5.png

Rails 6 では

画面を表示すると以下のようになります。
@new_author_name の値と @new_editions の値は更新後の値に変わっています。

rails6.png

試したソース

試したソースは以下にあります。
https://github.com/suketa/rails6_0_0rc1/tree/try043_query_cache

参考情報

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

Let's Encrypt 更新したのに、期限切れ

現象

Railsで作成したサイトで、Let's Encryptを使ってSSL化をしていた。
pemの参照はRailsのpuma.rbで管理していた。
しかし、更新前の期限が来た時に「この接続は保護されておりません」と
表示されてしまいました。

原因

Nginxが古い情報をキャッシュしていたため。
SSLのpemファイルの参照はRails側で行っていましたが、
その情報をNginx側でキャッシュしていました。

対策

Nginxを再起動しましょう。
再起動
sudo nginx -s reload

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

Webpacker 3 → 4

Rails5.2で使っている webpacker を3系から4系にアップデートしようとしたところ、ほとんどデフォルト環境で使っているにも関わらずいくつか作業が必要だったのでメモしておきます。

Gemfile

まずgemのバージョンを上げます。2019/7/1現在だと4.0.7が最新でした。

gem 'webpacker', '~> 4.0'
$ bundle install

Webpackerを再インストール

環境を綺麗にするため、一度インストールし直します。
色々聞かれますが、全部上書きしちゃいます。

$ bundle exec rails webpacker:install

Vueも入れ直します。

$ bundle exec rails webpacker:install:vue

設定ファイル変更

  • .babelrc
  • .postcssrc.yml

これらのファイルはそれぞれ babel.config.jspostcss.config.js に置き換えられたようなので削除します。

$ rm .babelrc .postcssrc.yml 

Pug

テンプレートエンジンとしてPugを使っていたんですが、webpackのloaderが置き換わったようなので対応します。

$ yarn remove pug-loader
$ yarn add pug-plain-loader
config/webpack/loaders/pug.js
module.exports = {
  test: /\.pug$/,
  use: [{
    loader: 'pug-plain-loader'
  }]
}
config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const vue = require('./loaders/vue')
const pug = require('./loaders/pug')

environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
environment.loaders.prepend('vue', vue)
environment.loaders.prepend('pug', pug)
module.exports = environment

動作確認

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

Webpacker 3 -> 4

Rails5.2で使っている webpacker を3系から4系にアップデートしようとしたところ、ほとんどデフォルト環境で使っているにも関わらずいくつか作業が必要だったのでメモしておきます。

Gemfile

まずgemのバージョンを上げます。2019/7/1現在だと4.0.7が最新でした。

gem 'webpacker', '~> 4.0'
$ bundle install

Webpackerを再インストール

環境を綺麗にするため、一度インストールし直します。
色々聞かれますが、全部上書きしちゃいます。

$ bundle exec rails webpacker:install

Vueも入れ直します。

$ bundle exec rails webpacker:install:vue

設定ファイル変更

  • .babelrc
  • .postcssrc.yml

これらのファイルはそれぞれ babel.config.jspostcss.config.js に置き換えられたようなので削除します。

$ rm .babelrc .postcssrc.yml 

Pug

テンプレートエンジンとしてPugを使っていたんですが、webpackのloaderが置き換わったようなので対応します。

$ yarn remove pug-loader
$ yarn add pug-plain-loader
config/webpack/loaders/pug.js
module.exports = {
  test: /\.pug$/,
  use: [{
    loader: 'pug-plain-loader'
  }]
}
config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const vue = require('./loaders/vue')
const pug = require('./loaders/pug')

environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
environment.loaders.prepend('vue', vue)
environment.loaders.prepend('pug', pug)
module.exports = environment

動作確認

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

Railsでpublic以下の静的ページ(404.htmlといったエラーページ等)をデプロイ時に生成するgemを作った

はじめに: 404.htmlや500.htmlといったエラーページをhtmlで直接書くのって面倒じゃないですか?

Railsでは独自デザインの404ページや500ページをpublic/404.htmlpublic/500.htmlに置くことができます。
ただし、このファイルは静的なファイルなので、HTMLやCSSも静的にしなければなりません。
そのためデザインをサイト全体で合わせようとして、以下のようにHTML内にがんばって静的なCSSを埋め込んだりしているケースもあるのではないでしょうか?

public/404.html
<html>
  <head>
    <style type="text/css">
      // コンパイル済みのapplication.cssからコピペした自前のCSSが何百行も並んだり
      // ...
      // ...
      // ...
    </style>
    <!-- もしくはpublic以下に専用のcssファイルを用意したり -->
    <link rel="stylesheet" media="all" href="/css/errors.css" />
  </head>
  <body>
    <h1>404 Not found</h1>
    <p>ページが見つかりません。</p>
  </body>
</html>

この問題を解決するために、hanmotoというgemを作りました。
このgemは弊社ソニックガーデンの複数のプロジェクトで1年以上、本番利用されてきた実績があります。

今回の記事ではこのgemの概要と使い方を紹介します。

何が出来るの?

  • hamlやslimを使って静的ページが書ける
  • WebpackerやSprocketsで生成したcssをそのまま使える
  • Layoutファイルを使ってエラーページをDRYに管理できる
  • link_to等のヘルパーが使える
  • public以下にファイルが吐き出されるので、railsが死んでも表示出来る

インストール

Gemfile
gem 'hanmoto'
$ bundle install

使い方

404.htmlの例

レイアウトを用意

app/views/layout/public.html.haml
!!!
%html
  %head
    %title #{yield(:title)} | MyAPP
    = stylesheet_pack_tag 'application', media: 'all'
    = favicon_link_tag '/favicon.ico'
  %body
    = yield

ビューを用意

app/views/public_pages/404.html.haml
- provide(:title, 'Not found')
%h1 Not found
%p This webpage is not found.
%p= link_to 'Home', root_path

public以下にファイルを生成

$ rake assets:precompile

OR

$ rake hanmoto:publish

.gitignorepublic/404.htmlを追加しておいて、デプロイ時にrake assets:precompileまたはrake hanmoto:publishを実行するという使い方を想定しています。

出力結果

public/404.html
<!DOCTYPE html>
<html>
<head>
<title>Not found | MyAPP</title>
<link rel="stylesheet" media="all" href="/packs/css/application-cc5b8b21.css" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
</head>
<body>
<h1>Not found</h1>
<p>This webpage is not found.</p>
<p><a href="/">Home</a></p>
</body>
</html>

htmlファイル以外の例

robots.txtを動的に生成する場合

app/views/public_pages/robots.text.erb
<% unless Rails.env.production? %>
User-Agent: *
Disallow: /
<% end %>

設定

config/initializers/hanmoto.rb
Hanmoto.configure do |config|
  # ビューファイルを置くディレクトリを変更したい場合は指定してください
  # config.view_dir = 'public_page'

  # レイアウトファイルを変更したい場合はファイルタイプ別に指定してください
  # config.layouts = {
  #   html: 'public',
  # }
end

その他

仕組み

Herokuでも使える?

RailsアプリをHerokuにデプロイすると自動的にrake assets:precompileが実行されるので、特に意識する必要なく利用できます。

gemの名前の由来

publicに書き出す -> publisher -> 版元

リポジトリ

https://github.com/aki77/hanmoto

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

配列のメソッドまとめ!

こんにちは!

最近雨模様が続いてますね...

梅雨が明けて真夏の日々が待ち遠しいです:relaxed:(←夏生まれ)

はい!

今回は、ブロックを扱う配列のメソッドの中でも、特に使用頻度の高いメソッドをまとめていきます!

それではLet's GO!

mapメソッド

mapメソッドは各要素に対してブロックを評価した結果を新しい配列に返します!

具体例を交えながら説明していきますね!

例えば、以下のように配列の各要素に5を足した新しい配列を作るコードがあります。

sample.rb
numbers = [0,1,2,3,4,5]
plus_numbers = []
numbers.each do |number|
  plus_numbers << number + 5
end

plus_numbers #=> [5,6,7,8,9,10]

ここでmapメソッドの登場です!!!

mapメソッドを使うと、ブロックの返り値が配列の要素となる新しい配列が形成されるため、mapメソッドの返り値をそのまま変数に入れることができます!

それでは見てみましょう!

sample.rb
numbers = [0,1,2,3,4,5]
plus_numbers = numbers.map do |number|
  number + 5
end

plus_numbers #=> [5,6,7,8,9,10]

selectメソッド

selectメソッドは、各要素に対してブロックを評価して、その返り値が真の要素を集めた配列を返すメソッドです!

同じく具体例を交えながら説明していきますね!

例えば、以下のようにすると、"e"を含んだ値だけを集めた配列を新たに作ることができます!

sample.rb
colors = ["red","blue","yellow","black"]
new_colors = colors.select do |color|
  color.include?('e')
end

new_colors #=> ["red","blue","yellow"]

rejectメソッド

rejectメソッドはselectメソッドの反対で、ブロックの返り値が真になった要素を除外した配列を返します!

例えば、以下のようにすると、"e"を含んだ値を除いた配列を新たに作ることができます!

sample.rb
colors = ["red","blue","yellow","black"]
new_colors = colors.reject do |color|
  color.include?('e')
end

new_colors #=> ["black"]

findメソッド

findメソッドは、ブロックの返り値が真になった最初の要素を返します!

例えば、以下のようにすると、"e"を含んだ最初の要素を返します!

sample.rb
colors = ["red","blue","yellow","black"]
new_colors = colors.find do |color|
  color.include?('e')
end

new_colors #=> ["red"]

以上となります!

配列のメソッドは使い方次第でとても便利なので知っておくだけでもかなり幅が広がると思いました!

何かご意見等ございましたら、お気軽にコメントお願いします!

ご静聴ありがとうございました!:relaxed:

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

gemでエラーは出た時の1つの解決方法(メモ書き)

gemをインストールした直後などにエラーが発生した時は、とりあえずrails s(サーバー)を立ち上げ直すことが1つの解決方法である。

特に、deviseというgemに関するエラーは、だいたいrails s(サーバー)を立ち上げ直せば、解決できることが多い。

したがって、gemをインストールした直後のエラーなどは、とりあえずrails s(サーバー)を立ち上げ直すことをやっておくと良い。

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

validationの日本語化

実行環境

Ruby: 2.5.1
Rails: 5.2.3

日本語に変換

デフォルトでは、英語でエラーが書かれていて下のように日本語にしたい。

スクリーンショット 2019-07-01 01.26.27.png

エラーメッセージを日本語にするには、以下を追加してbundle install

Gemfile
gem 'rails-i18n'

次にconfig/application.rbに以下を追加

config/application.rb
module KotoKoto
  class Application < Rails::Application

    config.i18n.default_locale = :ja

  end
end

次にconfig/locales以下にja.ymlを作成します。そこで記述する文は任意のモデルによって変えてください。例としてuserモデルで書いています。

locales/ja.yml
ja:
  activerecord:
    attributes:
      user:
        email: メールアドレス
        password: パスワード
        password_confirmation: 確認用パスワード
        remember_me: 次回から自動的にログイン
        name: 名前
        nickname: ニックネーム
        introduction: 自己紹介

userと書いているところは自分が指定したいモデル名。それ以下のemailなどはモデルのカラム名に適宜、日本語を設定してください。

参考文献

以下のurlで詳しく書かれています。
https://qiita.com/Ushinji/items/242bfba84df7a5a67d5b

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

RubyonRailsにまつわるマインドマップをsvgにしたよ

https://qiita.com/jnchito/items/063e332cbe3023f52f93
こちらに載っているマインドマップのソースを探していたのですが削除されているようで自分で作り直してみました。

jap.png

svg形式はこちら

記事を元に日本語化して、リンクを入れてクリックするだけでgoogle検索に移動するようにしました。

これ作るときに使ったmindmupはgoogleと連携しやすくていいなと思ってたけどsvg出力するときにテキストが壊れちゃって残念な感じになってしまった。mindmapソフトガチャ失敗?

一応
mindmupのソース
英語版
元のマインドマップではどのソフトを使っていてどうやったらあんな風になるのか知りたい。

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