- 投稿日:2021-01-25T23:26:23+09:00
rails newするときのoptionなにしたらええんやっけ?となったとき
$ bundle exec rails help Usage: rails new APP_PATH [options] Options: [--skip-namespace], [--no-skip-namespace] # Skip namespace (affects only isolated applications) -r, [--ruby=PATH] # Path to the Ruby binary of your choice # Default: /Users/shoutaro/.rbenv/versions/2.7.2/bin/ruby -m, [--template=TEMPLATE] # Path to some application template (can be a filesystem path or URL) -d, [--database=DATABASE] # Preconfigure for selected database (options: mysql/postgresql/sqlite3/oracle/frontbase/ibm_db/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc) # Default: sqlite3 [--skip-gemfile], [--no-skip-gemfile] # Don't create a Gemfile -G, [--skip-git], [--no-skip-git] # Skip .gitignore file [--skip-keeps], [--no-skip-keeps] # Skip source control .keep files -M, [--skip-action-mailer], [--no-skip-action-mailer] # Skip Action Mailer files [--skip-action-mailbox], [--no-skip-action-mailbox] # Skip Action Mailbox gem [--skip-action-text], [--no-skip-action-text] # Skip Action Text gem -O, [--skip-active-record], [--no-skip-active-record] # Skip Active Record files [--skip-active-storage], [--no-skip-active-storage] # Skip Active Storage files -P, [--skip-puma], [--no-skip-puma] # Skip Puma related files -C, [--skip-action-cable], [--no-skip-action-cable] # Skip Action Cable files -S, [--skip-sprockets], [--no-skip-sprockets] # Skip Sprockets files [--skip-spring], [--no-skip-spring] # Don't install Spring application preloader [--skip-listen], [--no-skip-listen] # Don't generate configuration that depends on the listen gem -J, [--skip-javascript], [--no-skip-javascript] # Skip JavaScript files [--skip-turbolinks], [--no-skip-turbolinks] # Skip turbolinks gem -T, [--skip-test], [--no-skip-test] # Skip test files [--skip-system-test], [--no-skip-system-test] # Skip system test files [--skip-bootsnap], [--no-skip-bootsnap] # Skip bootsnap gem [--dev], [--no-dev] # Setup the application with Gemfile pointing to your Rails checkout [--edge], [--no-edge] # Setup the application with Gemfile pointing to Rails repository [--rc=RC] # Path to file containing extra configuration options for rails command [--no-rc], [--no-no-rc] # Skip loading of extra configuration options from .railsrc file [--api], [--no-api] # Preconfigure smaller stack for API only apps -B, [--skip-bundle], [--no-skip-bundle] # Don't run bundle install --webpacker, [--webpack=WEBPACK] # Preconfigure Webpack with a particular framework (options: react, vue, angular, elm, stimulus) [--skip-webpack-install], [--no-skip-webpack-install] # Don't run Webpack installhelpを見ましょう
$ bundle exec rails new . -B -d mysql --skip-turbolinks --skip-test --no-skip-webpack-install -Jこんな感じでつくりました。
- 投稿日:2021-01-25T22:58:18+09:00
railsのバリデーション
バリデーションとは
正当性を実証(確認)すること。
例えば、新規登録フォームでユーザー名が入力されていなかったら登録できない、
メールアドレスが正規の型でない等を検知する。新規登録時に名前、メールアドレスが入力されているか検証する
app/models/user.rbファイルに記入する。
validatesメソッドに presence:trueという引数を与えて使うことで検証できます。app/models/user.rbclass User < ApplicationRecord validates :name, presence: true validates :email, presence: true end長さを検証する
上記のコードにlenghtを追加します。
今回は名前を50文字、メールアドレスを255文字を制限とします。app/models/user.rbclass User < ApplicationRecord validates :name, presence: true, length: { maximum: 50 } validates :email, presence: true, length: { maximum: 255 } endフォーマットを検証する
メールアドレスにおなじみのパターンuser@example.comに合っているかを検証します。
無効なメールアドレスにはマッチしない正規表現を組み立てる必要があります。
正規表現とは、一定の規則に従って特定の文字列(群)を集合の要素として表す表記法。
コンピューターで,テキスト処理に使われる。
正規表現がこちら。
/\A[\w+-.]+@[a-z\d-.]+.[a-z]+\z/i暗号みたいでわかりずらいので表を置いときます。
正規表現 意味 /\A[\w+-.]+@[a-z\d-.]+.[a-z]+\z/i (完全な正規表現) / 正規表現の開始を示す \A 文字列の先頭 [\w+-.]+ 英数字、アンダースコア(_)、プラス(+)、ハイフン(-)、ドット(.)のいずれかを少なくとも1文字以上繰り返す @ アットマーク [a-z\d-.]+ 英小文字、数字、ハイフン、ドットのいずれかを少なくとも1文字以上繰り返す . ドット [a-z]+ 英小文字を少なくとも1文字以上繰り返す \z 文字列の末尾 / 正規表現の終わりを示す i 大文字小文字を無視するオプション app/models/user.rbclass User < ApplicationRecord validates :name, presence: true, length: { maximum: 50 } VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX } end一意性を強制
メールアドレスの一意性を強制するために、validatesメソッドの:uniquenessオプションを使います。
uniquenessは登録されているメールアドレスは登録できないことを検証します。pp/models/user.rbclass User < ApplicationRecord validates :name, presence: true, length: { maximum: 50 } VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness:true endemail属性を小文字に変換してメールアドレスの一意性を保証
emailを小文字に変換はemail.downcaseを使います。
今回の場合は、オブジェクトが保存される時点で処理を実行したいので、before_saveというコールバックを使います。
ユーザーがデータベースに保存する前にemail属性を強制的に小文字に変換しますapp/models/user.rbclass User < ApplicationRecord before_save { self.email = email.downcase } validates :name, presence: true, length: { maximum: 50 } VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: true end
- 投稿日:2021-01-25T22:46:18+09:00
モデルとテーブルについて
目次
①モデルとは
②テーブルとは
②モデルの作成方法
④テーブルの作成・編集方法①モデルとは
MVCモデルの役割の一つ。データベースにアクセスすることができ、あらゆる情報に関する処理をすることができる。モデルがあることによって、データベースにあるテーブルも管理ができるようになる。各テーブルは各モデルに対応しており、モデルとにテーブルを管理できる。
②テーブルとは
データベース内に作成されるデータを表形式で収納するもの。データベースに各用途におうじてテーブルが存在して、必要となればそのテーブルからデータを抽出することができる。
③モデルの作成方法
rails g model person #モデルの作成、モデルは単数形④テーブルの作成・編集方法
モデルを作成後、それに対応するテーブルは出来上がる。ただ、まっさらなテーブルの状態で、どのような情報を入れたいかなどの設計がなされていない状態である。それを設計するために、マイグレーションファイルに以下のように記述し、コマンドを実行するとテーブルに反映される
class CreateHumans < ActiveRecord::Migration def change create_table :humans do |t| t.integer :age ←記述 t.name :name ←記述 t.timestamps end end end上記のマイグレーションをテーブルに反映させるには以下のコマンドを実行する
rails db:migrate #マイグレーションをテーブルに反映もしテーブルの使用を変更したいときは、
rails db:rollbackをすると前の状態に戻るので、マイグレーションファイルを正しい情報に書き換えたのちにrails db:migrate
をするとまたテーブルに反映される。
- 投稿日:2021-01-25T22:04:00+09:00
コントローラについて
目次
①コントローラとは
②コントローラの作成方法
③コントローラの削除方法
④コントローラの処理のカテゴリー①コントローラとは
MVCモデルの役割の一つ。リクエストに対する処理をまとめて用意しておき、ルーティングからリクエストを受け取って処理を行った後、クライアントにレスポンスを返す。またレスポンスに必要となるデータがあれば、他の役割と連携してデータを取得したり受け渡しを行い、レスポンスを完成させる。
②コントローラの作成方法
rails g controller コントローラ名 #コントローラを作成、コントローラは複数形③コントローラの削除方法
rails d controller コントローラ名 #コントローラを削除、コントローラは複数形④コントローラの処理のカテゴリー
コントローラはリクエストに対応する処理を記述する場所。リクエストの処理はアクションと呼ばれ、主に7つのアクションがある。
アクション名 何に対応するか index 一覧表示ページを表示するリクエストに対応 new 新規投稿のページを表示するリクエストに対応 create データの投稿を行うリクエストに対応 show 詳細ページを表示するリクエストに対応 edit 編集ページを表示するリクエストに対応 update データの更新をおこなうリクエストに対応 destory データの削除をおこなうリクエストに対応
- 投稿日:2021-01-25T21:49:56+09:00
テーブルの内容を修正する方法
rails db:rollbackの手順
マイグレーションを差し戻して、テーブルの内容を修正する。
必要な手順は以下の3ステップ
ステップ1
ロールバック
ステップ2
migrationファイルの修正
ステップ3
再度migrationを実行
ステップ1
rails db:rollbackコマンド
ターミナル% rails db:rollback
rails db:rollback
カラム名を誤ってしまった場合などに、モデルに紐づくテーブルを作り直したいときに用いられるターミナルコマンド例: nameをnemeにしてしまった等
「差し戻す」
と表現される実行すると以下のような表示が出て差し戻される。
ターミナル== 20200315054113 CreatePosts: reverting ====================================== -- drop_table(:posts) -> 0.1939s == 20200315054113 CreatePosts: reverted (0.2332s) =============================rails db:migrate:statusコマンドとは?
補足情報として
rails db:migrate:status
というコマンドで状態を確認出来る。ターミナル% rails db:migrate:status
- マイグレーションファイルの状況
- up = 実行済み
- down = 適応されていない
ターミナルdatabase: first_app_development Status Migration ID Migration Name -------------------------------------------------- up 20190820071210 Create postsdownの表記がされていれば差し戻されている
ターミナルdatabase: first_app_development Status Migration ID Migration Name -------------------------------------------------- down 20190820071210 Create postsステップ2
migrationファイルの修正
db/migrate/20XXXXXXXXXXXX_create_変更前.rbclass CreatePosts < ActiveRecord::Migration[6.0] def change create_table :posts do |t| t.text :memo t.timestamps end end end
t.text :memo
をt.text :content
へ変更db/migrate/20XXXXXXXXXXXX_create_変更後.rbclass CreatePosts < ActiveRecord::Migration[6.0] def change create_table :posts do |t| t.text :content t.timestamps end end endカラム名と型とは?
補足情報として、カラム名と型とは何のことなのか解説
カラム名と型t.text :memot.に続くのがカラムの型
その右側にシンボルで記載されるものがカラム名ステップ3
再度migrationを実行
修正したマイグレーションを実行
します。ターミナル% rails db:migrate以上の修正が反映されているか確認して終了です
- 投稿日:2021-01-25T21:30:19+09:00
アプリケーションの作成〜立ち上げ
アプリケーション作成の流れ
①アプリケーションを保存するためのディレクトリを作成
②新規のrailsアプリケーションを作成
③データベースを作成
④アプリのケーションの立ち上げ①アプリケーションを保存するためのディレクトリを作成
ホームディレクトリから新規フォルダで適当な名前のディレクトリを作成する
②新規のrailsアプリケーションを作成
cd ①のディレクトリ #①のディレクトリに移動する rails railsのバージョン new Career_up -d mysql #railsのバージョンを指定して、Career_upを作成 cd Career_up #Career_upのディレクトリに移動する pwd #現在のディレクトリに移動③データベースを作成
rails db:create #データベースを作成する④アプリのケーションの立ち上げ
cd Career_up #Career_upのディレクトリに移動する rails s #Career_upのディレクトリ上記のコマンドを打つ以上です
- 投稿日:2021-01-25T21:00:26+09:00
pramasについて
目次
①paramsとは何か
②値はどのように送られてくるのか?
③どのように取り出すのか
④まとめ①paramsとは何か
送られてきた値を受け取るためのメソッドのこと
②値はどのように送られてくるのか?
以下のコードはブラウザから入力されたデータを受け取るためのコードです。
def create Peroson.create(human_params) end def human_params params.require(:human).permit(:text).merge(user_id:current_user.id) end投稿作業を行った後、ターミナルを見てみると
Parameters: {"authenticity_token"=>"MgJJR92h/eFO7aQ+4YMt4y2tY6kPAxD1KaiVccrRxcuK4342o8v7bNpMV0SQgmmIZW8WZA4ik/UwxLVLyT5NSA==", "human"=>{ "text"=>"おはよう"}, "commit"=>"SEND", "id"=>"14"}といったものが表示されています。
Parametersにハッシュの形でいろいろ格納されてデータが送られてきます。③どのように受け取るのか
②の"human"=>{ "text"=>"おはよう"}, "commit"=>"SEND", "id"=>"14"}の「おはよう」を取り出すときは
human(params[:text])というように記述するとParametersのハッシュから「おはよう」を取り出すことができる。
④まとめ
クライアントサイドから送られてきた値はParametersというハッシュに格納されたデータが送られてくる。その送られてきたデータをハッシュから取り出してデータを受け取るメソッドがparamsです。
- 投稿日:2021-01-25T20:49:24+09:00
Model.human_attribute_name(:カラム名)について(Rails)
経緯
普段viewでよく見かけるタイトルについて自分の学習用のメモ的な感じです。
Model.human_attribute_name(:カラム名)とは?
ActiveRecord::Base のクラスメソッドで内部的にI18nモジュールを
利用してくれるというものです
参照先は config/locales/ja.ymlです。ja.yml--- ja: activerecord: errors: messages: record_invalid: 'バリデーションに失敗しました: %{errors}' restrict_dependent_destroy: has_one: "%{record}が存在しているので削除できません" has_many: "%{record}が存在しているので削除できません" models: task: タスク attributes: task: id: ID name: 名称 description: 詳しい説明 created_at: 登録日時 updated_at: 更新日時 user: name: 名前 email: メールアドレス admin: 管理者権限 password: パスワード password_confirmation: パスワード(確認) created_at: 登録日時 updated_at: 更新日時viewではこんな感じで使います。
th= Task.human_attribute_name(:name)この場合ですと「名称」ですね!
最後に
ymlの書き方は特徴があって毎回躓きます。。
- 投稿日:2021-01-25T17:15:17+09:00
Docker開発環境
はじめに
現在開発中のアプリにDockerを導入したのでアウトプットします。
環境
Ruby on Rails '6.0.0'
Ruby '2.6.5'
MySQL '5.6.47'Dockerfile
開発中アプリのルートディレクトリにDockerfileを作成します。
DockerfileFROM ruby:2.6.5 RUN apt-get update -qq && \ apt-get install -y build-essential \ libpq-dev \ nodejs RUN mkdir /アプリ名 WORKDIR /アプリ名 ADD ./Gemfile /アプリ名/Gemfile ADD ./Gemfile.lock /live_search/Gemfile.lock RUN gem install bundler RUN bundle install ADD . /アプリ名docker-compose.yml
docker-compose.ymlversion: '3' services: db: image: mysql:5.6.47 environment: MYSQL_ROOT_PASSWORD: 'password' ports: - "4306:3306" volumes: - ./db/mysql-data:/var/lib/mysql web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/アプリ名 ports: - "3000:3000" depends_on: - dbentrypoint.sh
entrypoint.shset -e rm -f /myapp/tmp/pids/server.pid exec "$@"database.yml
database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password host: db socket: /tmp/mysql.sockpassword: password
host: db
を追加コンテナを作成
ターミナル% docker-compose buildDB作成、migrationの実行
ターミナル% docker-compose run web bundle exec rake db:create % docker-compose run web bundle exec rake db:migrateコンテナを起動
ターミナル% docker-compose up
- 投稿日:2021-01-25T16:10:37+09:00
【Ruby】レシーバのないメソッド
Rubyにおいてレシーバのないメソッドでは、暗に
self
をレシーバとしているらしい。puts "hello" # => helloは下の文と等しい。
self.puts "hello" # => helloトップレベルでの
self
はmain
という名前のObjectクラスのインスタンスであり、
ObjectクラスはKernelモジュールをincludeしている。
Kernelモジュールにputsメソッドが定義されているため、トップレベルでputsが使えるということらしい。参考
【Ruby】メソッドの前のレシーバがない(ように見える)場合の考え方)
プロを目指す人のためのRuby入門
p.300
- 投稿日:2021-01-25T16:01:04+09:00
Ruby初心者向けプログラミング問題10選を解いてみた(下)
Ruby初心者向けプログラミング問題10選を解いてみた(上)の続きです
引き続き自分の回答を貼っていきますが、2問解けてないです(へなちょこ)素晴らしき元サイト様
アウトプットのネタに困ったらこれ!?Ruby初心者向けのプログラミング問題を集めてみた(全10問)
国民の祝日.csv パースプログラム (回答無し)
問題文
問題文(折りたたみ)
その昔、「国民の祝日.csv」という扱いづらいCSVが話題になっていました。
具体的にはこんなCSVファイルです↓平成28年(2016年),,平成29年(2017年),,平成30年(2018年), 名称,月日,名称,月日,名称,月日 元日,2016/1/1,元日,2017/1/1,元日,2018/1/1 成人の日,2016/1/11,成人の日,2017/1/9,成人の日,2018/1/8 建国記念の日,2016/2/11,建国記念の日,2017/2/11,建国記念の日,2018/2/11 春分の日,2016/3/20,春分の日,2017/3/20,春分の日,2018/3/21 昭和の日,2016/4/29,昭和の日,2017/4/29,昭和の日,2018/4/29 憲法記念日,2016/5/3,憲法記念日,2017/5/3,憲法記念日,2018/5/3 みどりの日,2016/5/4,みどりの日,2017/5/4,みどりの日,2018/5/4 こどもの日,2016/5/5,こどもの日,2017/5/5,こどもの日,2018/5/5 海の日,2016/7/18,海の日,2017/7/17,海の日,2018/7/16 山の日,2016/8/11,山の日,2017/8/11,山の日,2018/8/11 敬老の日,2016/9/19,敬老の日,2017/9/18,敬老の日,2018/9/17 秋分の日,2016/9/22,秋分の日,2017/9/23,秋分の日,2018/9/23 体育の日,2016/10/10,体育の日,2017/10/9,体育の日,2018/10/8 文化の日,2016/11/3,文化の日,2017/11/3,文化の日,2018/11/3 勤労感謝の日,2016/11/23,勤労感謝の日,2017/11/23,勤労感謝の日,2018/11/23 天皇誕生日,2016/12/23,天皇誕生日,2017/12/23,天皇誕生日,2018/12/23 ,,,,, 月日は表示するアプリケーションによって形式が異なる場合があります。,,,,,(中略)
これをいい感じにパースして、以下のようなデータ構造(Rubyのハッシュオブジェクト)に変換しよう、というプログラミング問題です。{ 2016 => { # 実際のキーは文字列ではなくDateオブジェクト '2016/01/01' => '元日', '2016/01/11' => '成人の日', # ... '2016/11/23' => '勤労感謝の日', '2016/12/23' => '天皇誕生日', }, 2017 => { '2017/01/01' => '元日', '2017/01/09' => '成人の日', # ... '2017/11/23' => '勤労感謝の日', '2017/12/23' => '天皇誕生日', }, 2018 => { '2018/01/01' => '元日', '2018/01/08' => '成人の日', # ... '2018/11/23' => '勤労感謝の日', '2018/12/23' => '天皇誕生日', }, }コード
csvの扱い方が全くわからなかったので解けなかったです…
代わりと言ってはなんですが本家の模範解答のURLを貼っておきます
【短命に終わった】国民の祝日.csvをパースして変換するRubyプログラムとコード解説動画要点解説
解説動画です
【短命に終わった】国民の祝日.csvをパースして変換するRubyプログラムとコード解説「Rubyで英語記事に含まれてる英単語を数えて出現数順にソートする」問題
問題文
問題文(折りたたみ)
テキストファイルの中から英熟語や英単語を抜き出してカウントする、という問題です。
入力に使うテキストファイルはこんな感じです。
Interior design and decorating resource Houzz is the overall best Android app of the year, according to Google, which this evening announced the results of the first-ever Google Play Awards at its developer conference, Google I/O. (略)出力結果はこんな感じになります。
単語数(熟語以外):331 英熟語?------------------------------------------------------------------ 2 Google I/O 2 Google Play Awards 1 And Google 1 Best App 1 Best Game 1 Best of 1 Best Standout Startup 1 Best Use of Google Play Game Services 1 Best Use of Material Design (略) 英単語------------------------------------------------------------------ 22 the 11 and 11 of 8 a 6 apps 5 app 5 best 5 for 5 Google 5 to 4 that 4 this (略)コード
*かなりゴチャゴチャしてます
*熟語の判定がガバガバなので本家と出力結果が違いますfile_pass = # 任意のパス words_hash = Hash.new(0) words = [] idioms_hash = Hash.new(0) idioms = [] sentence = File.read(file_pass) # 英熟語を抜き出す while (idiom = sentence.slice!(/[A-Z][\w]*(?:[\/\s-]+[A-Z][\w]*)+/)) idioms << idiom end idioms.sort.each { |idiom| idioms_hash[idiom] += 1 } # 記号系を消す while (s = sentence.slice!("’s")) words << s end sentence.gsub!(/[,.“”?!;:ー"–]/, " ") # 単語を抜き出す words << sentence.split words.flatten! wods.sort.each { |word| words_hash[word.downcase] += 1 } # ソート i = 0 words_hash = words_hash.sort_by { |_, v| [v, i -= 1] }.reverse.to_h idioms_hash = idioms_hash.sort_by { |_, v| [v, i -= 1] }.reverse.to_h # 出力 puts "単語数 : #{words.count + idioms.count}" puts "英熟語?-----------------------------------------------------------------" idioms_hash.each { |word, num| puts "#{num} #{word}" } puts "英単語------------------------------------------------------------------" words_hash.each { |word, num| puts "#{num} #{word}" }要点解説
while (idiom = sentence.slice!(/[A-Z][\w]*(?:[\/\s-]+[A-Z][\w]*)+/)) idioms << idiom end
(idiom = sentence.slice!(/[A-Z][\w]*(?:[\/\s-]+[A-Z][\w]*)+/))
は条件式の中で警告を出さずに変数代入を行う書き方です(カッコを外すと警告が出ます)i = 0 words_hash = words_hash.sort_by { |_, v| [v, i -= 1] }.reverse.to_h idioms_hash = idioms_hash.sort_by { |_, v| [v, i -= 1] }.reverse.to_hるりまのsort_byのページを参考に安定なソート(比較結果が同じ要素は元の順序通りに並ぶソート)を作りました
原理は全くわかりません()sortの結果は配列になっているので
to_h
でハッシュに戻します(執筆中に気づきましたがここは配列のままでも動作するみたいです)行単位、列単位で合計値を求めるプログラム
問題文
問題文(折りたたみ)
行単位、列単位で合計値を出しましょう、という問題です。
たとえばこういうインプットであれば、
- col1 col2 col3 col4 row1 9 85 92 20 row2 68 25 80 55 row3 43 96 71 73 row4 43 19 20 87 row5 95 66 73 62 こういう結果になります。
- col1 col2 col3 col4 sum row1 9 85 92 20 206 row2 68 25 80 55 228 row3 43 96 71 73 283 row4 43 19 20 87 169 row5 95 66 73 62 296 sum 258 291 336 297 1182 ただし、出題元のブログでは以下のような仕様になっていました。
- ランダムに数字を出力する
- 計算結果は以下のようなフォーマットで出力する
9| 75| 83| 74| 241 0| 27| 32| 48| 107 51| 66| 76| 3| 196 2| 37| 69| 85| 193 55| 40| 25| 88| 208 117| 245| 285| 298| 945コード
class SumMatrix class << self def sum matrix = generete_matrix matrix = sum_matrix(matrix) format_matrix(matrix) end def generete_matrix matrix = Array.new(5) { [] } 5.times { |i| 4.times { matrix[i] << rand(0..99) } } matrix end def sum_matrix(matrix) 2.times do matrix.each { |ary| ary << ary.sum } matrix = matrix.transpose end matrix end def format_matrix(matrix) matrix.each { |elem| elem.map! { |x| x.to_s.rjust(4) } } matrix.map! { |elem| elem.join("|") } matrix.join("\n") end end end要点解説
class << selfendまでで定義したメソッドがクラスメソッドとして定義されます
ネストは増えるけど便利matrix = Array.new(5) { [] }
Array.new
は第1引数に要素数、第2引数に中身を指定してデフォルト値(?)を作れます
しかし、出来上がった配列の中身はすべて同じオブジェクトを参照しているのでうまく動きません
なので別々のオブジェクトを与えるためブロックを使っています5.times { |i| 4.times { matrix[i] << rand(0..99) } }同じ列に重複する値が入るのもいいかなと思ってこんな書き方になりました
最初は5.times { |i| matrix[i] = [*(0..99)].sample(4) }
としていましたが、中途半端ですしねmatrix.each { |elem| elem.map! { |x| x.to_s.rjust(4) } }
[1,2], [3, 4]
を[[" 1", " 2"], [" 3", " 4"]]
にします
ここはもうちょっといい書き方があった気がしますガラケー文字入力問題
問題文
問題文(折りたたみ)
英語のガラケーでは「2」キーを2回押すと「b」になり、「3」キーを3回押すと「f」になります。
ただし、この問題では特別ルールとして「0」で文字を確定させます。たとえば、このプログラムに対して"440330555055506660"を入力すると、"hello"が返ってきます。
コード
*keitai_messageの引数はStringとして取っていますが、これはIntegerとするとメソッド呼び出しのとき8進法の数と解釈されてエラーを起こすことがるからです
*入力を10進法のリテラルにするのも違うかな、と考えこうしましたCHARSES = { "1" => %w(. , ! ? \ ), "2" => %w(a b c), "3" => %w(d e f), "4" => %w(g h i), "5" => %w(j k l), "6" => %w(m n o), "7" => %w(p q r s), "8" => %w(t u v), "9" => %w(w x y z) }.freeze def keitai_message(message) nums = message.scan(/([123456789]+)0/).flatten return if nums.empty? nums.map! do |num| chars = CHARSES[num.chr] index = (num.size % chars.size) - 1 chars[index] end nums.join end要点解説
nums = message.scan(/([123456789]+)0/).flattenscanの引数の正規表現にカッコが含まれる場合、カッコの内側にマッチした文字列が配列になって返ります
つまり、"01022"は[["1"], ["22"]]になるわけですね値札分割問題 (回答無し)
問題文
問題文(折りたたみ)
「値段らしき文字列」を「数字部分」と「単位部分」に分割する、split_priceメソッドを作ってください、というプログラミング問題です。
split_price '110.0万円' #=> ['110.0', '万円'] split_price '2015円' #=> ['2015', '円'] split_price '1,123,456円' #=> ['1,123,456', '円'] split_price '110 - 120万円' #=> ['110 - 120', '万円'] split_price '2015円' #=> ['2015', '円'] split_price '価格未定' #=> ['価格未定', ''] split_price nil #=> ['', '']コード
全然わかりませんでした…!
なので本家の模範解答のURLを貼っておきます
【Rubyプログラミング問題】値札分割メソッド(split_price)を作成してください:解答編おわり
以上、「Ruby初心者向けプログラミング問題10選を解いてみた」でした
ここまで読んでいただき本当にありがとうございました!
- 投稿日:2021-01-25T15:59:44+09:00
Sinatraでデータを修正、更新する(CRUDのUpdate機能)
Rubyでシステムを構築する際に、Railsだとちょっとボリュームが多いので、そんな場合は軽量フレームワークとしてSinatra(PythonのFlaskみたいなもの)というものがあります。
そして、色々と使い方を解説したページや記事もあるのですが、なぜかデータの修正、更新機能については触れていないことが多く、それではどうやって作るのかをひたすら調べ、ようやく解決したので、備忘録として置いておきます。
まずは、この記事(自分とは別人です)のように登録機能と削除機能を作ってみてください。自分の記事はそこから補足説明となります。
なぜ、データ修正機能の記事が少ないのか?
日本語サイトでもほとんど見つからなかった上に、MVCの観点を鑑みて、全ての機能を懇切丁寧に解説しているものは皆無だったので、英語サイトも隈なく探してみたのですが、そういったサイトは見つかりませんでした(この記事を作ろうとしたきっかけです)。
その理由は明白で、SinatraはRailsとは異なりコントローラの自動生成が簡単にできない上にRailsと記述が若干異なります。その上、公式ページの解説がかなり不親切なので、実際に機能作成を行った事例が少なく、またそのような例もコントローラ部分の解説にとどまっていることが多く、テンプレート周りの記述事例がほとんどありませんでした。
また、普通にサーバ起動してからデータ更新処理を行うと、処理がもたつきます。したがってRackサーバを使って立ち上げる方が能率的なのですが、そもそもSinatraは軽量が売りでありそこまで大掛かりなものは作らないので、利用目的としては矛盾している(実用的価値が少ない)のもありそうです。このへんも踏まえて解説できたらと思います。
ツリー構造
最低限のデータ構造はこうなっています。Rackを使うので、そのためにはconfig.ruが必要となります。config.ruは自動生成されないので、適宜作成します。
- 任意のプロジェクト名 - db - public - vendor - views edit.erb #編集用 index.erb #リスト config.ru #Ruckの設定ファイル app.rb #コントローラRackの設定
Rackサーバの設定はconfig.ruで行います。色々記事がありますが、最低限これだけ必要です。
config.rurequire './app' #コントローラ run Sinatra::Applicationまた、Rackサーバの起動コマンドは以下の通りとなります(ローカルサーバ接続)。また、rackのデフォルトポートは9292となるので、sinatraと同じように4567にしています(bashを使ってbundle execを省略した場合、rackコマンドで起動可能)。
# bundle exec rackup -o 0.0.0.0 -p 4567コントローラのメソッド記述
データの更新作業は以下のプロセスを経由します。
一覧画面から修正ボタンを押下 → 編集画面に遷移 → 編集画面でデータの編集
→ 編集画面から更新ボタンを押下 →更新処理 → 一覧画面に遷移このうち、編集画面に遷移するにはgetメソッドを使用し、データの編集を反映させるにはpatchメソッドを使用します。また、今回はレコード名がuserとなっているので、以下のディレクトリで処理が行われます。
app.rb#編集データを編集画面(edit.erb)に遷移 get '/users/:id/edit' do @user = User.find_by_id(params[:id]) #該当IDのデータ取得 erb :edit #編集画面の呼び出し end #編集画面での更新処理を反映 patch '/users/:id' do @user = User.find_by_id(params[:id]) #該当IDのデータ情報取得 @user.name = params[:name] #更新データの代入 @user.save #データ更新の反映 redirect to "/" #一覧画面へ end参考にしたサイト
- Sinatra Restful Routes Readme 【英語サイト】
コントローラの全容はこのようになっています。csrf対策のために任意のトークンを発行する必要があります。
app.rbrequire 'sinatra' require 'active_record' #モデルからレコード取得 require 'rack/csrf' #csrf制御に不可欠 use Rack::Session::Cookie, secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxx" #任意のトークン use Rack::Csrf, rise:true ActiveRecord::Base.establish_connection( adapter: 'sqlite3', database: './db/sindb.db' ) class User < ActiveRecord::Base validates :name, presence: true end get '/' do @title = "User List" @users = User.all erb:index end #新規作成 post '/create' do User.create(name: params[:name]) redirect to('/') end get '/users/:id/edit' do @user = User.find_by_id(params[:id]) erb :edit end patch '/users/:id' do @user = User.find_by_id(params[:id]) @user.name = params[:name] @user.save #redirect to redirect to "/" end #削除 post '/destroy' do User.find(params[:id]).destroy endテンプレートの作成
テンプレートの注意点としてはcsrf対策を行わないと403エラーに悩まされることになります(一覧、編集双方で対応が必要です)。
一覧
一覧画面はそこまで難しく考える必要ないですが、actionプロパティの値に変数を埋め込む必要があります。
index.erb<body> <h1><%= @title %></h1> <% @users.each do |user| %> <form method="get" action="/users/<%= user.id %>/edit"> <ul> <li data-id="<%= user.id %>" data-token="<%= Rack::Csrf.csrf_token(env) %>"> <%= Rack::Utils.escape_html(user.name) %> <button type="submit" >修正</button> <button class="delete">削除</button> </li> </ul> </form> <% end %> <form action="/create" method="post"> <%= Rack::Csrf.csrf_tag(env) %> <input type="text" name="name"> <input type="submit" value="追加"> </form> </body>編集画面
編集画面は以下の通りとなります。大事なポイントはpatch処理が必要なので、メソッドをhiddenで埋め込む必要があります。
edit.erb<form action="/users/<%= @user.id %>" method="post"> <%= Rack::Csrf.csrf_tag(env) %> <input id="hidden" type="hidden" name="_method" value="patch"> <input type="text" name="name" value="<%= @user.name %>"> <button type="submit">更新</button> </form>実際の動き
一覧画面(更新前)
ここではshoujiというデータを編集するので、修正ボタンを押します。
編集処理
shoujiをshinjiに変更します。
一覧画面(更新後)
データが反映されます。
- 投稿日:2021-01-25T12:24:02+09:00
[個人メモ] Ruby on Rails 時間計測
p "start : #{Time.now.iso8601(6)}" p "end : #{Time.now.iso8601(6)}"
- 投稿日:2021-01-25T10:42:05+09:00
Rails RSpecテストを導入しよう!
経緯
Railsチュートリアルなどではminitestが使われているが
実際の現場ではRSpecを用いたテストを行っているため
今回はRailsにRSpecを導入するまでの手順を乗せていこうと思います。利用するテスト用ライブラリ
1 RSpec
2 Capybara
3 FactoryBotRSpecのインストールと初期準備
group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'rspec-rails', '~>3.7' end次に以下のgenereteコマンドを実行します。
bundle bin/rails g rspec:install =>Running via Spring preloader in process 4359 create .rspec create spec create spec/spec_helper.rb create spec/rails_helper.rb最後にminitest用のtestディレクトリを削除します。
rm -r ./testCapybaraの初期準備
spec/spec.helper.rbを以下のように編集します。
spec.helper.rbrequire 'capybara/rspec' RSpec.configure do |config| config.before(:each, type: :system) do driven_by :selenium_chrome_headless endFactoryBotのインストール
テストデータを作成支援してくれるFactoryBotを導入します。
Gemfileに以下のように追記します。group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'factory_bot_rails', '~> 4.11' end導入に向けての手順は以上となります。
最後に
ここまで見てくれてありがとうございました!
具体的な書き方については別の機会で解説していこうかなと思います!
- 投稿日:2021-01-25T07:14:40+09:00
Rubyスクリプトにもmainメソッドを定義するといいかも、という話
はじめに
Ruby(Railsではない、単純なRubyスクリプト)では、以下のようにトップレベルで変数を宣言したり、様々な処理を記述したりすることができます。
require 'date' def play puts 'あそぶよー' end def study puts '勉強するよー' end # トップレベルで変数宣言 today = Date.today # トップレベルで条件分岐とメソッド呼び出し if today.sunday? play else study end上のコードの問題点
もちろんこれでもよいと言えばよいのですが、以下のような問題点もあります。
コードリーディング時に下から上に進まないといけない
プログラムとしてのロジックが開始されるのは
today = Date.today
の行からですが、プログラムの構造上、どうしてもメソッド定義(def play
やdef study
)の方を先に書かざるを得なくなります。よって、コードリーディング時(またはコードレビュー時)は先にファイルの下に進んでから、メソッドの内容を確認するために上スクロールしなければならなくなります。
できれば実行の起点となるコードはできればスクリプトの先頭に書いて、上から下へ文章っぽく自然に読みたいところです。
可読性の低いコードを書いてもRubocopに指摘されない
コードレビューを自動化するためにRubocopを導入している人も多いと思います。
しかし、トップレベルに書いたロジックはいくらダラダラと何行に渡って書いても、Rubocopに「長すぎる」と怒られることがありません。
その結果、他の人にとって理解しづらいメソッドを書いてしまう恐れがあります。これがメソッドになっていれば、メソッドの長さをRubocopがチェックしてくれるはずです。
そこでmainメソッドを導入してみる
こういった問題を避けるため、僕は明示的な
main
メソッドを導入することが多いです。require 'date' # トップレベルに書いていたロジックをmainメソッドに移動させる def main today = Date.today if today.sunday? play else study end end def play puts 'あそぶよー' end def study puts '勉強するよー' end # トップレベルではmainメソッドの呼び出しを最後に書くだけ mainmainメソッドを導入するメリット
main
メソッドを導入すると、実行の起点となるコードをスクリプトの先頭に書くことができるので、コードを上から下へ順に読み下しやすくなります。
また、main
メソッドが無駄に長くなるとRubocopのチェックで「メソッド長すぎ!」と指摘されるようになります。なぜmainという名前なのか
main
というメソッド名は任意です。start
でもexecute
でも何でも構いません。
ただ、C言語やJavaなどではmain
メソッド(main
関数)から処理を開始するようになっています。#include <stdio.h> // C言語 int main(void) { puts("Hello, world!"); return 0; }// Java public class Hello { public static void main(String[] args) { System.out.println("Hello, world!"); } }そのため、
main
という名前にしておけば他の開発者も「あ、ここから処理が始まるんだな」と推測しやすくなると思い、この名前を付けるようにしています。まとめ
というわけで、この記事ではRubyスクリプトにmainメソッドを導入する理由やメリットについて書いてみました。
メソッド定義がいくつかあって、1画面に収まらないぐらいの長さのRubyスクリプトを書く場合は、
main
メソッドを導入して可読性を上げることを検討してみてください?
- 投稿日:2021-01-25T01:21:56+09:00
【M1チップ】Homebrew経由でのRubyインストールに苦戦した
概要
プログラミング勉強真っ只中の私ですが、先日M1チップ搭載のMacbook Proを購入しました。
そこでRuby on Railsの環境構築をしようとしたところ苦戦しましたが、初心者の私でもなんとか出来たのでやったことを残しておきます。
(最初はHomebrewって何?美味しいの?ってレベルでした)参考にさせていただいた記事
https://qiita.com/aiorange19/items/5ffaefc85f912f60c2fa動作環境
・Macbook Pro (13-inch, M1, 2020)
・macOS Big Sur (ver11.0.1)Xcodeをインストールして無い人は予めインストールしておくと幸せになれるかもしれません。
(App StoreからDL出来ます)
容量約12GBなのでめっちゃ時間かかった。Homebrewのインストール
Homebrewをインストールします。
https://brew.sh/index_ja公式ドキュメントにも記載があるように、M1チップのMacでは「/opt/homebrew」にインストールすることが推奨されているので、そうしましょう。
自分の場合は何も考えずに公式サイトのコードをコピペして自動的に「/opt/homebrew」にインストールされましたが...。(訳)
ただし、macOSIntelでは/ usr / local、macOSARMでは/ opt / homebrew、Linuxでは/home/linuxbrew/.linuxbrewにインストールしてください。予めディレクトリを作っておいて、インストール先を指定した方が良いかもしれません。
% cd /opt /opt % sudo mkdir homebrew /opt % curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrewbrewコマンドが打てない
しかし、このままだとbrewコマンドが打てなかった
% brew -v zsh: command not found: brewで、ここで最初の壁にぶち当たりましたが、どうやらPATHというものを通さなければならないらしい。
PATHを通すためには「.zshrc」
というファイルにその旨のコードを記述する必要があるっぽいんですけど...% ls -a . Documents Music Public Downloads .. Dropbox .DS_Store Movies Pictures Library Desktop .adobe .zsh_history .cups .zsh_sessions .dropbox .Trash Creative Cloud Files .localそのファイルが無い\(^o^)/
無くて焦りましたが、なかったら作れば良いということで作りました。
作成したら、PATHを通すコードを記述します。% touch .zshrc % open ~/.zshrc # .zshrcに下記を記述 export PATH=/opt/homebrew/bin:$PATH # またはコマンドラインで下記を実行 % echo 'export PATH=/opt/homebrew/bin:$PATH' >> .zshrc # .zshrcが編集できたら設定を反映させるために下記を実行 % source .zshrcbrewコマンドが使えるか確認してみる。
% brew -v Homebrew 2.7.5 # Homebrewのバージョンが表示されればOK無事PATHを通せました。
rbenvでRubyのインストール
Homebrewがインストール出来たら、Rubyのバージョン管理ができるようにrbenvをインストールします。
% brew install rbenvこれも先ほどと同じようにPATHを通す必要があるので、
.zshrc
に追記します。% open ~/.zshrc # 下記を記述 export PATH="$HOME/.rbenv/bin:$PATH" eval "$(rbenv init -)" # またはコマンドラインで下記を実行 % echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> .zshrc % echo 'eval "$(rbenv init -)"' >> .zshrc # 設定を反映 % source .zshrcこれでRubyインストールの準備完了です。
Rubyのインストール
# 公開されている(DL可能な)Rubyのバージョン一覧を確認 % rbenv install -l 2.5.8 2.6.6 2.7.2 3.0.0 jruby-9.2.14.0 mruby-2.1.2 rbx-5.0 truffleruby-21.0.0 truffleruby+graalvm-21.0.02020年12月25日に
Ruby 3.0.0
が公開されましたが、ここでは2.7.2
をインストールしました。
Ruby 3.0.0はなんか動作が早くなったとか...。
もうちょっと勉強したらアップデートしようと思います。ということでRubyをインストール
% rbenv install 2.7.2、、、しようとしましたがなぜか上手くいかない。
いろいろ調べると、
openssl
関連で上手くいっていないようでした。
とりあえずインストールを試みましたが...% brew install openssl Error: /opt/homebrew/opt/openssl@1.1 is not a valid kegなんやこれ...
このエラー解消に結構時間がかかってしまいました。結果、
/opt/homebrew/Cellar
に作られてたopenssl@1.1
というフォルダが空だったので、一度削除したらインストール出来ました。
インストール出来ましたが、また
.zshrc
を編集してPATHを通します。% which openssl /usr/bin/opensl # homebrewへPATHを通しましょう # .zshrcに下記を追記 export PATH="/opt/homebrew/opt/openssl@1.1/bin:$PATH" export LDFLAGS="-L/opt/homebrew/opt/openssl@1.1/lib" export CPPFLAGS="-I/opt/homebrew/opt/openssl@1.1/include" export PKG_CONFIG_PATH="/opt/homebrew/opt/openssl@1.1/lib/pkgconfig" export RUBY_CONFIGURE_OPTS="--with-openssl-dir=/opt/homebrew/opt/openssl@1.1" # 設定を反映 % source .zshrc # 再度opensslの場所を確認 % which openssl /opt/homebrew/opt/openssl@1.1/bin/openssl % openssl version OpenSSL 1.1.1i 8 Dec 2020 # ちゃんとインストール出来てる # homebrewへリンクを通す % brew link opensslこれでようやくRubyをインストールできるはず!
% rbenv install 2.7.2 Downloading ruby-2.7.2.tar.bz2... -> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.2.tar.bz2 Installing ruby-2.7.2... ruby-build: using readline from homebrew BUILD FAILED (macOS 11.0.1 using ruby-build 20210119) Inspect or clean up the working tree at /var/folders/p8/krxwz5vn6ld7l4_bc2g1xnbr0000gn/T/ruby-build.20210124030531.27274.KLMWnZ Results logged to /var/folders/p8/krxwz5vn6ld7l4_bc2g1xnbr0000gn/T/ruby-build.20210124030531.27274.log Last 10 log lines: checking for off_t... yes checking char bit... 8 checking size of int... 4 checking size of short... 0 checking size of long... 0 checking size of long long... configure: error: in `/var/folders/p8/krxwz5vn6ld7l4_bc2g1xnbr0000gn/T/ruby-build.20210124030531.27274.KLMWnZ/ruby-2.7.2': configure: error: cannot compute sizeof (long long) See `config.log' for more details You have not agreed to the Xcode license agreements, please run 'sudo xcodebuild -license' from within a Terminal window to review and agree to the Xcode license agreements....あれ?
最後を見ると、Xcodeインストールしとけや!って書いてありますね。
はい。自分は最初にインストールしてなかったのでここでまた無駄なダウンロード待ち時間が発生しました。3度目の正直
Xcodeをインストールし、再度実行。さすがに頼む。
% rbenv install 2.7.2 Downloading ruby-2.7.2.tar.bz2... -> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.2.tar.bz2 Installing ruby-2.7.2... ruby-build: using readline from homebrew Installed ruby-2.7.2 to /opt/homebrew/opt/rebind/versions/2.7.2出来たーーー!!
あとは下記の流れに沿って...
% rbenv versions * system (set by /opt/homebrew/opt/rebind/version) 2.7.2 % rbenv rehash % rbenv global 2.7.2 % rbenv versions system * 2.7.2 (set by /opt/homebrew/opt/rebind/version) % ruby -v ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [arm64-darwin20]これでRubyのバージョン切り替えができるようになりました!
Ruby on Railsのインストール
Railsもインストールしておきましょう。
% gem install rails # バージョン指定しなければ最新版がインストールされる...と思います。 # 最後に一通り更新しておく % rbenv rehash % source ~./zshrc # Railsのバージョン確認 % rails -v Rails 6.1.1これでRuby on Railの環境も整いました!
ここまで長かった...
環境構築って大変
プログラミングを挫折する人が多い理由の一つに環境構築が大変、というのをよく目にしますが、よく分かった気がします。笑
しかし、色々根気強く調べながらやっていけばなんとかなる!とも思いました。
先輩エンジニアの方々の情報にはとても感謝です。まだまだ駆け出しの駆け出しですが、もっと頑張るぞ〜