Webエンジニア目指して#49
どうも運動不足マンです。 出勤や構内を歩くのってかなり運動になっていたんだなあと感じてます。
さあ毎日やっていることが固定なのでネタが特にありません、技術的な話に参りましょう
rubyの課題は終わらせました。全て一発合格であまりにもさらっといって逆に不安です
というわけでrails編です。progateである程度はやったので思い出し+追加ですね
partial
htmlの共通パーツを作っておいて使い回せる
以下のようなやり方でできるが、viewsディレクトリにsharedフォルダを作りそこにpertialを格納するのが一般らしい
views/shared/_partial.html.erb
<p>partial</p>
views/main.html.erb
<%= render "shared/partial" %>
指定ファイルの.html.erbは省略でOK
sqliteのコマンド
$.tables
作成済テーブルの確認
$.schema テーブル名
テーブルの定義確認
ctrl+z
.quitコマンドの代わり
CRUD処理の記述省略
こう書くと対象コントローラーに省略実装できる(actionは手動で記述が必要)
Rails.application.routes.draw do resources :コントローラー名 end
さらに、メソッドでroute指定する際に以下のような例で指定できるようになる
<%= link_to "ユーザー情報一覧", :users %>
各アクションによって割り当てられるハッシュが違い、またupdateやdestroyなどのアクションはhttpメソッドを指定する必要があるためその都度確認したい
routing定義の確認
resourcesのように省略記述した際はroutes.rbでは詳細を確認できないため、
$rails routes
でCUIから確認する
なにやら色々出てくるので見たいところだけ抜粋
form_forメソッド
progateではform_tagメソッドで下記のように記述しデータの受け渡し、データベースとのやりとりをしていた
<%= form_tag("/users/#{@user.id}/update",{multipart:true}) do %> <p>ユーザー名</p> <input name="name" value="<%= @user.name %>"> <p>e-mail</p> <input name="email" value="<%= @user.email %>"> <p>プロフィール画像</p> <input type="file" name="image"> <p>-</p> <input type="submit" value="変更"> <% end %>
form_forを使えば、以下のように書けばその次のようにhtml変換される
(@users = User.all)
<%= form_for @user do |f| %> <%= f.text_field :name %> <% end %>
↓
<input type="text" name="user[name]" id="user_name">
paramsメソッド
今まではparams[:id]
のようにform_tagメソッド内のname属性から拾った情報を使っていたが、form_forメソッドの場合は下記のように記述できる
@user = User.new(params.require(:user).permit(:name, :email))
paramsメソッドにはrequireメソッドとpermitメソッドがチェーンでき、
requireで対象テーブルのインスタンスを指定→permitで編集できるキーの指定をする。
これによって指定したオブジェクトでなければエラーを吐くため、意図しないキーの編集を防ぐことができるためストロングパラメータと呼ぶらしい
form_forめっちゃ便利...
created_atなどの時間情報を日本時間に変える
1.config/application.rbを開くとモジュールの中に入ったクラスが1つある
そこに下記の通り書いてある見本がある
# config.time_zone = "Central Time (US & Canada)"
これのコメントアウトを外してconfig.time_zone = 'Tokyo'
に書き換える
2.config/initializersディレクトリにtime_formats.rbを作成し、以下のように書く
Time::DATE_FORMATS[:datetime_jp] = '%Y年 %m月%d日'
3.view中の時間を表示するオブジェクトに.to_s(:datetime_jp)
をつける
<%= user.updated_at.to_s(:datetime_jp) %> <%= user.created_at.to_s(:datetime_jp) %>
4.サーバーを再起動する
config/initializerはサーバー起動時に参照されるそう
結果
updateメソッド
レコードに対して値の更新をするメソッド
これにもストロングパラメータを渡すのが良いらしい
@user.update(params.require(:user).permit(:name, :email))
data-confirm
link_toメソッドなどの引数にdata: { confirm: "メッセージ" }
のように使うとポップアップアラートを表示させられる
下の例のようにdestroy処理などの不可逆処理の警告に使う
<%= link_to "削除", user, method: :delete, data: { confirm: "本当に削除しますか?" } %>
ちなみにこれは参照と同じリンク先になっているが、httpメソッドを指定することでdestroyアクションを呼び出すことになっている
モデルの関連付け(一対多)
railsではアソシエーションというらしい 例えばuserモデルにpostモデルを関連付けるなら、userに対し多数のpostを持つことになり、postに対し多数のuserは紐付かない。その場合は次のように書く
user.rb
class User < ApplicationRecord has_many :posts end
post.rb
class Post < ApplicationRecord belongs_to :user end
これを行うことで、あるuserのpostを全て表示したい場合は以前は以下のように書いていたが
@posts = Post.where(user_id: @user.id)
関連付けによって以下のように書けるようになる
@posts = @user.posts
postのuserは以下のように書けるようになる
<%= @post.user.name %>
モデルの関連付け(多対多)
多対多の例は、postに対しuserのfavが追加されるパターン
favがあると1つのpostに対してのuserが一意に決まらないため、2つのテーブルだとfav用のカラムが半無限に増えてしまう(このpostにはこのユーザーがfavしました、のようなカラム)
このような多対多の場合はfavテーブルを作って中間テーブルにする。
下記が例
user.rb
class User < ApplicationRecord has_many :posts has_many :posts, through: fav end
post.rb
class Post < ApplicationRecord belongs_to :user has_many :user, through: fav end
fav.rb
class Fav < ApplicationRecord belongs_to :user belongs_to :post end
has_many :favでも書けるが、例のようにthroughを使った書き方をするとpost<=>user間のダイレクトアクセスが可能となる
hidden_field
扱いたいが表示はしたくないパラメータがある場合に使える
下の例の場合は以前やったsession変数でもよさそう
<%= f.hidden_field :user_id, value: @user.id %>
renderメソッドで変数を渡す
以下のようにすると変数smpがtestパーシャルで使えるようになる
<%= render "shared/test", smp: @user %>
バリデーションなどのrailsメッセージを日本語化する
rails-i18nというgemで実装できる。 i18nはInternationalizationの略で、国際化の意味らしい
まずはgemfileに記述しbundle install
する
gem 'rails-i18n'
config/application.rbに以下の記述をする
config.i18n.default_locale = :ja
これでエラー文が日本語化される
このNameやEmailなどのキーを日本語で表示するには、yamlという構造定義ファイルで定義する必要がある
config/localesディレクトリにja.ymlを作成し以下のように書く
ja: activerecord: models: user: ユーザー attributes: user: name: 名前 email: メールアドレス age: 年齢 introduction: 一言紹介
これでエラー文が日本語になった
この辺で区切ります。ではでは