Ruby on Rails初心者が突破するべきこと一覧


環境構築


やりたいこと


  • railsなどのgemはプロジェクトごとにバージョン管理したい。

  • githubを基本利用する

  • mysqlを利用したい


前提


  • bundleはグローバルにインストールされてる


構築

mkdir project

cd project
bundle init
vim Gemfile
〜〜 gem 'rails'のコメントアウトを外す〜〜
bundle install --path=vendor/bundle
bundle exec rails new . -d mysql
〜〜 Gemfileは上書きしてOK〜〜
git init
vim gitignore
〜〜 https://www.gitignore.io/ を参照〜〜
git remote add origin hogehoge.git

rails newのオプションに関しては、

bundle exec rails new -hで参照してください。

ここではmysqlを指定しますが、デフォルトだとsqlite3になります。


知っておくべき基礎


routes.rb

root users#index

=> 初期画面

resources :posts

=> シンボリック、複数形

resources :posts do

resources :comments
end

=> postの内側にネストされたリソースとしてcommentsが作成される。


rails generate

bundle exec rails generate controller Users

=> 大文字、複数形

bundle exec rails generate model Post title:string

=> 大文字、単数形

=> DBは複数形となる。

bundle exec rails generate model Comment commenter:string body:text article:references

=> articleモデルと紐づけられる。

=> belongs_to :article

=> article_idというカラムを生成

=> article_idにインデックスを付与


データ取得

Post.all

=> 全てのデータを取得するメソッド。

Post.first

=> idがもっとも新しいデータセットを取得するメソッド。

Post.last

=> idがもっとも古いデータセットを取得するメソッド

Post.find

=> idを検索キーとしてデータを取得する。

=> 該当データがない場合エラーが返る。

Post.find_by()

=> idを含む様々な条件で検索するメソッド

=> 複数条件でも検索可能だが、結果は一件のみ。

=> 該当データがない場合nilが返る。

Post.where()

=> id以外の条件で検索するメソッド。

=> 該当するデータ全てが返ってくる。

Post.includes(:user)

=> N+1問題を解決してPostにUserをjoinしたデータが取得できる。


link_to

link_to('リンク名', posts_path)

link_to('リンク名', controller: 'posts', action: 'index'

=> 現在と同じコントローラのアクションにしない場合に利用される。

link_to('リンク先', '/posts')

<%= link_to('Destroy', post_path(post), method: :delete, data: { confirm: 'Are you sure?' }) %>

=> 削除時にアラート画面を出しながら削除。


Form

Rails5からform_tagform_forに代わってform_withが標準化される。

二つが統合したと考えて良くて、かなり構造的に似たものとなった。

<%= form_with url: post_path, scope: :post do |form| %>

<%= form.label :title %>
<%= form.text_field :title %>
<%= form.submit %>
<% end %>

=> scopeを使うことによって、params[:scope名][:title]みたいなアクセスの仕方ができる。

=> 要はパラメータをグループ化してくれる。

<%= form_with model: Post.new do |form| %>

<%= form.label :title %>
<%= form.text_field :title %>
<%= form.submit %>
<% end %>

=> modelを使う場合は、urlとscopeを自動的に推測してくれる。

参考


Strong parameters

データの受け渡しをパラメータでする際に、何のチェックもしないのは攻撃の絶好の対象となってしまうため対策する。

Railsにはそのセキュリティを高めるための考えとしてStrong Parametersというものがある。

なお、通常同一コントローラー内で複数回パラメータのやり取りはするため、共用できるようにメソッドを切り出し、なおかつprivateにすることが多い。

def create

@post = Post.new(post_params)
if @post.save
end
end

def update
@post = Post.find(params[:id])
if @post.update(post_params)
end
end

private
def post_params
params.require(:スコープ名).permit(変数名)
end


Error

生成するオブジェクト(インスタンス)にエラーがある場合、

そのインスタンスメソッドのerrorsを利用して要因特定ができる。

主に、モデルクラスのvalidatesなどの定義で問題があった場合に力を発揮する。

<% if @post.errors.any? %>

<%= pluralize(@post.errors.count, "error") occured %>
<ul>
<% @post.errors.full_messages.each do |error| %>
<li><%= error %></li>
<% end %>
</ul>
<% end %>

なお、エラーメッセージを含むフィールドは自動的にfield_with_errorsクラスを持つdivタグで囲まれます。

これを利用して、エラーメッセージをもっと目立たせるようにcssルールを定義できます。


Partial


方法1

アンダースコアつけたファイル名を作成。

_form.html.erbなどなど。

呼び出しは下記の通り。

<%= render 'form' %>


方法2

Nestingされている場合、下記のように呼び出すことができる。

views/comments/_comment.html.erbのパーシャルを、

<%= render @post.comments %>

なお、パーシャルの中では、commentという変数で紐づく内容を取得可能。


方法3

単純にviews/comments/_form.html.erbを下記のように呼び出すことも可能。

<%= render "comments/form" %>

ビューを出力しているだけなので、パーシャルでもインスタンス変数を利用可能。


Nesting

ルーティングなどでネストされた関係を構築すると、

書くコード量をかなり減らすことができる。


timestamp_migration_file.rb

def change

create_table :comments do |t|
t.string :commenter
t.text :body
t.references :article, foreign_key: true

t.timestamps
end
end



routes.rb

resources :articles do

resources :comments
end


models/article.rb

has_many :comments, dependent: :destroy


=> dependentを追加することで、記事が削除されたタイミングで関連するコメントも削除することができる。


models/comment.rb

belongs_to :article



controllers/articles_controller.rb

def show 

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


views/articles/show.html.erb

<%= form_with(model: [@article, @article.comments.build]) do |form| %>

...
<% end %>


controllers/comments_controller.rb

def create

@article = Article.find(params[:article_id])
@comment = @article.comments.create(comment_params)
...
end

private
def comment_params
params.require(:comment).permit(:commenter, :body)
end


参考