Webエンジニア目指して#35

どうも筋肉痛マンです 思い出したようにワイドスクワットしたら足がヨボヨボになりました

ようやく退職証明書が届いたので色々と動ける!!1月後半はまあまあニート生活になってましたね

のんびりしてると貯金が尽きるので頑張っていこうと思います

というわけでProgateのRails IIです

2個目のcontroller生成

特に気にすることはなくrailsコマンドを使えば生成できる

役割が別のページはcontrollerを分けたほうがいいみたい

$ rails g controller sample aiueo

generategで略せる

html.erb内で変数宣言をする

.erbはembedded rubyから略されてたんですね

このファイルはrubyの埋め込みが可能で、
<% %>で囲うとページでの表示なし、
<%= %>で囲うとページでの表示ありでrubyのコードを記述できる

表示なしを利用して変数宣言などをして、
表示ありを利用して変数の値の出力をする

<% message1="こんにちは" %>
<%= message1 %>
配列とeach文でテキストを表示する

こんな感じで埋め込みとhtmlを織り交ぜることもできる

<% messages=[
  "メッセージ1",
  "メッセージ2"
] %>
<% messages.each do |message| %>
  <div class="messages-entire">
    <%= message %>
  </div>
<% end %>
controller actionにrubyを記述する

一般的には変数の定義はactionで記述するらしい

controller

class PostController < ApplicationController
  def index
    @messages=[
      "メッセージ1",
      "メッセージ2"
    ]
  end
end

html.erb

<div class="main">
      <% @messages.each do |message| %>
        <div class="messages-entire">
          <%= message %>
        </div>
      <% end %>
</div>

こんな感じで@変数名で扱うことでviewとcontrollerで相互的に使える @変数は配列に限らずなんでも使えるっぽい

データベースを用意する

migraionファイルの生成

まずはmigrationファイルというデータベースに指示を出すファイルを生成
railsコマンド$ rails g model テーブル名 カラム名:データ型

$ rails g model post message:text

今回は文字を入れるのでデータ型はtext

生成される場所はここ f:id:misokatsu_sand:20210211192140p:plain

中身はrubyで何やら書かれていますがまだわからないのでメモは割愛

class CreatePosts < ActiveRecord::Migration[6.1]
  def change
    create_table :posts do |t|
      t.text :message

      t.timestamps
    end
  end
end

テーブルの生成

先程のmigrationファイルを使ってデータベースに変更指示を出す

$ rails db:migrate

migrationファイルを作ったらmigrateをしないとどのviewを開いてもエラーが出るそう
migration errorが表示されるのでその際はmigrateが必要

modelの確認

migrationファイルの生成でmodelというものが下図のフォルダに作られている f:id:misokatsu_sand:20210211195720p:plain

中身はこれだけ

class Post < ApplicationRecord
end

ApplicationRecordを継承したクラスのことをmodelというらしい これがあることで生成したPostテーブルが操作できる

rails consoleでテーブルにレコードを追加する

rails consoleはrubyのコードを入力してEnterをするとその結果をすぐ出力するもの
終了するまでは定義した変数に代入した値など覚えてくれる
↓こんなやつ f:id:misokatsu_sand:20210212003833g:plain

これを使って、
変数=モデル名.new(カラム名:"文字列")を実行した後に
インスタンスを代入した変数.save を実行すると対象テーブルにレコードが保存される

↓こんな感じ
f:id:misokatsu_sand:20210212184559p:plain

このsaveメソッドが使えるのはApplicationRecordクラスを継承しているおかげみたい

rails consoleでテーブルからデータを取り出す

レコードを追加したので確認してみる
変数=モデル名.firstで変数にテーブルの1つめのレコードを代入できる
レコードを代入した変数.カラム名で対象レコードのカラム名に格納されたデータを参照できる

こんな感じ
f:id:misokatsu_sand:20210212185033p:plain

モデルのallメソッド

モデル名.all[0].messageのように、allメソッドを使うと配列としてテーブルにアクセスできる

データベースとアクションの連動

データベースの状態

progateではまだ出てきてないけどsqlite3で表示してみる f:id:misokatsu_sand:20210214024533p:plain rails dbconsoleで起動して.headers onカラム名の表示ON、あとはSQL文を打てばOK。ちゃんと保存したレコードが入ってる

rails consoleで見るよりこっちの方が絶対いいね

controller

class PostController < ApplicationController
  def index
    @posts=Post.all
  end
end

html.erb

<div class="main">
  <h1>ruby埋め込みテスト用</h1>
  <% @posts.each do |post| %>
    <div class="messages-entire">
    <%= post.message %>
    </div>
  <% end %>
</div>

できた

f:id:misokatsu_sand:20210214025421p:plain

要所はcontrollerの@posts=Post.allと
html.erbの<%= post.message %>

allメソッドで配列として変数に格納して、eachでmessageの値を取り出す。

viewの共通レイアウト

今のview

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <header>
      <p>テストページ</p>
    </header>
    <div class="main">
      <h1>ruby埋め込みテスト用</h1>
      <% @posts.each do |post| %>
        <div class="messages-entire">
          <%= post.message %>
        </div>
      <% end %>
    </div>
    <footer>
      <p>Copyright © misokatsusand All Rights Reserved.</p>
    </footer>
  </body>
</html>

これのmainクラスタグの部分だけ記述しても機能させる方法がある
(余談ですがhtml5はmainタグ標準装備されてます、後から知りました)

下図のディレクトリにあるapplication.html.erbというファイルがある f:id:misokatsu_sand:20210214031105p:plain

中身はこれ

<!DOCTYPE html>
<html>
  <head>
    <title>Webapp</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

デフォルトでこの状態だから中身は好みに書き換えるとして、
トップページなどのviewのhtmlにいきなりmainタグとその中身だけ書いても、
このapplication.html.erbの<%= yield %>の部分にhtmlが代入されてからブラウザに表示される。

これを使って共通するレイアウトはまとめられる

現状のように各viewに個別にheaderタグやら書いちゃってもそれはapplication.html.erbより優先されるっぽい

色々置きすぎて手元のhtmlはメンテの手間がでかいため割愛

link_toメソッド

<%= link_to("表示文字列","URL") %>

html.erbに使うメソッドで、aタグと同じ役割

有効利用の仕方はまた後から出てくるらしい。その時でよかったんじゃね?

以上、rails II終わり!ではでは

Webエンジニア目指して#34

どうも無職マンです。

退職証明書類が未だ届かず、事務手続きを全て終わらせてからWebエンジニアのスクールへ臨むつもりが遅れてます。はよしてくれ〜〜〜〜〜

運動不足をなんとかしようと思って2億年振りにDDRやったんですが、全然踏めません。軟体動物が地団駄を踏むゲームになっています

そんな感じでいきまShow ProgateのRuby on Rails I !!!!!!!!!!!!!!

Webアプリケーションの生成
$ rails new application_name

ターミナルでこいつを入力すると自動で必要なディレクトリを作ってくれるらしい!行くぜうおお!
あ、$はコマンドを表す文字で、ターミナルに元々表示されるため入力は不要です f:id:misokatsu_sand:20210202062741p:plain Rails入っとらんやんけ!!!!!!!

f:id:misokatsu_sand:20210202063445p:plain 入れてきました。なにやら警告されてますが初めてRailsを始める場合は無視でいいそうなので無視します

というわけで先程のrails newを実行すると f:id:misokatsu_sand:20210202112551p:plain 予想よりたくさん生成されました。これがwebアプリの土台になるわけですね。こんなん手作業で作ってられないのでRailsは偉大ですね

サーバーの起動

rails newをしたら今度はサーバーを起動します 別途ターミナルを立ち上げて下記の通り入力

$ rails server

するとこんな表示になります。
f:id:misokatsu_sand:20210203181814p:plain Ctrl+Cでサーバーを閉じるまではこの窓は開きっぱなしにします。
忘れると閉じられなくなるんで回りくどい操作が必要になってしまうそうな

次にブラウザでlocalhost:3000をアドレスバーに入力するとこんな画面が出ます。 これでサーバーが立ちました。 f:id:misokatsu_sand:20210204162806p:plain

トップページの自動生成
$ rails generate controller home top

このコマンドを実行するとトップページが自動生成されます メリットはまだ分かりませんがなにやら色々やってるのでただトップページを作るだけじゃないみたい f:id:misokatsu_sand:20210205004828p:plain この状態でlocalhost:3000/home/topをブラウザで開くといかにもデフォルトな感じのページが開きます f:id:misokatsu_sand:20210205005235p:plain

viewについて

Railsページにはview,controller,routingの3ファイルが必要で、
ブラウザの要求に対してRailsrouting>controller>viewの順に経由しviewを返します

viewは見た目の部分、つまりhtmlのことです
viewファイルは下図のディレクトリに入ってます。自動生成したhome/topも入ってますね f:id:misokatsu_sand:20210205010215p:plain

生成したtop.html.erbはhtmlのノリで編集できます。末尾にerbがついてますがhtmlと同じ記述らしい

controllerについて

先述の通り、Railsがブラウザにviewを返す前にcontrollerファイルを経由してきます。さてはサーバーサイドの処理だな?

rails generate controller home topで生成されたものの中にcontrollerと名のついた.rb拡張子のファイルがあります f:id:misokatsu_sand:20210205011333p:plain これの中身がこちら

class HomeController < ApplicationController
  def top
  end
end

home/topを生成したのに合わせてtopメソッドが書かれてます

このようにcontrollerに書かれたメソッドをactionといって、

routingについて

rountingはブラウザに入力されるURLとcontrollerをリンクさせるファイルです

[viewについて]で書いた流れを細かく書くと、
1.ブラウザからの要求に対しRailsがURLとroutingを参照
2.対応したcontrollerファイル名とそのactionを参照
3.そのaction名のviewとなるhtmlをブラウザに返す って感じですね

このroutingも自動生成されてます f:id:misokatsu_sand:20210205015623p:plain その中身がこちら

Rails.application.routes.draw do
  get 'home/top'
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

あれ、Progateだとget "home/top" => "home#top"となりましたが結果が違う
ver.の違いでしょうか(Rails6.1.1)

コメントアウトに書いてあるURLへ行ってみると、どうやらURLの指定とcontroller actionが同じだと省略できるみたいです。なるほどね

ちなみに全然関係ないURLを入力したらrounting errorが出ました。

f:id:misokatsu_sand:20210205030216p:plain
やばそう
routingがうまく記述できてないとこうなるわけですね

routingの変更

controllerを呼び出すURLを変えます

Rails.application.routes.draw do
  get 'top'=>'home#top'
end

こうするとlocalhost:3000/topだけで呼び出せるようになります f:id:misokatsu_sand:20210205031150p:plain

また、下のように書いた場合はlocalhost:3000だけで呼び出せます

Rails.application.routes.draw do
  get '/'=>'home#top'
end
2個目以降のページの作成

home/topはrailsコマンドを使って自動生成しましたが、重複したcontrollerはコマンドが弾かれるため今まで書いたview,controller,routingファイルの自作が必要です

cssの適用

railsで下図のようにcss専用のフォルダが作られます f:id:misokatsu_sand:20210207184036p:plain home.scssがhomeフォルダのview全てに適用、
application.cssが全てのviewに適用されます

適用順はapplication>homeなので重複要素があればapplicationの記述は上書きされます

railsではscssなんですね。sass覚えといて良かった〜

画像の保存場所

railsは独特な参照をするみたいで、<img src="/bnr_mini.png">みたいな書き方をすると下図のフォルダを参照します。 f:id:misokatsu_sand:20210208233243p:plain 別にもapp/assets/imagesに保存場所があってどっちやねん!って感じですね
参照する際は/assets/images/xxx.pngのように記述します。appがルートディレクトリになるわけですね

ちらっと調べた感じwebアプリを立ち上げたとして、ユーザーが利用する範囲のものはpublic、システム画像などであまり変化のないものはassets/imagesに置くのがいいというのを見ました

htmlリンクの設定

htmlのaタグのリンク先にroutingのパスを記述するとその設定通りに飛ぶ

<a href="/">トップページ</a>

途中で調べることが多くて止まっちゃいましたがRails Iおわり!ではでは

Webエンジニア目指して#33

どうも運動不足マンです

外に出ないせいで完全に冬眠モードです。実家なのでリングフィットやるスペースもないし困ったもんですね

さてやっていきましょうProgateのRuby Vです。Ruby単体はこれが最後ですね

クラスの継承
class Sushi < Food
end

継承の記述が左に流れるため紛らわしい

jsと同様に継承や上書きなどほとんど同じ概念がある
継承によって生成された子クラスにはインスタンス変数とインスタンスメソッドが継承されるところも同じ

また、子クラスで新規メソッドを記述すれば子クラスにのみ追加され、既存メソッドを記述すれば上書きされる

superメソッド
class Food
  attr_accessor:name

  def initialize(name:)
    self.name=name
    puts "#{self.name}が生成されました"
  end
end

class Sushi < Food
  attr_accessor:wasabi

  def initialize(name:,wasabi:)
    super(name: name)
    self.wasabi=wasabi
    puts "わさび#{self.wasabi}です"
  end
end

food1=Sushi.new(name:"ネギトロ",wasabi:"なし")

実行結果-----------------
ネギトロが生成されました
わさびなしです

super(name: name)の部分で親クラスの同名関数を呼び出してます

新しく定義した変数については通常通り記述

もうほぼjsでやった内容と同じですね

Dateクラス
require "date"
eventday=Date.new(2021,1,31)
puts eventday
puts eventday.sunday?

実行結果-------------
2021-01-31
true

定義しなくてもrequire "date"でDateクラスを読み込み、上記の流れでその日が何曜日か判定できる。 調べたところ、インスタンスメソッドは他にもたくさんあるみたい

また、下記のようにインスタンス生成の際に.newではなく.todayと記述することでその日の日付を取得できる

require "date"
eventday=Date.today
puts eventday

実行結果---------------------
2021-02-01
クラスメソッド

Date.newDate.todayのような記述をクラスメソッドと呼ぶとか呼ばないとか
クラスに対するメソッドなのでそのまんまですね
クラスメソッドを自前で用意するにはdef クラス名.メソッド名のように記述 以下お試し結果

require "date"

class Sample

  def Sample.is_today_sunday?
    today=Date.today
    if today.sunday?
      puts "今日は日曜日"
    else
      puts "今日は日曜日ではありません"
    end
  end

end

sample1=Sample.is_today_sunday?

実行結果-------------
今日は日曜日ではありません
クラスメソッドの連結

1つ上のコードは回りくどいなあと思って Date.today.sunday?みたいに記述できないかな?と気になって試してみたらできた
メソッドチェーンと呼ぶらしい jQと同じ呼び方ですね

require "date"

today1=Date.new(2021,1,31).sunday?
puts today1

today2=Date.new(2021,2,1).sunday?
puts today2

実行結果------------
true
false

これでRuby Vは終わり!次はやっとRailsですね 遅くね?

ではでは

Webエンジニア目指して#32-2

#32のアウトプットです

Foodsというクラスに名前とその数のインスタンス変数を与え、空の配列を用意しそこに食べ物のインスタンスを入れていくものです

gets.chomp.to_iのところで数字以外も入力できちゃうので工夫がいる、みたいなのを書きましたが、これは「getsで入力された文字列が自然数かどうか」で判定させることにしました

調べて辿り着いたのは「正規表現」です。ざっくり説明すると、めちゃくちゃ細かい指定ができるワイルドカードみたいなものです

その正規表現を使うと、ある文字列がお望みの文字列かどうか真偽値を返してくれます。 お望みの文字列のところを自然数にして、getsで数字以外を入力したらやり直しをさせるif文を書きました

loop do
    jdg_natural=gets
    if jdg_natural =~ /^[0-9]+$/ then
      food_alley[i].number=jdg_natural.to_i
      break
    else
      puts "個数は自然数のみで入力してください"
    end
  end

この部分ですね。最初はgetsの時点でint変換をしてましたが、integerは正規表現で比較すると常にnilを返しやがるので、一旦ただの文字列として取得して、自然数かどうか判定してからインスタンス変数に代入してます。 正規表現はstring型じゃないと動かない、ということですね。多分

loopメソッドを使ってみましたが、絶対に一度は通って条件分岐でやり直しをさせるものには結構便利ですね。

それ以外はゴリゴリ書いただけです。以下コードです

最後に実行結果のgifを載せます

class Foods
  attr_accessor:name
  attr_accessor:number

  def info
    return "名前:#{self.name} | 個数:#{self.number}"
  end
end

i=0
food_alley=[]

while i<5 do
  food_alley[i]=Foods.new
  puts "入荷物の名前を入力してください"
  food_alley[i].name=gets.chomp
  puts "入荷物の個数を入力してください(自然数のみ)"
  loop do
    jdg_natural=gets
    if jdg_natural =~ /^[0-9]+$/ then
      food_alley[i].number=jdg_natural.to_i
      break
    else
      puts "個数は自然数のみで入力してください"
    end
  end

  puts "入力結果 → #{food_alley[i].info}"
  i+=1
  if i>=5 then
    puts "入力終了"
  else
    puts "あと#{5-i}回入力可能です。続けますか?"
    cont_flag=0
    while cont_flag==0 do
      puts "続ける:y やめる:n"
      continue=gets.chomp
      if continue=="n" then
        puts "入力終了"
        cont_flag=1
        i=5
        break
      elsif continue=="y" then
        puts "入力を続けます"
        cont_flag=1
      else
        puts "yかnを入力してください"
      end
    end
  end
end

f:id:misokatsu_sand:20210123223651g:plain

以上!!!

Webエンジニア目指して#32

どうもスマホ画面割れマンです。
退職日前日の12/30、同部署80人余りの各位へ直接お別れの挨拶とお菓子を渡して、応援の言葉もたくさん貰って、仕事でも色々と成果残してやることもやりきってすごい晴れ晴れとした気分で晩飯にカップ麺食ってたんですけど、机の上からスマホがずり落ちて割れました。
丁度使ったドライヤーを足元に置いててその角にクリティカルヒットしました。
グローバル版だったもんでfelicaが使えず国内版に買い換えようか迷っているところではありましたが、きっかけがこんな残念なものとは・・・78000円で得たというより補填した感覚が勝ってます 画面修理だけでも50000円超えますからね、転活真っ最中なのでサイフポイントへのダメージが痛いです

整理整頓は本当に大事ですね。
さあやっていきましょうProgate Ruby IVの続きですね

ファイルの分割
require "./class_foods

同じディレクトリにclass_foods.rbというファイルがある場合、これでjsで言うところのimportができる(拡張子の.rbは記述不要)

class名の先頭大文字で気になって調べてみたところ、推奨の命名規則があるらしくファイル名もcamel_caseの命名規則がありました。
命名規則とは解読する際に役割の判別をしやすくするものらしいです。

インスタンスと配列
class Foods
  attr_accessor:name
  attr_accessor:number

  def initialize(name:,number:)
    self.name=name
    self.number=number
  end

  def show_text
    if self.number>50
      return "#{self.name}は過剰在庫です(#{self.number}個)"
    end
    return "#{self.name}は過剰在庫ではありません(#{self.number}個)"
  end
end

food1=Foods.new(name:"apple",number:60)
food2=Foods.new(name:"orange",number:30)
food3=Foods.new(name:"banana",number:10)

foods_alley=[food1,food2,food3]

foods_alley.each do |food|
  puts food.show_text
end
実行結果-----------------
appleは過剰在庫です(60個)
orangeは過剰在庫ではありません(30個)
bananaは過剰在庫ではありません(10個)

生成したインスタンスを配列に格納してeach処理で在庫確認メソッドを動かしてます。ここで知ったんですけど、配列は後から格納できるんですね

getsメソッド
puts "なにか入力してEnterで確定してください"
test=gets.chomp
puts "#{test}が入力されました"

実行するとこうなる↓

f:id:misokatsu_sand:20210123173711g:plain
getsだけでも使えますが↓のように改行されてしまいました

aiueo
が入力されました

chompは改行をなくすメソッドみたいですね
また、getsは文字列として取得されるため
数値を取得したい場合はgets.chomp.to_iにする必要あり
to_iはintegerに変換するメソッドです
数値以外を入力すると0が取得されてしまうので、実際に使う場合は一工夫要りそう

Ruby IVはここまで!筆が乗っちゃって(?)自分で色々駆使したまとめを作ったんですが、欲張りすぎて情報量が多いので別枠にします

ではでは〜

Webエンジニア目指して#31

どうも帰省マンです
実家に戻ると「部屋が狭え!!!」ってなりますね。実質2畳間なので・・・
引っ越しそのものは終わりましたが、健康保険やら年金やらの手続きがめんどいですね

さあやっていきましょう、ProgateのRuby IVです。

クラスとインスタンス
class Foods
  attr_accessor:name
  attr_accessor:number
  def show_text
    puts "これはFoodsクラス"
  end
end

food1=Foods.new
food1.name="apple"
food1.number=10
food1.show_text

puts "#{food1.name}#{food1.number}個生成されました"
実行結果-----------------
これはFoodsクラス
appleが10個生成されました

jsでやったクラスって概念は他言語にもあったんですね
classend間にクラス情報を記述
attr_accessorインスタンス変数の定義
変数=クラス名.newインスタンスの生成
クラス名.インスタンス変数で代入や出力が可能

インスタンスメソッド
class Foods
  attr_accessor:name
  attr_accessor:number
  def show_text(count)
    if count>50
      return "過剰在庫です"
    end
    return "過剰在庫ではありません"
  end
end

food1=Foods.new
food1.name="apple"
food1.number=60

puts "#{food1.name}#{food1.number}個生成されました"
puts food1.show_text(food1.number)
実行結果-----------------
appleが60個生成されました
過剰在庫です

クラス内にメソッドを定義し、インスタンスで呼び出すメソッドとして使う

self.変数名
class Foods
  attr_accessor:name
  attr_accessor:number
  def show_text
    if self.number>50
      return "過剰在庫です"
    end
    return "過剰在庫ではありません"
  end
end

food1=Foods.new
food1.name="apple"
food1.number=10

puts "#{food1.name}#{food1.number}個生成されました"
puts food1.show_text
実行結果--------------
appleが10個生成されました
過剰在庫ではありません

selfでの置き換えver
コールバックに使いそう

initializeメソッド
class Foods
  attr_accessor:name
  attr_accessor:number
  def initialize(name:,number:)
    self.name=name
    self.number=number
    puts "Foodsインスタンスが生成されました"
    puts "在庫名:#{self.name}"
    puts "個数:#{self.number}"
  end
end

food1=Foods.new(name:"apple",number:40)
実行結果---------------
Foodsインスタンスが生成されました
在庫名:apple
個数:40

インスタンスメソッド名をinitializeで定義するとjsのconstructorみたいな動きをする

ほい

Ruby IVはまだ終わってませんがクラスについてはキリがいいのでここまでにします。 ではでは

Webエンジニア目指して#30

どうも謹賀新年マンです。あけましておめでとうございます。 ついに退職しました。かなり時間が取れるようになりますが、スケジュール詰めすぎて引っ越しが忙しい!!!! 合間にやっていきましょう、ProgateのRuby IIIです。 

メソッド
def ingredients_info(name,number)
  puts "#{name}#{number}個あります"
end

ingredients_info("apple",9)
実行結果----------------
appleは9個あります

関数定義。引数も使える。引数はメソッド内にスコープを作る
また、メソッド内で定義した変数もメソッド内にスコープを作る

戻り値
def add(a,b)
  return a+b
end

sum=add(2,7)
puts sum
実行結果--------------
9
真偽値を返すメソッド
def smallerThan10?(a)
  return a<10
end

judge=smallerThan10?(8)
puts judge
実行結果----------------
true

if文などと組み合わせて使う

複数の戻り値
def score_judge(score)
  if score>=80
    return "pass"
  end
  return "failure"
end

puts score_judge(100)
実行結果---------------
pass
キーワード引数
def item(name:, number:)
    puts "#{name}#{number}個生成しました"
end

item(name:"金塊", number:999)
実行結果----------------
金塊を999個生成しました

こんなもんですね ではでは。