Webエンジニア目指して#51
どうもワクチンマンです。1回目は筋肉注射による筋肉痛だけでした。2回目はどうなるかな
さてrailsであれこれしているうちのエラー備忘録です。
rails error_I18n::InvalidLocaleData
ymlファイルのインデントが間違っていた。下の例が動作する記述例
attributes以降がインデント一つ分余分だったときにエラーが出た
あとはキーの定義で間に半角スペースを挟んでおらず反映されなかった
ja: activerecord: models: schedule: スケジュール attributes: schedule: title: タイトル start: 開始日 end: 終了日 allday: 終日 memo: メモ created_at: 作成日時 updated_at: 更新日時
herokuのデプロイエラー
作ったアプリをgithubとherokuなるものを使って公開する際に、デプロイを実行したら以下のエラーが出た
Your bundle only supports platforms ["x86_64-darwin-18"] but your local platform is x86_64-linux. Add the current platform to the lockfile with `bundle lock --add-platform x86_64-linux` and try again. Bundler Output: Your bundle only supports platforms ["x86_64-darwin-18"] but your local platform is x86_64-linux. Add the current platform to the lockfile with `bundle lock --add-platform x86_64-linux` and try again. ! ! Failed to install gems via Bundler. ! ! Push rejected, failed to compile Ruby app. ! Push failed
なにやらlockfileのplatformがどうとか書いてあるのでgemfile.lockを覗いてみると、それっぽいのを発見
エラー文の中にbundle lock --add-platform x86_64-linux
実行してね、みたいなのがあるので実行するとlockファイルにx86_64-linux
が追加された(わざわざコマンド打つってことは直書きだとまずい?)
これでOK!
以上、ではでは。
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: 一言紹介
これでエラー文が日本語になった
この辺で区切ります。ではでは
rubyで擬似的に発火キーを実装する
rubyであれこれしてるんですが、cui上でenterを押したら処理開始〜のようなものに最適そうなメソッドが見つからず早3日...
ようやくそれっぽいのを編み出しました、自信作です
require 'io/console'
でio/consoleライブラリを読み込んでSTDIN.getch
を使えるようにする
getch
はgets
と違い入力中の文字が表示されない+最後に入力された一文字だけ取得される
これとwhileを組み合わせて、Enter(rawモードのため¥r)が入力されるまで何も表示させず入力ループを起こさせる
require 'io/console' #STDIN.getch利用のため puts "1文字取得" while (str1 = STDIN.getch) != "\r" #Enterの入力受付(キー入力は表示されない) end if str1 == "\r" p str1 puts "Enterが入力されました" end
以上
Webエンジニア目指して#48
どうもご無沙汰マンです。 ポテパンキャンプに入りました。ある程度独学した人間にとっては昔と違って旨味が激減してしまいましたが、当初よりの予定なのでいたしかたなし... 斡旋入社でキャッシュバックがめちゃ魅力的だったんだけどな、前職1年でやめるべきでした
さて未来に目を向けていきましょう、PostgreSQLなるRDBMSを導入しました。 今までSQliteだったので純粋なSQL文以外が微妙に違くてむずがゆい GUIが有料でまあまあ値が張るものしかないので嫌ですね〜
グローバル変数
変数にも種類があって、変数名の先頭を$にすると別rbを読み込んだ際に共有されるグローバル変数になる
例
testA.rb
local = "A" $global = "A" require_relative "variableB" puts "ローカル変数" puts local puts "--------------------" puts "グローバル変数" puts $global
testB.rb
local = "B" $global = "B"
実行結果
testA.rbにて、$grobalを定義したあとにtestB.rbを読み込み、そこで$grobalの再定義がされるためputs $grobal
の結果は"B"になった
クラス変数
@@変数名
とすることでクラス内スコープの変数を定義できる
下の例のように継承しても共有できる
class Test @@class_name="クラス内定義" def set_name(name) @instance_name=name output() end def output puts "--------" puts "Testクラスによるインスタンスメソッド" puts "@@class_name=#{@@class_name}" puts "@instance_name=#{@instance_name}" puts "--------" end end class CopyTest < Test def output puts "CopyTestクラスによるインスタンスメソッド" puts "@@class_name=#{@@class_name}" puts "@instance_name=#{@instance_name}" end end testA=Test.new testA.set_name("インスタンスA") testB=CopyTest.new testB.set_name("インスタンスB")
実行結果
クラス変数の@@を@にしてみたり無くしてみたりしたが、動作しなかった。@@でちゃんとクラス変数として認識してくれるみたい
定数
変数名の頭を大文字にすると定数扱いになり、再定義ができなくなる。
Teisu = "定数" puts Teisu Teisu = "変更済定数" puts Teisu
配列の要素を追加する
array.push("")
とarray << ""
がある。
pushは複数要素を追加でき、<<は1つしか追加できない。
どちらも配列の末尾に追加される。
例
fruits1 = ["apple","banana","grape"] p fruits1 fruits1 << "orange" p fruits1 fruits2 = ["peach","lemon"] fruits1.push *fruits2 p fruits1
実行結果
並列の要素を削除する
array.delete_at(arrayNo.)で削除ができる
例
fruits1 = ["apple","banana","grape"] p fruits1 fruits1.delete_at(0) p fruits1 p fruits1[0]
実行結果
削除した配列番号を参照すると[1]だった要素が表示されることから、nilにはならず左詰めになることがわかる。
ハッシュの要素を削除する
fruits={ :name => "apple", :price => "500" } p fruits p fruits[:name] fruits.delete(:name) p fruits p fruits[:name]
実行結果
ループ処理のnext
nextが処理されると現在のループ処理をスキップし次のループ処理へ飛ぶ
例
for i in 1..10 do if i%9==0 p "9の倍数の出力でbreakによりループ処理を終了します" break p "出力確認" end if i%3==0 p "3の倍数の出力はnextによりスキップされます" next p "出力確認" end p i end
実行結果
next及びbreakによりp "出力確認"
は処理されない
例外処理
begin内でエラーが発生した際に、処理を終了させずrescure内の処理を実行し処理を継続させられる
例
begin number = 10 + nil p number rescue puts $! #エラー文を表示 puts $@ #エラー発生位置を表示 p "エラー発生、例外処理を実行します" end p "end"
実行結果
intにnilを足すことはできないためエラーが発生する。
それを検知しrescue内の処理が実行される。
モジュール
モジュールを定義してクラスへ適用(Mix-in)することができる 共通処理がある場合、同じコードを何回も書くことになるためモジュールでまとめるのがよさそう
例
module Math def add(a, b) return a + b end end class Number include Math #MathモジュールをMix-in attr_accessor :a , :b def initialize(a,b) @a = a @b = b puts "#{@a},#{@b}が生成されました" end end num = Number.new(6,1) p num.add(num.a, num.b)
実行結果
また、クラス以外でもモジュールは適用できる
例
module Math def add(a, b) return a + b end end num = {a:6, b:1} num.extend(Math) p num.add(num[:a], num[:b])
ディレクトリ内のファイル名を検索・取得
rubyでファイルを上書きする際に、ファイルが存在するかどうかを確認したい1
Dir.glob("ディレクトリとファイル名(ワイルドカード可)")
これを使えばディレクトリに対してファイル名を検索し、引っかかったファイル名の文字列を配列におさめてくれる
なお、引っかからなかった場合は空の配列empty
になる
例:オブジェクトがemptyかどうかを真偽値で返す.empty?
メソッドと合わせてみた
p "csvファイル名を入力してください" file_name = gets.chomp search_file = Dir.glob("./#{file_name}.csv") if search_file.empty? p "該当するファイルがありません" else p "以下のファイルが見つかりました" p search_file end
整数の乱数生成
下の例の場合、0,1,2,3をランダムに生成する
rand(3)
トピックの内容が濃くなってきたのでこの辺で区切ります
ではでは。
brew updateでDL先のURLが403を連発する件
mysqlの導入に当たって環境構築で躓いたので備忘録。
terminalでbrew install mysql
を実行すると
curl: (22) The requested URL returned error: 403 Forbidden Error: Failed to download resource "gettext" Download failed: https://homebrew.bintray.com/bottles/gettext-0.21.big_sur.bottle.tar.gz Warning: Bottle installation failed: building from source.
が出る。brew update
でも同様。
どうやら参照gitのリポジトリが古いらしい。
CLTを入れ直すといいらしいとの記事を見つけ実行。
sudo rm -rf /Library/Developer/CommandLineTools xcode-select --install sudo xcode-select -r
その後brew update
を実行すると新たなエラー文が。
Error: homebrew-core is a shallow clone. To `brew update`, first run: git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
誘導に従ってgit -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
を実行。特にエラーはなく色々と処理が行われた。
その後brew update
を実行したら成功した。
これで無事brew install mysql
によってmysql 8.0.26のインストールが成功した。
以上
Webエンジニア目指して#47
とあるサイトの模写をしてます。得た知見をメモっていきます
文字を縦横軸の中央に配置
display:flex +
align-items:center +
justify-content: center
cssによるグラデーション
border-image: linear-gradient(to right, #fff 0%, #000 100%);
幅や座標に計算値を使う
width: calc(100% - 50px);
before,after疑似要素
flexboxの要素間にスペースを設ける
display: flex +
justify-content: space-between
hover動作などスマホへのレスポンシブ表示時に不要なcssは@mediaでまとめると便利
どちらかというと知見
posituon:absoluteの要素に:hoverは効かない
どうやらそうらしい
cssで矢印を作る
角ボーダーを90度回転させると矢印になる
隣接セレクタにスタイル適用
p+p{margin-top:5px;} 上の例では、p要素が連続する場合にmarginが適用される
文字にグラデーション
background: -webkit-linear-gradient(0deg , #fff, #000);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
ネガティブマージン
margin:-20px;のようにするとボックスから指定の値だけ要素が飛び出る
flex-boxで並べた要素を並べ替える
対象要素にorder:1;など
flex-boxの末端に要素を配置
align-self: flex-end; 親のalign-itemを無視できる。
一区切りついたのでここまで。ではでは