- 投稿日:2020-02-27T23:49:22+09:00
多対多テーブルの作り方
データベース設計
投稿(postテーブル)に対してタグ(tagテーブル)付けができる機能を作るとします
一つの投稿は複数のタグを持つことができ、一つのタグは複数のタグを持つことができる場合、そのままアソシエーションを組んでしまうとデータベースの中身が複雑になってしまいます。
そのためどの投稿がどのタグに結びついているのかを記憶するテーブルを別に作り、整理します。内容
postテーブルを作る
ターミナルrails g model Post image:texttagテーブルを作る
ターミナルrails g model Tag name:string中間テーブルを作る
中間テーブルは各モデルの複数形を名前をスネーク型で繋げます
今回の場合はPosts_tags
postとtagの結びつきを記憶するテーブルのため各idのカラムを作ります
refarencesの型はこの後記述するマイグレーションファイルに記載するforeighn_keyの制約に対応した型になります。
foreighn_keyはpost_idやtag_idカラムに対してpost_idに対応したpostsテーブルのidがあることを保証する制約です。
例)post_id:1 tag_id:1 であればpostsテーブルにid:1の投稿があり、tagsテーブルにもid:1があることを保証しています。ターミナルrails g model Posts_tags post_id:refaremces tag_id:refarencesアソシエーション
多対多テーブルのアソシエーションはthroughを使用します。
postとtagは関連しているがposts_tagsを経由して関連することを表します。ppst.rbhas_many :posts_tags has_many :tags, through: :posts_tagstag.rbhas_many :posts_tags has_many :posts, through: :posts_tagsposts_tag.rbbelongs_to :post belongs_to :tagマイグレーションファイル
マイグレーションファイルclass CreatePostsTags < ActiveRecord::Migration[5.2] def change create_table :posts_tags do |t| t.refarence :post_id, foreign_key: true t.refarences :tag_id, foreign_key: true t.timestamps end end end完成
これで多対多テーブルの作成が完了します。
※sqliteでrefarences型を使用しようとしたところマイグレーションができませんでした。integer型に変更したところマイグレーションできたので、sqliteではrefarences型は使用できないようです。
- 投稿日:2020-02-27T23:30:17+09:00
【Ruby on Rails 5】Instagram風簡易SNSアプリを作ってみよう!(Techpit教材)を終えて
Techpitの【Ruby on Rails 5】教材の感想
TechCommitさんのお年玉企画にて頂いたTechpit教材を使って、Ruby on Rails 5で簡易アプリを作成しました。
簡単ではありますが、どのようなことを学べたのか、その感想を記します。また、当方実務経験などが全く無く、言語を独学で学んでいる程度なので、経験も知識も非常に浅いことをご了承願います。
教材に取り組む上で必要な知識
まず、【Ruby on Rails 5】instagram風簡易SNSアプリを作ってみよう!という教材は、以下の言語を使用します
- HTML
- CSS
- Javascript
- Ruby
必要条件はHTML/CSS、及びRubyの基礎知識とされています。
主な目的はRuby on Railsの流れを把握するものであり、
SNSのinstagramを参考にしたアプリ作成を進める内容となっています。今回の教材に取り掛かるにあたって、HTMLとCSS、Rubyの基礎知識をProgateで補っています。
教材は、2回ほど繰り返し学習を行いました。※教材内でHTML/CSSは多く使われますが、詳しい解説はありません。
教材の流れと大まかな内容
- 環境構築
- Mac -Homebrew
- Windows -Cloud9
- Railsアプリケーション作成
- Gemインストール
- ローカルサーバー立ち上げ
- MVC知識
- Bootstrap導入
- 機能を付ける
- サインアップ・サインイン
- プロフィール
- 画像投稿
- いいね
- コメント
- デプロイ
- Herokuを利用してサービス公開
- pry-railsを用いたデバック方法
どのファイルでどのコードを記述するか、コードの意味から、詳しい情報が書いてある詳細ページのリンクも要所要所あります。
また、各項ごとに質問投稿欄があり、わからないことが運営へ質問出来るようになっていました。
全体を通しての感想
プログラミング超初心者ながら教材を終えて、感想を大きく三つあります。
- 初心者にも作れるわかりやすさ
- 使用する知識が多い
- エラーに慣れてくる
初心者にも作れるわかりやすさ
アプリを作るというと難しそうだなとは思っていましたが、
一つ一つのページを作り、それを組み立てるような流れでわかりやすかったので、
進めていければアプリ作成・公開まで行うことが出来ます。使用する知識が多い
教材内容全てを理解する、というのは、特に言語など基礎の基礎を学んだだけでは出来ませんでした。使用する言語も多い(ように感じた)ので、基礎知識しか無い段階で全て理解しようとすると相当な時間がかかると思われます。
といっても、そもそもこの教材の一番目的がRuby on Railsの流れを把握することなので、まずは流すように取り組むだけでも、大枠が見えてきます。
細かいことを知りたい時はそのページで質問するでも、リンクを参考にするでも可能なところが良かったです。エラーに慣れてくる
私が初心者なせいかとは思いますが、教材通りにしているつもりでもどこかしらでエラーが起きて躓いてしまうことが多々ありました。
しかし自分が躓いていることは大体他の人も躓いていることが多かったので、特に各項の質問投稿欄は、同じエラーで解決した人が居たりして、非常に助けになり、また、何度かエラーを繰り返すことでエラーの直し方や着目すべきところも以前より見えるようになった気がします。
まとめ
長くなりましたが、この教材の対象者でもあるように、Ruby on Rails開発の流れをつかみたい人、アプリを作成してみたい人、特にRubyを学んでいる方にはおすすめです。
しかし感想でも触れましたが、やはり言語の面での自分の知識不足が痛かったです。
基礎知識をしっかり固めてやると、もっと入りやすいのかなと思いました。教材としては扱いやすくてとても良かったです。アプリ作成、そしてサイトの公開まで学べるという点で、知識の色んな活用の仕方が出来るのではと思います。
- 投稿日:2020-02-27T22:33:21+09:00
Ruby学習のためのローカル開発環境構築
Ruby学習のために手元のPCにローカル環境構築(VirtualBox、Vagrant)を行った仮定を忘れないようメモ代わりにまとめます。ローカル開発環境を構築する必要が何故あるのか
サーバーサイド言語(PHP、Ruby、Javaなど)は、サーバー側でプログラムを実行するので、サーバーへの接続を行います。
そのためには、サーバーを借りる必要があるのですが、コストがかかってしまったり、手元のPCの情報を24時間インターネット上に公開するというデメリットもあります。
それならば、同じ環境を自分のPC内に構築すれば、コストもかからず、ネット上に公開せずにWebアプリやWebサイトの開発、テストも行えて便利だよね!ということで、手元に置いておける環境(ローカル環境)が必要になります。
※ちなみにフロントエンド言語(HTML、CSS、JavaScript)は、ブラウザ上で動くため、サーバーとの通信を必要とせず、htmlファイルを用意しブラウザにドラッグ&ドロップすれば表示されるので、動作確認だけならブラウザとhtmlファイルがあれば可能であり、開発環境は必要ない。
※またここでいきなり今回のテーマをぶち壊しますが、ローカル環境構築を作るのではなく、ブラウザ上にサーバー環境を構築してくれるCloud9というサービスもあります。
ので、今後こちらも利用し学習する予定です。今は忘れます。ローカル環境構築までの流れ
1. VirtualBoxをインストール
VirtualBox:仮想マシン本体ツール。手元のPCにいくつものサーバー(例えば1つを勉強用、もう1つを作りたいWebサーバーの開発用)を立ち上げることができる。
2. Vagrantをインストール
Vagrant:サーバーの設定やOSのインストール作業などをするのが複雑なVirtualBoxを、簡単なコマンドで扱えるようにしてくれるツール。
直接扱っていくのはVagrant、VirtualBoxは直接扱わないが、Vagrantコマンドを通じて裏でVirtualBoxは動いているというイメージ。
3.サーバーを立ち上げる。
サーバー1つにディレクトリ(今回は『MyCentOS』)が1つ必要。(複数のサーバー=複数のディレクトリをまとめられる大元のディレクトリ(今回は『MyVagrant』)を作成すると管理しやすい。)
MyCentOSディレクトリの中でサーバーを立ち上げ、サーバーの設定ファイルをVagrantのコマンドで作る(Vgrantfileを作りIPアドレスの設定などのサーバーの設定をする)
Vgrantfileの設定を読み込んで、裏でVirtualBoxを立ち上げてサーバーを作ってくれるという仕組み。
4.仮装マシンを立ち上げる
ターミナル起動#ホームディレクトリに移動し、今後複数の仮想マシンを作ることを想定して、それらをまとめるディレクトリ(MyVagrant)を作る ~ $ cd ~ $ mkdir MyVagrant #作成したディレクトリ(MyVagrant)へ移動。(移動できてればプロンプト部分に『MyVagrant』と表示される) ~$ cd MyVagrant #仮想マシンを入れるディレクトリ(MyCentOS)を作り、移動。(移動できてればプロンプト部分に『MyCentOS』と表示される) MyVagrant $ mkdir MyCentOS MyVagrant $ cd MyCentOS #仮想マシンを設定するための『Vagrantfile』を作る MyCentOS $ vagrant init bento/centos-6.8 #Vagrantfileを編集して仮想マシンのIPアドレスを192.168.33.10にする MyCentOS $ sed -i '' -e 's/# config.vm.network "private_network", ip: "192.168.33.10"/config.vm.network "private_network", ip: "192.168.33.10"/' Vagrantfile # 仮想マシンを起動 MyCentOS $ vagrant up # 仮想マシンの状態を確認する。『running』と表示されれば仮想マシンが起動されている。 MyCentOS $ vagrant status
5.仮想マシンの設定#立ち上げたサーバーにログインする(Vagrantfileのあるディレクトリから) MyCentOS $ vagrant ssh #サーバーが立ち上がりOSがインストールできたが、アプリケーションがインストールされていないので行う。OS最新状態にアップデートする。 [vagrant@localhost ~]$ sudo yum -y update # スクリプト(プログラム)を入手するためのgitをインストール [vagrant@localhost ~]$ sudo yum -y install git # gitを使ってアプリケーション設定用のスクリプトをダウンロード。centos6ディレクトリが作成される。 [vagrant@localhost ~]$ git clone https://github.com/dotinstallres/centos6.git # centos6フォルダへ移動 [vagrant@localhost ~]$ cd centos6 # スクリプトを実行 [vagrant@localhost centos6]$ ./run.sh # 他の設定を反映 [vagrant@localhost centos6]$ exec $SHELL -l
6.仮装マシン上のファイルを簡単に扱えるようにするため、ファイル転送ツール『Cyberduck』(FTPクライアントソフト)のインストールを行う7.仮想マシンにアクセスする
Cyberduckの『新規接続』→『SETP』→サーバーに上記で設定したIPアドレスを入力→ユーザ名、パスワード共に『vagrant』→接続
※今後も同じサーバーにアクセスしやすいようにブックマークしておくと便利。
→ブックマークメニュー→新規ブックマーク→ニックネームに『MyCentOS』で完了
8.Ruby学習用のディレクトリ作成
右クリック→『新規フォルダ』→『Ruby_lessons』作成
『Ruby_lessons』へ移動→『新規ファイル(index.rb)』作成
この作成したファイルをクリックすると、設定したエディタが起動する。これでRubyを学習する環境の完成です。
補足
●仮装マシンからのログアウト方法
・ブラウザやファイル転送ツールを終了させる
・ターミナルにて[vagrant@localhost ruby_lessons]$ exit #仮想マシンからログアウトしMacの方へ操作が移る MyCentOS $ vagrant suspend #仮装マシン停止 MyCentOS $ exit #ターミナル終了※ターミナルメニューにて『環境設定』→『プロファイル』→『シェル』→『シェルの終了時:シェルが正常に終了した場合は閉じる』に設定しておくと、ターミナル終了時に自動でウィンドウが閉じる
※上記のように『exit』と入力しなくてもターミナルのウィンドウを閉じても終了はできるがコマンドを入力し正式に終了させる癖をつけておく
●仮想マシンに再びログインする方法
・ターミナル起動#ホームからMyVagrant(仮想マシンをまとめたディレクトリ)へ移動 ~ $ cd MyVgrant #MyVagrantからMyCentOS(仮装マシンのディレクトリ)へ移動 MyVagrant $ cd MyCentOS #仮装マシン起動 MyCentOS $ vagrant up #仮想マシンの状態確認(running表示でOK) MyCentOS $ vagrant status #仮想マシンへログイン MyCentOS $ vagrant ssh ([vagrant@localhost ~]$となればログインできている)最後に
以上、自分なりに仮定をまとめてみました。拙い文章でしたが、ここまでお読みいただきありがとうございました。
何か誤っている点がありましたら、お教えいただけるとありがたいです。
- 投稿日:2020-02-27T22:16:29+09:00
複数の配列にeachメソッドを使いたい
rubyのzipメソッドを使えば可能
Ruby 2.7.0 リファレンスマニュアルよりサンプルコードを引用
p [1,2,3].zip([4,5,6], [7,8,9]) # => [[1, 4, 7], [2, 5, 8], [3, 6, 9]] p [1,2].zip([:a,:b,:c], [:A,:B,:C,:D]) # => [[1, :a, :A], [2, :b, :B]] p [1,2,3,4,5].zip([:a,:b,:c], [:A,:B,:C,:D]) # => [[1, :a, :A], [2, :b, :B], # [3, :c, :C], [4, nil, :D], [5, nil, nil]] p [1,2,3].zip([4,5,6], [7,8,9]) {|ary| p ary } # => [1, 4, 7] # [2, 5, 8] # [3, 6, 9] # nil参考
https://docs.ruby-lang.org/ja/latest/method/Array/i/zip.html
- 投稿日:2020-02-27T22:15:23+09:00
Ruby/GTK3 - Switch
gem install gtk3
Switch
Gtk.Switchは、オンまたはオフの2つの状態を持つウィジェットである。
シグナルはnotify::active
に接続するのがよいとのこと。require 'gtk3' class SwitcherWindow < Gtk::Window def initialize super set_title 'Switch Demo' set_border_width 10 grid = Gtk::Grid.new grid.set_column_spacing 6 grid.set_row_spacing 6 add grid 4.times do |i| 2.times do |j| switch = Gtk::Switch.new switch.signal_connect('notify::active') { |s| on_switch_activated s } switch.set_active [true, false].sample grid.attach switch, i, j, 1, 1 end end end def on_switch_activated(switch) state = switch.active? ? 'on' : 'off' puts "Switch was turned #{state}" end end win = SwitcherWindow.new win.signal_connect('destroy') { Gtk.main_quit } win.show_all Gtk.main
- 投稿日:2020-02-27T20:34:00+09:00
標準入力で連続した数値を受け取る方法(paiza用)
Rubyで文字列ではなく連続した数値を入力したい
paizaの問題を解くときに標準入力で数値を受け取りたいが、paizaの入力方法ではgets.to_iだけでは不十分だったのでメモとして残します。
NG例
入力は以下である場合
1 2 3example.rbnumber = gets.chomp.split.map(&.to_i) puts numbermap(&.to_i)のように'&'の後に'.'をつける方法がネットによく出ているが、paizaの環境ではsyntaxエラーがでて動かない。
成功例
example.rbnumber = gets.chomp.split.map(&:to_i) puts number'.'を':'に変えると動いた。
- 投稿日:2020-02-27T20:23:46+09:00
bin/rails db:migrateしようとしたらMysql2::Error: Table '*****' doesn't existが出る
経緯
bin/rails g model imageと
bin/rials g model productによって作られたマイグレーションファイル
20200227092210_create_images.rbと
20200227092647_create_products.rbを,20200227092210_create_images.rb(中略) t.references :product, foreign_key: true (中略)と書いて, bin/rails db:migrate を実行
起きたエラ〜
(中略) rails aborted! StandardError: An error has occurred, all later migrations canceled: Mysql2::Error: Table 'プロジェクト名_development.products' doesn't exist: SHOW FULL FIELDS FROM `products` (中略)というエラーが発生した。
解決策
スペルのミスも、文法ミスも、探したけれど見つからないよ♪...
なので、googleで検索したところ、参考になる記事を発見。どうやら、
referencesされるマイグレーションファイル
の方が先にmigrateされるべきなようで、
20200227092647_create_products.rbを、
→2020022709 2209_create_products.rb
(20200227092210_create_images.rb)
にすると、images.rbよりも早くmigrateされた!!参照したwebページ
- 投稿日:2020-02-27T19:45:39+09:00
rails:DM送信機能を簡単に実装〜model〜
ダイレクトメッセージ機能
検索に苦労したのでDM機能について簡単に実装手順を紹介します。
前提として、DM機能の実装には
①トークルームを作成してそこで話す機能を実装する方法(中間テーブルが2つ)
②トークルームを作成しない方法
があります。今回は②についての説明です。
ER図
roomモデルを作らなくても作成できる理由は、routesで設定できます。
手順
usersモデルがある前提で書きていきます。
$ rails g model Messages content:string user:references receive_user:referencesMessages modelとmigrateファイルを作成します。
完成したものがこちら
_create_messages.rbclass CreateMessages < ActiveRecord::Migration[5.2] def change create_table :messages do |t| t.string :content t.references :user, foreign_key: true t.references :receive_user, foreign_key: { to_table: :users } t.timestamps end end end_create_messages.rb{ to_table: :users }を追記しています。
これが無いと、receive_usersテーブルを参照してしまうので『そんなテーブルは存在しないよ』と言われてしまいます。
そのため、外部キーとしてusersテーブルを参照するという指定を行っています。$ rails db:migrate↑します。
続いて、model
models/message.rbclass Message < ApplicationRecord belongs_to :user belongs_to :receive_user, class_name: 'User' endmodels/message.rbclass_name: ‘User’を追加します。
これによって、receive_userがReceive_userという存在しないクラスを参照することを防ぎます。models/user.rbhas_many :messages has_many :sent_messages, through: :messages, source: :receive_user has_many :reverses_of_message, class_name: 'Message', foreign_key: 'receive_user_id' has_many :received_messages, through: :reverses_of_message, source: :user def sent_messages(other_user, content) #メッセージを送るためのメソッド unless self == other_user self.messages.find_or_create_by(receive_user_id: other_user.id, content: content) end endこれで完成です!
しっかり作成できるか $ rails cで確認することは忘れないでください?♂️
補足
修正依頼などあれば気軽にお申し付けください。
- 投稿日:2020-02-27T18:29:43+09:00
Net::HTTP::Get を用いた HTTP リクエスト - クエリパラメータを簡単に渡す方法
経緯
- Ruby 2.6.5 の Net::HTTP::Get を使って HTTP リクエスト を実行していたが、 クエリパラメータ を簡単に渡して実行する方法がなかった。
- Post なら
post_form
というメソッドがあって、 比較的楽にできる。コード
class Sample def self.get(path, params = {}, header = {}) uri = URI(path + build_query_string(params)) request = Net::HTTP::Get.new(uri) header.each do |key, value| request[key] = value end response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http| http.request(request) end response.body end private # @param [Hash] params def self.build_query_string(params) if params.length === 0 return '' end query_string_parts = [] params.each do |key, value| if value.is_a? Array value.each do |single_value| query_string_parts << "#{key}[]=#{single_value}" end next end query_string_parts.push("#{key}=#{value}") end return '?' + query_string_parts.join('&') end end注意点
{'a': [1, 2, 3]}
を Getパラメータ に使った場合は、?a[]=1&a[]=2&a[]=3
という文字列が URL に追加される。
- 投稿日:2020-02-27T17:00:42+09:00
Rubyの基礎
最初に
自身で学習してきた内容を書き出していきます。
基本的には自分自身でわかるような内容になりますので、ご容赦ください。
また、誤っている点がありましたら、コメントにてご指摘ください。!! (要確認)マークがあるものは実行前に必ずググるべき内容 !!
index
- 基本文法
- Hello, World!
- データ型について
- オブジェクトとメソッド
- オブジェクトとは
- メソッドとは
- 変数と定数
- 変数とは
- 定数とは
- データ型
- 数値(0除算について)
- 文字列
- 配列
- ハッシュ
- シンボル
- 条件分岐
- if文
- 比較演算子
- 論理演算子
- elsif、else
- 繰り返し処理
- 文字列や数字をキーボードから入力する方法
- gets
- to_i
- 繰り返し処理や要素を順に取り出す処理
- while文
- for文
- each文
- break
基本文法
Hello, World!
xxx.rbputs 'Hello, World!'ターミナルruby xxx.rb(実行するプログラムファイル名) # 結果 Hello, World!基本的に、xxx.rbのようなファイルを作りやりたいことを記述、ターミナルで動かす流れ。
ターミナルtouch xxx.rb # ターミナルコマンドでからファイルを作成、ここに処理を記述していく ruby xxx.rb # 実行 # 結果 # 記述した処理がここに出るデータ型について
文字列型(String「""」)と整数型(Integer「 」)がよく使われる。
詳しくは後日、投稿予定。xxx.rbputs 5 + 3 puts "5 + 3" puts "5" + "3"ターミナルruby xxx.rb # 結果 8 # 両方integerなので、「5+3」の計算結果 5 + 3 # 計算式をstringで囲っているので、「文字としての"5+3"」が表示される結果 53 # 文字列と文字列を足しているので、「文字としての"5"と"3"」が連続して表示される結果同じ見た目のメソッドでも、中身が異なる場合があるが、めちゃくちゃ便利。
文字列型、整数型の型変換
to_s 27.to_s # 数字→文字へ変換,この場合は文字列型の27になる to_i "27"to_i # 文字→数字へ変換,この場合は整数型の27になるオブジェクトとメソッド
オブジェクトとは
操作対象の状態(データ)と便利な機能(メソッド)を1つにまとめたもの
オブジェクトは「~~のもの」メソッドとは
オブジェクトが持っている固有の機能や処理のこと
メソッドは「~~するもの」つまり・・・?
puts "XXXYYYY".length # 結果 7 # 「文字列オブジェクト」を「lengthメソッドで文字数を数え」、結果を「出力(puts)」他にも、「reverse(文字列を逆にする)」メゾットや、「include?(引数に指定した文字列が含まれているか)」メゾットなどがある。
(メソッドが使えるのかを一覧表示したい場合は、使用可能なメソッド一覧を表示できる「methods」メソッド)
include?の場合は、「true(真)」か「false(偽)」で結果が表示される。変数と定数
変数とは
オブジェクトにつける名札。
名札をつけることで、欲しいデータを呼び出すことが用意になる。
ただし、変数名は小文字で始まるルールがあり、尚且つ数字は使えない。test = "テストコメントが表示されることを確認しよう" puts test # 結果 テストコメントが表示されることを確認しよう変数名 = 入れたいデータ
ポイント : 「=」は数学的な等しいという意味ではなく、「右のオブジェクトを左の変数に代入する」という意味。定数とは
あらかじめ変更しないことが保証された数値やデータにつける名札。
基本的に大文字で始まる。
⚠️値を書き換えることができない点に注意⚠️
(warning(実行不可能なエラーではないが非推奨な使い方)が表示されて書き換えができてしまうが、エラーが出る時点でアウト。)Xx = 3.14 puts Xx # 結果 3.14 Pi = 3.14 puts Pi Pi = 100 puts Pi # 結果 3.14 pi.rb:4: warning: already initialized constant Pi pi.rb:1: warning: previous definition of Pi was here 100データ型
数値
「1」「100」「-100」「0」などの整数や、「3.14」などの小数のこと
メソッドとしては、+(足し算)、-(引き算)、/(割り算)、*(掛け算)、%(割り算の余りの計算)などの四則演算。puts 100 # 結果 100 puts 100 + 5 # 結果 105ポイント : 0除算について
任意の数字 を0で割ってはいけないという数学的ルールがプログラミングにも適用されるぞ。
詳しくは後日投稿予定。
[四則演算注意点] 数字を0で割ってはいけないプログラム計算式文字列
シングルクォートやダブルクォートで囲むことで、文字列として出力。
文字列の中に#{変数}と記述することによって、{}内の変数の値を展開可能。
+を使うと、文字列の連結も可能になり、文字列同士だけでなく、文字列と変数、または変数同士でも、連結できる。puts "Rubyを学習" # 結果 Rubyを学習 name = "テストさん" puts "Hello" + name # 結果 Helloテストさん puts "こんにちは#{name}" # 結果 こんにちはテストさん配列
配列を使うと、複数のデータをまとめて保存できる。
配列の各要素には、どのようなオブジェクトでも代入でき、同じ配列の要素に異なった種類のオブジェクトを代入することも可能。
しかも、データ型は問われず、文字列でも数値でも代入できる。
ただし、先頭から0、1、2というように「インデックス番号」が割り振られ、「0」から開始することに注意。names = ["Ruby", "Java", "Python", "PHP"] puts names[1] # 結果 Javaポイント : たまにeach文で回したデータをarray(からの箱的な感じ)に突っ込んだりする。
ハッシュ
ハッシュは、キーと値をセットで保存できるデータの集合。
配列では各要素にインデックス番号が割り振られるが、ハッシュでは任意の値(キー)を割り振ることができる。tall = {"あい"=>185, "うえ"=>170, "お!"=>150} puts tall["あい"] # 結果 185シンボル
シングルクォートやダブルクォートの代わりにコロンを使用することで、文字列と同様に扱うことが可能。
tall = {:かき=>185, :くけ=>170, :こ!=>150} puts tall[:こ!] # 結果 150条件分岐
if文
「もしAならばBを実行し、AでなければCを実行」
条件に当てはまればtrue、当てはまらなければfalseという真偽判定ができる。apple = 110 if apple >= 100 puts "りんごの値段は100円以上です" #true=>処理される end if apple <= 100 puts "りんごの値段は100円以下です" #false=>処理されない end # 結果 りんごの値段は100円以上です # apple = 110のためtrue処理になった比較演算子
「条件を比較して判定する」時に使用する記号とかのこと。
< # 右辺の方が大きい <= # 右辺の方が大きい、または等しい > # 左辺の方が大きい >= # 左辺の方が大きい、または等しい # 数値だけでなく、文字列の比較(同じ文字列かどうか)でも利用できる == # 右辺と左辺が等しい != # 右辺と左辺が等しくないとき論理演算子
「2つ以上の条件を判定する」時に使用する。
! # 否定 && # どちらの条件も正しければtrue || # どちらかの条件が正しければtrue tall = 180 if tall >= 170 && tall <= 190 puts "身長は170以上190以下です。" end # 結果 身長は170以上190以下です。elsif、else
if(もし〜)文では、elsif(それとも〜)やelse(当てはまらないなら〜)を使うことで、ifの条件に当てはまらなかった場合の処理を設定できる。
else
apple = "A" if apple == "A" #もしappleがAなら puts "それはAのリンゴです" else #ifが当てはまらない場合は puts "そのリンゴはAではないです" end # 結果 A typeのリンゴですelsifとelse
apple = "B" if apple == "A" #もしappleがAなら puts "そのりんごはAです" elsif apple == "B" #それともappleがBなら puts "そのりんごはBです" else #どちらも当てはまらない場合は puts "そのりんごはCです" end # 結果 そのりんごはBですよくFizzBuzz問題としてここあたりが使われると思う。
繰り返し処理
全て100%覚える必要はないが、処理ごとの特徴くらいは覚えよう。
文字列や数字をキーボードから入力する方法
gets
キーボード入力された値を取得するメソッド。
getsを使うと、キー入力待ちの状態になり、文字を入力してEnterキーを押すまで次に進まない。
文字列として返されるぞ。to_i
文字列を整数に変換するメソッド。
例えば、getsメゾットにto_iを使って文字列(String)を整数(Integer)に変換すると計算ができる。puts "キーボードで数字「2」と数字「3」を入力してください" a=gets.to_i b=gets.to_i puts "a+b=#{a+b}" # 結果 a+b=5繰り返し処理や要素を順に取り出す処理
while文
繰り返し処理を行いたいときに使用し、指定した条件式が真(true)の間、繰り返し実行されるのが特徴。
while 条件 do #条件がtrueの間 処理 #処理を繰り返す end # サイコロを振って「6」が出るまで繰り返し実行 dice = 0 # diceに0を代入し、初期値を設定 while dice != 6 do # サイコロの目が6ではない間、diceの初期値は0なので条件を満たす。 # 以降はdiceに代入される数によって結果が異なる dice = rand(1..6) # 1~6の数字がランダムに出力 puts dice end # 結果 ~ 6 # サイコロを振って「6」が出るまで繰り返し実行された最後の数字として6で繰り返し処理が止まるfor文
繰り返し処理を行いたいときに使用し、指定したオブジェクトから順に値を取り出しながら繰り返されるのが特徴。
for 変数 in 範囲、ハッシュ、配列などを指定 do 処理 end # for ~ end内で、1から10まで順番に表示する処理を繰り返す実行 for i in 1..10 do # 1..10は、1~10までの範囲を表す puts i end # 結果 1 2 3 ~ 9 10 # 1から10まで順番に表示されるため10で止まるeachメソッド
オブジェクト内の要素を順に取り出すメソッド。
個人的に一番使う繰り返し処理。
繰り返し処理を行いたいときに使用し、データの先頭から順に繰り返して処理されるmのが特徴。(範囲、ハッシュ、配列などを指定).each do |変数| 実行する処理 end apple: 130 strawberry:180 orange:100 という結果が欲しいと仮定 {"apple"=>130, "strawberry"=>180, "orange"=>100}.each do |fruit, price| # ハッシュの内容を順にキーをfruit、値をpriceに代入して繰り返す puts "#{fruit}は#{price}円です。" # 変数展開 end # 結果 appleは130円です。 strawberryは180円です。 orangeは100円です。地味にポイントなのが、|fruit, price|のように、左から入っていく。
さらに付け加えると、平均点を求める際にも使える。xxx_controller.rbratesum = 0 # 初期値は0 movie_comments.each do |comment| # movie_commentsを繰り返し、1つ1つをcommentとする ratesum += comment.rate # 初期値0に対して、comment.rateという数字を存在するだけ、足し算し続ける end # @averageに平均点を代入 # movie_comments.length(配列の要素数を取得)した時、0なら0,0ではなかったら計算して欲しい処理をしてもらう @average = movie_comments.length == 0 ? 0 : ratesum / movie_comments.length # comment.rateを足し続けた数字に対して、存在する配列の要素数で割ることで、平均点を割り出す。break
繰り返し処理を中断することができる。
whileやfor、eachなどの繰り返し文の中で利用する。i = 0 while i <= 10 do if i >5 break # iが5より大きくなると繰り返しから抜ける end puts i i += 1 end # 結果 0 1 2 3 4 5追加あれば、どんどん更新していきます。
駆け出しとして頑張ります。
- 投稿日:2020-02-27T17:00:42+09:00
Rubyの基礎について
最初に
自身で学習してきた内容を書き出していきます。
基本的には自分自身でわかるような内容になりますので、ご容赦ください。
また、誤っている点がありましたら、コメントにてご指摘ください。!! (要確認)マークがあるものは実行前に必ずググるべき内容 !!
index
- 基本文法
- Hello, World!
- データ型について
- オブジェクトとメソッド
- オブジェクトとは
- メソッドとは
- 変数と定数
- 変数とは
- 定数とは
- データ型
- 数値(0除算について)
- 文字列
- 配列
- ハッシュ
- シンボル
- 条件分岐
- if文
- 比較演算子
- 論理演算子
- elsif、else
- 繰り返し処理
- 文字列や数字をキーボードから入力する方法
- gets
- to_i
- 繰り返し処理や要素を順に取り出す処理
- while文
- for文
- each文
- break
〜主な流れ〜
ターミナル$ touch xxx.rb # ターミナルコマンドでからファイルを作成、ここに処理を記述していく $ ruby xxx.rb # 実行 # 結果 # 記述した処理がここに出る以後は省略。
基本文法
Hello, World!
puts 'Hello, World!' # 結果 Hello, World!基本的に、xxx.rbのようなファイルを作りやりたいことを記述、ターミナルで動かす流れ。
データ型について
文字列型(String「""」)と整数型(Integer「 」)がよく使われる。
詳しくは後日、投稿予定。puts 5 + 3 puts "5 + 3" puts "5" + "3" # 結果 8 # 両方integerなので、「5+3」の計算結果 5 + 3 # 計算式をstringで囲っているので、「文字としての"5+3"」が表示される結果 53 # 文字列と文字列を足しているので、「文字としての"5"と"3"」が連続して表示される結果同じ見た目のメソッドでも、中身が異なる場合があるが、めちゃくちゃ便利。
文字列型、整数型の型変換
to_s 27.to_s # 数字→文字へ変換,この場合は文字列型の27になる to_i "27"to_i # 文字→数字へ変換,この場合は整数型の27になるオブジェクトとメソッド
オブジェクトとは
操作対象の状態(データ)と便利な機能(メソッド)を1つにまとめたもの
オブジェクトは「~~のもの」メソッドとは
オブジェクトが持っている固有の機能や処理のこと
メソッドは「~~するもの」つまり・・・?
puts "XXXYYYY".length # 結果 7 # 「文字列オブジェクト」を「lengthメソッドで文字数を数え」、結果を「出力(puts)」他にも、「reverse(文字列を逆にする)」メゾットや、「include?(引数に指定した文字列が含まれているか)」メゾットなどがある。
(メソッドが使えるのかを一覧表示したい場合は、使用可能なメソッド一覧を表示できる「methods」メソッド)
include?の場合は、「true(真)」か「false(偽)」で結果が表示される。変数と定数
変数とは
オブジェクトにつける名札。
名札をつけることで、欲しいデータを呼び出すことが用意になる。
ただし、変数名は小文字で始まるルールがあり、尚且つ数字は使えない。test = "テストコメントが表示されることを確認しよう" puts test # 結果 テストコメントが表示されることを確認しよう変数名 = 入れたいデータ
ポイント : 「=」は数学的な等しいという意味ではなく、「右のオブジェクトを左の変数に代入する」という意味。定数とは
あらかじめ変更しないことが保証された数値やデータにつける名札。
基本的に大文字で始まる。
⚠️値を書き換えることができない点に注意⚠️
(warning(実行不可能なエラーではないが非推奨な使い方)が表示されて書き換えができてしまうが、エラーが出る時点でアウト。)Xx = 3.14 puts Xx # 結果 3.14 Pi = 3.14 puts Pi Pi = 100 puts Pi # 結果 3.14 pi.rb:4: warning: already initialized constant Pi pi.rb:1: warning: previous definition of Pi was here 100データ型
数値
「1」「100」「-100」「0」などの整数や、「3.14」などの小数のこと
メソッドとしては、+(足し算)、-(引き算)、/(割り算)、*(掛け算)、%(割り算の余りの計算)などの四則演算。puts 100 # 結果 100 puts 100 + 5 # 結果 105ポイント : 0除算について
任意の数字 を0で割ってはいけないという数学的ルールがプログラミングにも適用されるぞ。
詳しくは後日投稿予定。
[四則演算注意点] 数字を0で割ってはいけないプログラム計算式文字列
シングルクォートやダブルクォートで囲むことで、文字列として出力。
文字列の中に#{変数}と記述することによって、{}内の変数の値を展開可能。
+を使うと、文字列の連結も可能になり、文字列同士だけでなく、文字列と変数、または変数同士でも、連結できる。puts "Rubyを学習" # 結果 Rubyを学習 name = "テストさん" puts "Hello" + name # 結果 Helloテストさん puts "こんにちは#{name}" # 結果 こんにちはテストさん配列
配列を使うと、複数のデータをまとめて保存できる。
配列の各要素には、どのようなオブジェクトでも代入でき、同じ配列の要素に異なった種類のオブジェクトを代入することも可能。
しかも、データ型は問われず、文字列でも数値でも代入できる。
ただし、先頭から0、1、2というように「インデックス番号」が割り振られ、「0」から開始することに注意。names = ["Ruby", "Java", "Python", "PHP"] puts names[1] # 結果 Javaポイント : たまにeach文で回したデータをarray(からの箱的な感じ)に突っ込んだりする。
ハッシュ
ハッシュは、キーと値をセットで保存できるデータの集合。
配列では各要素にインデックス番号が割り振られるが、ハッシュでは任意の値(キー)を割り振ることができる。tall = {"あい"=>185, "うえ"=>170, "お!"=>150} puts tall["あい"] # 結果 185シンボル
シングルクォートやダブルクォートの代わりにコロンを使用することで、文字列と同様に扱うことが可能。
tall = {:かき=>185, :くけ=>170, :こ!=>150} puts tall[:こ!] # 結果 150条件分岐
if文
「もしAならばBを実行し、AでなければCを実行」
条件に当てはまればtrue、当てはまらなければfalseという真偽判定ができる。apple = 110 if apple >= 100 puts "りんごの値段は100円以上です" #true=>処理される end if apple <= 100 puts "りんごの値段は100円以下です" #false=>処理されない end # 結果 りんごの値段は100円以上です # apple = 110のためtrue処理になった比較演算子
「条件を比較して判定する」時に使用する記号とかのこと。
< # 右辺の方が大きい <= # 右辺の方が大きい、または等しい > # 左辺の方が大きい >= # 左辺の方が大きい、または等しい # 数値だけでなく、文字列の比較(同じ文字列かどうか)でも利用できる == # 右辺と左辺が等しい != # 右辺と左辺が等しくないとき論理演算子
「2つ以上の条件を判定する」時に使用する。
! # 否定 && # どちらの条件も正しければtrue || # どちらかの条件が正しければtrue tall = 180 if tall >= 170 && tall <= 190 puts "身長は170以上190以下です。" end # 結果 身長は170以上190以下です。elsif、else
if(もし〜)文では、elsif(それとも〜)やelse(当てはまらないなら〜)を使うことで、ifの条件に当てはまらなかった場合の処理を設定できる。
else
apple = "A" if apple == "A" #もしappleがAなら puts "それはAのリンゴです" else #ifが当てはまらない場合は puts "そのリンゴはAではないです" end # 結果 A typeのリンゴですelsifとelse
apple = "B" if apple == "A" #もしappleがAなら puts "そのりんごはAです" elsif apple == "B" #それともappleがBなら puts "そのりんごはBです" else #どちらも当てはまらない場合は puts "そのりんごはCです" end # 結果 そのりんごはBですよくFizzBuzz問題としてここあたりが使われると思う。
繰り返し処理
全て100%覚える必要はないが、処理ごとの特徴くらいは覚えよう。
文字列や数字をキーボードから入力する方法
gets
キーボード入力された値を取得するメソッド。
getsを使うと、キー入力待ちの状態になり、文字を入力してEnterキーを押すまで次に進まない。
文字列として返されるぞ。to_i
文字列を整数に変換するメソッド。
例えば、getsメゾットにto_iを使って文字列(String)を整数(Integer)に変換すると計算ができる。puts "キーボードで数字「2」と数字「3」を入力してください" a=gets.to_i b=gets.to_i puts "a+b=#{a+b}" # 結果 a+b=5繰り返し処理や要素を順に取り出す処理
while文
繰り返し処理を行いたいときに使用し、指定した条件式が真(true)の間、繰り返し実行されるのが特徴。
while 条件 do #条件がtrueの間 処理 #処理を繰り返す end # サイコロを振って「6」が出るまで繰り返し実行 dice = 0 # diceに0を代入し、初期値を設定 while dice != 6 do # サイコロの目が6ではない間、diceの初期値は0なので条件を満たす。 # 以降はdiceに代入される数によって結果が異なる dice = rand(1..6) # 1~6の数字がランダムに出力 puts dice end # 結果 ~ 6 # サイコロを振って「6」が出るまで繰り返し実行された最後の数字として6で繰り返し処理が止まるfor文
繰り返し処理を行いたいときに使用し、指定したオブジェクトから順に値を取り出しながら繰り返されるのが特徴。
for 変数 in 範囲、ハッシュ、配列などを指定 do 処理 end # for ~ end内で、1から10まで順番に表示する処理を繰り返す実行 for i in 1..10 do # 1..10は、1~10までの範囲を表す puts i end # 結果 1 2 3 ~ 9 10 # 1から10まで順番に表示されるため10で止まるeachメソッド
オブジェクト内の要素を順に取り出すメソッド。
個人的に一番使う繰り返し処理。
繰り返し処理を行いたいときに使用し、データの先頭から順に繰り返して処理されるmのが特徴。(範囲、ハッシュ、配列などを指定).each do |変数| 実行する処理 end apple: 130 strawberry:180 orange:100 という結果が欲しいと仮定 {"apple"=>130, "strawberry"=>180, "orange"=>100}.each do |fruit, price| # ハッシュの内容を順にキーをfruit、値をpriceに代入して繰り返す puts "#{fruit}は#{price}円です。" # 変数展開 end # 結果 appleは130円です。 strawberryは180円です。 orangeは100円です。地味にポイントなのが、|fruit, price|のように、左から入っていく。
さらに付け加えると、平均点を求める際にも使える。xxx_controller.rbratesum = 0 # 初期値は0 movie_comments.each do |comment| # movie_commentsを繰り返し、1つ1つをcommentとする ratesum += comment.rate # 初期値0に対して、comment.rateという数字を存在するだけ、足し算し続ける end # @averageに平均点を代入 # movie_comments.length(配列の要素数を取得)した時、0なら0,0ではなかったら計算して欲しい処理をしてもらう @average = movie_comments.length == 0 ? 0 : ratesum / movie_comments.length # comment.rateを足し続けた数字に対して、存在する配列の要素数で割ることで、平均点を割り出す。break
繰り返し処理を中断することができる。
whileやfor、eachなどの繰り返し文の中で利用する。i = 0 while i <= 10 do if i >5 break # iが5より大きくなると繰り返しから抜ける end puts i i += 1 end # 結果 0 1 2 3 4 5追加あれば、どんどん更新していきます。
駆け出しとして頑張ります。
- 投稿日:2020-02-27T17:00:42+09:00
Rubyについて(基礎)
最初に
自身で学習してきた内容を書き出していきます。
基本的には自分自身でわかるような内容になりますので、ご容赦ください。
また、誤っている点がありましたら、コメントにてご指摘ください。!! (要確認)マークがあるものは実行前に必ずググるべき内容 !!
index
- 基本文法
- Hello, World!
- データ型について
- オブジェクトとメソッド
- オブジェクトとは
- メソッドとは
- 変数と定数
- 変数とは
- 定数とは
- データ型
- 数値(0除算について)
- 文字列
- 配列
- ハッシュ
- シンボル
- 条件分岐
- if文
- 比較演算子
- 論理演算子
- elsif、else
- 繰り返し処理
- 文字列や数字をキーボードから入力する方法
- gets
- to_i
- 繰り返し処理や要素を順に取り出す処理
- while文
- for文
- each文
- break
〜主な流れ〜
ターミナル$ touch xxx.rb # ターミナルコマンドでからファイルを作成、ここに処理を記述していく $ ruby xxx.rb # 実行 # 結果 # 記述した処理がここに出る以後は省略。
基本文法
Hello, World!
puts 'Hello, World!' # 結果 Hello, World!基本的に、xxx.rbのようなファイルを作りやりたいことを記述、ターミナルで動かす流れ。
データ型について
文字列型(String「""」)と整数型(Integer「 」)がよく使われる。
詳しくは後日、投稿予定。puts 5 + 3 puts "5 + 3" puts "5" + "3" # 結果 8 # 両方integerなので、「5+3」の計算結果 5 + 3 # 計算式をstringで囲っているので、「文字としての"5+3"」が表示される結果 53 # 文字列と文字列を足しているので、「文字としての"5"と"3"」が連続して表示される結果同じ見た目のメソッドでも、中身が異なる場合があるが、めちゃくちゃ便利。
文字列型、整数型の型変換
to_s 27.to_s # 数字→文字へ変換,この場合は文字列型の27になる to_i "27"to_i # 文字→数字へ変換,この場合は整数型の27になるオブジェクトとメソッド
オブジェクトとは
操作対象の状態(データ)と便利な機能(メソッド)を1つにまとめたもの
オブジェクトは「~~のもの」メソッドとは
オブジェクトが持っている固有の機能や処理のこと
メソッドは「~~するもの」つまり・・・?
puts "XXXYYYY".length # 結果 7 # 「文字列オブジェクト」を「lengthメソッドで文字数を数え」、結果を「出力(puts)」他にも、「reverse(文字列を逆にする)」メゾットや、「include?(引数に指定した文字列が含まれているか)」メゾットなどがある。
(メソッドが使えるのかを一覧表示したい場合は、使用可能なメソッド一覧を表示できる「methods」メソッド)
include?の場合は、「true(真)」か「false(偽)」で結果が表示される。変数と定数
変数とは
オブジェクトにつける名札。
名札をつけることで、欲しいデータを呼び出すことが用意になる。
ただし、変数名は小文字で始まるルールがあり、尚且つ数字は使えない。test = "テストコメントが表示されることを確認しよう" puts test # 結果 テストコメントが表示されることを確認しよう変数名 = 入れたいデータ
ポイント : 「=」は数学的な等しいという意味ではなく、「右のオブジェクトを左の変数に代入する」という意味。定数とは
あらかじめ変更しないことが保証された数値やデータにつける名札。
基本的に大文字で始まる。
⚠️値を書き換えることができない点に注意⚠️
(warning(実行不可能なエラーではないが非推奨な使い方)が表示されて書き換えができてしまうが、エラーが出る時点でアウト。)Xx = 3.14 puts Xx # 結果 3.14 Pi = 3.14 puts Pi Pi = 100 puts Pi # 結果 3.14 pi.rb:4: warning: already initialized constant Pi pi.rb:1: warning: previous definition of Pi was here 100データ型
数値
「1」「100」「-100」「0」などの整数や、「3.14」などの小数のこと
メソッドとしては、+(足し算)、-(引き算)、/(割り算)、*(掛け算)、%(割り算の余りの計算)などの四則演算。puts 100 # 結果 100 puts 100 + 5 # 結果 105ポイント : 0除算について
任意の数字 を0で割ってはいけないという数学的ルールがプログラミングにも適用されるぞ。
詳しくは後日投稿予定。
[四則演算注意点] 数字を0で割ってはいけないプログラム計算式文字列
シングルクォートやダブルクォートで囲むことで、文字列として出力。
文字列の中に#{変数}と記述することによって、{}内の変数の値を展開可能。
+を使うと、文字列の連結も可能になり、文字列同士だけでなく、文字列と変数、または変数同士でも、連結できる。puts "Rubyを学習" # 結果 Rubyを学習 name = "テストさん" puts "Hello" + name # 結果 Helloテストさん puts "こんにちは#{name}" # 結果 こんにちはテストさん配列
配列を使うと、複数のデータをまとめて保存できる。
配列の各要素には、どのようなオブジェクトでも代入でき、同じ配列の要素に異なった種類のオブジェクトを代入することも可能。
しかも、データ型は問われず、文字列でも数値でも代入できる。
ただし、先頭から0、1、2というように「インデックス番号」が割り振られ、「0」から開始することに注意。names = ["Ruby", "Java", "Python", "PHP"] puts names[1] # 結果 Javaポイント : たまにeach文で回したデータをarray(からの箱的な感じ)に突っ込んだりする。
ハッシュ
ハッシュは、キーと値をセットで保存できるデータの集合。
配列では各要素にインデックス番号が割り振られるが、ハッシュでは任意の値(キー)を割り振ることができる。tall = {"あい"=>185, "うえ"=>170, "お!"=>150} puts tall["あい"] # 結果 185シンボル
シングルクォートやダブルクォートの代わりにコロンを使用することで、文字列と同様に扱うことが可能。
tall = {:かき=>185, :くけ=>170, :こ!=>150} puts tall[:こ!] # 結果 150条件分岐
if文
「もしAならばBを実行し、AでなければCを実行」
条件に当てはまればtrue、当てはまらなければfalseという真偽判定ができる。apple = 110 if apple >= 100 puts "りんごの値段は100円以上です" #true=>処理される end if apple <= 100 puts "りんごの値段は100円以下です" #false=>処理されない end # 結果 りんごの値段は100円以上です # apple = 110のためtrue処理になった比較演算子
「条件を比較して判定する」時に使用する記号とかのこと。
< # 右辺の方が大きい <= # 右辺の方が大きい、または等しい > # 左辺の方が大きい >= # 左辺の方が大きい、または等しい # 数値だけでなく、文字列の比較(同じ文字列かどうか)でも利用できる == # 右辺と左辺が等しい != # 右辺と左辺が等しくないとき論理演算子
「2つ以上の条件を判定する」時に使用する。
! # 否定 && # どちらの条件も正しければtrue || # どちらかの条件が正しければtrue tall = 180 if tall >= 170 && tall <= 190 puts "身長は170以上190以下です。" end # 結果 身長は170以上190以下です。elsif、else
if(もし〜)文では、elsif(それとも〜)やelse(当てはまらないなら〜)を使うことで、ifの条件に当てはまらなかった場合の処理を設定できる。
else
apple = "A" if apple == "A" #もしappleがAなら puts "それはAのリンゴです" else #ifが当てはまらない場合は puts "そのリンゴはAではないです" end # 結果 A typeのリンゴですelsifとelse
apple = "B" if apple == "A" #もしappleがAなら puts "そのりんごはAです" elsif apple == "B" #それともappleがBなら puts "そのりんごはBです" else #どちらも当てはまらない場合は puts "そのりんごはCです" end # 結果 そのりんごはBですよくFizzBuzz問題としてここあたりが使われると思う。
繰り返し処理
全て100%覚える必要はないが、処理ごとの特徴くらいは覚えよう。
文字列や数字をキーボードから入力する方法
gets
キーボード入力された値を取得するメソッド。
getsを使うと、キー入力待ちの状態になり、文字を入力してEnterキーを押すまで次に進まない。
文字列として返されるぞ。to_i
文字列を整数に変換するメソッド。
例えば、getsメゾットにto_iを使って文字列(String)を整数(Integer)に変換すると計算ができる。puts "キーボードで数字「2」と数字「3」を入力してください" a=gets.to_i b=gets.to_i puts "a+b=#{a+b}" # 結果 a+b=5繰り返し処理や要素を順に取り出す処理
while文
繰り返し処理を行いたいときに使用し、指定した条件式が真(true)の間、繰り返し実行されるのが特徴。
while 条件 do #条件がtrueの間 処理 #処理を繰り返す end # サイコロを振って「6」が出るまで繰り返し実行 dice = 0 # diceに0を代入し、初期値を設定 while dice != 6 do # サイコロの目が6ではない間、diceの初期値は0なので条件を満たす。 # 以降はdiceに代入される数によって結果が異なる dice = rand(1..6) # 1~6の数字がランダムに出力 puts dice end # 結果 ~ 6 # サイコロを振って「6」が出るまで繰り返し実行された最後の数字として6で繰り返し処理が止まるfor文
繰り返し処理を行いたいときに使用し、指定したオブジェクトから順に値を取り出しながら繰り返されるのが特徴。
for 変数 in 範囲、ハッシュ、配列などを指定 do 処理 end # for ~ end内で、1から10まで順番に表示する処理を繰り返す実行 for i in 1..10 do # 1..10は、1~10までの範囲を表す puts i end # 結果 1 2 3 ~ 9 10 # 1から10まで順番に表示されるため10で止まるeachメソッド
オブジェクト内の要素を順に取り出すメソッド。
個人的に一番使う繰り返し処理。
繰り返し処理を行いたいときに使用し、データの先頭から順に繰り返して処理されるmのが特徴。(範囲、ハッシュ、配列などを指定).each do |変数| 実行する処理 end apple: 130 strawberry:180 orange:100 という結果が欲しいと仮定 {"apple"=>130, "strawberry"=>180, "orange"=>100}.each do |fruit, price| # ハッシュの内容を順にキーをfruit、値をpriceに代入して繰り返す puts "#{fruit}は#{price}円です。" # 変数展開 end # 結果 appleは130円です。 strawberryは180円です。 orangeは100円です。地味にポイントなのが、|fruit, price|のように、左から入っていく。
さらに付け加えると、平均点を求める際にも使える。xxx_controller.rbratesum = 0 # 初期値は0 movie_comments.each do |comment| # movie_commentsを繰り返し、1つ1つをcommentとする ratesum += comment.rate # 初期値0に対して、comment.rateという数字を存在するだけ、足し算し続ける end # @averageに平均点を代入 # movie_comments.length(配列の要素数を取得)した時、0なら0,0ではなかったら計算して欲しい処理をしてもらう @average = movie_comments.length == 0 ? 0 : ratesum / movie_comments.length # comment.rateを足し続けた数字に対して、存在する配列の要素数で割ることで、平均点を割り出す。break
繰り返し処理を中断することができる。
whileやfor、eachなどの繰り返し文の中で利用する。i = 0 while i <= 10 do if i >5 break # iが5より大きくなると繰り返しから抜ける end puts i i += 1 end # 結果 0 1 2 3 4 5追加あれば、どんどん更新していきます。
駆け出しとして頑張ります。
- 投稿日:2020-02-27T16:42:41+09:00
rails6 ActionTextの関連付けされない画像データをバックグラウンド削除してみた
はじめに
Rails6の新機能の1つのActionText(リッチテキストコンテンツと編集をかんたんに導入できる)の関連付けされてない画像データをsidekiqでバックグラウンド削除しようという内容です。
削除jobを実行するPostモデル(ポスト)と実行しないArticleモデル(記事)を使って比較していきます。WEBページ
GitHub
https://github.com/hironakazuki/aws_on_rails6/
環境
- Ruby 2.6.3
- Rails 6.0.2
- gem aws-sdk-s3 1.60.2
問題点
こちらがActionTextを実装したPostモデルとArticleモデルのER図になります。
active_storage_blobsにアップロードした画像が保存され、投稿を完了(save)した時にactive_storage_attachmentsにaction_text_rich_textsとの関連情報が保存されます。
しかし、画像をアップロードした時点で active_storage_blobs に新規レコードが作成されてしまい関連付けされなかった場合にも残り続けてしまいます。
以下sidekiqでjobを実行していないArticleモデルでのgifです。
↓一覧画面の上部にactive_storage_attachments, active_storage_blobsを表示しています
画像添付をやめたのにActiveStorage::Blobの数: 2に増えてしまっています。
本題
関連付けされなかったデータを削除するjobを作成します。
app/jobs/delete_unreferenced_blob_job.rbclass DeleteUnreferencedBlobJob < ApplicationJob sidekiq_options queue: :default, retry: 3 require 'aws-sdk-s3' def perform(*args) # 全Blobのidを取得 blob_ids = ActiveStorage::Blob.pluck(:id) # 関連付けされているBlobの取得 _blob_ids = ActiveStorage::Attachment.pluck(:blob_id).uniq # 関連付けされていないBlobの割り出し unreferenced_blob_ids = blob_ids - _blob_ids # 関連付けされていないBlobの画像ファイルを削除 if Rails.env.production? s3 = Aws::S3::Resource.new( region: 'ap-northeast-1', credentials: Aws::Credentials.new( Rails.application.credentials.dig(:aws, :access_key_id), # S3用アクセスキー Rails.application.credentials.dig(:aws, :secret_access_key) # S3用シークレットアクセスキー ) ) bucket = s3.bucket('aws-on-rails6') unreferenced_blob_ids.each do |id| s3_file_key = ActiveStorage::Blob.find(id).key bucket.object(s3_file_key).delete bucket.objects({prefix: "variants/#{s3_file_key}"}).batch_delete! end end # 関連付けされていないBlobの削除 ActiveStorage::Blob.where(id: unreferenced_blob_ids).delete_all end end本番環境のみs3の画像ファイルも削除しています。
これをPostモデルのsave, update, delete時に実行します。
posts_controller.rbdef create if @post.save DeleteUnreferencedBlobJob.perform_later . . def update if @post.update DeleteUnreferencedBlobJob.perform_later . . def destroy DeleteUndreferencedBlobJob.perform_later if @post.destroy . .ActiveStorage::Blobの数: 1となり削除されているのが確認できました!
注意点
この実装だとユーザーAが画像添付ポストを作成時、ユーザーBが別のポストをsaveやupdateした場合でもユーザーAのsave前の関連付けされていない画像データが消えてしまうので、複数ユーザーが利用するサービスではメンテナンス時などに実行するのが望ましいでしょう。
- 投稿日:2020-02-27T16:26:14+09:00
dependent: :destroyをつけていても削除できなかった原因
長時間調べたが解決方法が見つからないという状態が続きました。
私のミスだったので、同じような状態の人に私の経験を伝えれればと思い書きます。内容
紐付けしたオブジェクトを削除するために、
dependent: :destroy
をつけても、削除できない時に気をつけて欲しいことを書きます。問題点
ある特定のUserのみ削除できない
モデルの関係性
User
とCart
が親子関係で、
Cart
とProduct
がCart_products
と 1対多 です。
Users ー Carts → Cart_products ← Products
class User < ApplicationRecord has_one :cart, dependent: :destroy end class Cart < ApplicationRecord belongs_to :user has_many :cart_products, dependent: :destroy has_many :products, through: :cart_products end class Product < ApplicationRecord has_many :cart_products, dependent: :destroy end class CartProduct < ApplicationRecord belongs_to :cart belongs_to :product end行っていたこと
関連付けられたオブジェクトもdestroy削除できるように
has_many
,has_one
にdependent: :destroy
をつけていた。エラー文
Cannot delete or update a parent row: a foreign key constraint fails (`app_name_development`.`cart_products`, CONSTRAINT `fk_rails_a4f3e327f3` FOREIGN KEY (`cart_id`) REFERENCES `carts` (`id`))原因
User has_one Cart
でUser
にはCart
がは1つのみ紐づくようにしていたのですが、
削除できないUser
には2つのCart
が紐つかれていた。そのため
User has_one Cart
をUser has_many Carts
と変更すると削除できた。+----+---------------------+---------------------+---------+ | id | created_at | updated_at | user_id | +----+---------------------+---------------------+---------+ | 3 | 2020-02-21 07:07:57 | 2020-02-21 07:07:57 | 4 | | 12 | 2020-02-21 07:29:37 | 2020-02-21 07:29:37 | 7 | | 13 | 2020-02-21 07:34:26 | 2020-02-21 07:34:26 | 7 | | 16 | 2020-02-22 07:51:47 | 2020-02-22 07:51:47 | 11 | +----+---------------------+---------------------+---------+今後の対処法
モデルを作成する時に、オプションとして
unique: true
を付け、user
の重複をなしにする。XXXXXXX_create_cart.rbclass CreateCarts < ActiveRecord::Migration[5.2] def change create_table :carts do |t| t.references :user, foreign_key: true, unique: true #ここ t.timestamps end end end結論
User has_one Cart
関係の
User
に1つのみのCart
が紐づくようにしていたのですが、
削除できないUser
には2つのCart
が紐つかれていた。そのため、以下のように
User has_one Cart
をUser has_many Carts
と変更すると削除できた。class User < ApplicationRecord has_one :cart, dependent: :destroy end ⬇︎ class User < ApplicationRecord has_many :cart, dependent: :destroy end
- 投稿日:2020-02-27T16:25:54+09:00
RailsでのCookieのSameSite, Secureの対応
概要
2020年2月にChromeのバージョンが80にアップデートされました。
これはCSRFを防ぐためChromeのCookieのSameSite属性をデフォルトでSameSite=Lax
にしようというものです。アップデート前はSameSite=None
と同じ挙動をしていました。つまりアップデート前まで
SameSite=None
でないと正常に動作しないアプリケーションについては明示的にNone
を指定する必要があります。https://developers-jp.googleblog.com/2019/11/cookie-samesitenone-secure.html
から抜粋2月のChrome 80 以降、SameSite 値が宣言されていない Cookie は SameSite=Lax として扱われます。
外部アクセスは、SameSite=None; Secure 設定のある Cookie のみ可能になります。
ただし、これらが安全な接続からアクセスされることが条件です。SameSiteの挙動の説明
SameSite 説明 None クロスドメインでCookieの受け渡しが可能
(ただしSecure=Trueの設定は必須のためhttpの環境だと正常に動作しないはずです)Lax クロスドメインでGETメソッドであればCookieの受け渡しが可能だがPOSTメソッドは不可 Strict クロスドメインでGET、POSTメソッド両方ともCookieの受け渡しは不可 ただし、これはChromeでの挙動になります。
それ以外のブラウザでは違った挙動をするものがあるので注意が必要です。詳しくは下記のリンク先をご覧ください。
https://www.chromium.org/updates/same-site/incompatible-clientsこの中で結構問題があると思われるのは
Versions of Safari and embedded browsers on MacOS 10.14 and all browsers on iOS 12. These versions will erroneously treat cookies marked with SameSite=None as if they were marked SameSite=Strict. This bug has been fixed on newer versions of iOS and MacOS
です。
現時点(2020/2/27)でiOS 12、MacOS 10.14はそれほど古いバージョンではなく使用しているユーザーも多いと思われます。このユーザーに対してはSameSite=None
と設定しているとSameSite=Strict
と同じ挙動をするそうです。
対応するとしたらブラウザによってcookieを書き換える必要がありそうです。Ruby on RailsでSameSite=Noneを設定する対応例
こちらの記事ではgemでの対応が記載されているのでgemで対応したい方はこちらが良いと思います。
(rails_same_site_cookie gemで、RailsアプリにChrome 80向けのSameSite属性を指定する)以降はRuby on Railsでの実装例を記載します。
最初にrack gemのバージョンを確認します。
rackが2.0系だとSameSite=None
の対応が入っておらずエラーになるのでrackのバージョンアップをおこなうかRack::Utils
のモンキーパッチ以下のように作成します。
rackのバージョンアップ時に削除漏れがあるといけないので内容にTODOを記載しておきましょう。# -*- encoding: binary -*- # TODO: rack2.1.0以降だとsamesite=Noneの設定が入っているのでソースファイルごと削除する module Rack # Rack::Utils contains a grab-bag of useful methods for writing web # applications adopted from all kinds of Ruby libraries. module Utils def add_cookie_to_header(header, key, value) case value when Hash domain = "; domain=#{value[:domain]}" if value[:domain] path = "; path=#{value[:path]}" if value[:path] max_age = "; max-age=#{value[:max_age]}" if value[:max_age] # There is an RFC mess in the area of date formatting for Cookies. Not # only are there contradicting RFCs and examples within RFC text, but # there are also numerous conflicting names of fields and partially # cross-applicable specifications. # # These are best described in RFC 2616 3.3.1. This RFC text also # specifies that RFC 822 as updated by RFC 1123 is preferred. That is a # fixed length format with space-date delimited fields. # # See also RFC 1123 section 5.2.14. # # RFC 6265 also specifies "sane-cookie-date" as RFC 1123 date, defined # in RFC 2616 3.3.1. RFC 6265 also gives examples that clearly denote # the space delimited format. These formats are compliant with RFC 2822. # # For reference, all involved RFCs are: # RFC 822 # RFC 1123 # RFC 2109 # RFC 2616 # RFC 2822 # RFC 2965 # RFC 6265 expires = "; expires=" + rfc2822(value[:expires].clone.gmtime) if value[:expires] secure = "; secure" if value[:secure] httponly = "; HttpOnly" if (value.key?(:httponly) ? value[:httponly] : value[:http_only]) same_site = case value[:same_site] when false, nil nil when :none, 'None', :None '; SameSite=None'.freeze when :lax, 'Lax', :Lax '; SameSite=Lax'.freeze when true, :strict, 'Strict', :Strict '; SameSite=Strict'.freeze else raise ArgumentError, "Invalid SameSite value: #{value[:same_site].inspect}" end value = value[:value] end value = [value] unless Array === value cookie = "#{escape(key)}=#{value.map { |v| escape v }.join('&')}#{domain}" \ "#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}" case header when nil, '' cookie when String [header, cookie].join("\n") when Array (header + [cookie]).join("\n") else raise ArgumentError, "Unrecognized cookie header value. Expected String, Array, or nil, got #{header.inspect}" end end module_function :add_cookie_to_header end end修正箇所は↓の部分を追記しただけです。
when :none, 'None', :None '; SameSite=None'.freezerackが2.1系以降であれば対応されているので上記の対応は不要です。
使い方はこんな感じでいけると思います。
cookies[:hogehoge] = { value: "sample value", expires: 1.hour.from_now, same_site: "None", secure: true }環境によって
Secure=True or False
を設定したい場合以下のようなClassを作成します。
# frozen_string_literal: true class SecureCookieWithSameSiteLax def self.secure? Rails.env.staging? || Rails.env.production? end end使い方はこんな感じです。
secure = SecureCookieWithSameSiteLax.secure? cookies[:hogehoge] = { value: "sample value", expires: 1.hour.from_now, same_site: "Lax", secure: secure }production環境、staging環境では
SameSite=Lax Secure=True
development環境ではSameSite=Lax Secure=False
としたい場合の実装方法となります。
SameSite=None
を設定しなくても問題なく動作するアプリケーションであればLax
、Strict
を明示的にセットしてsecureな設定にしておくのが良いと思います。
- 投稿日:2020-02-27T16:15:46+09:00
チーム開発を始める際にチーム全員でgithubを共有する方法(rails)
チーム開発をする際にgithubを全員で共有する方法
某プログラミングスクールにて、チーム開発を始める際に全員でgithubを共有するのに苦戦したので分かりやすく丁寧にまとめたいと思います。
まず用語の説明をします。
ブラウザ上でのgithub = リモート
ブラウザ上でのgithubでのリポジトリ = リモートリポジトリ (リポジトリとは、chat-spaceなどのアプリケーションを指します。)
自分のPC = ローカル
github desktop = ローカルリポジトリまず簡単に流れを掴み、それから1つ1つの詳細を説明していきます。
流れ
1)チームの一人(これからオーナーと呼びます)が自分のローカルでアプリケーションを立ち上げる。
2)オーナーがそのアプリケーションを自分のgithubリモートと繋げる。
3)オーナーがチームメンバーを自分が作ったリモートリポジトリに招待する。
4)メンバーたちがそのリモートリポジトリに入り、その雛形のコードを自分のローカルにコピーする。
5)全員が何かしらの変更点を自分のエディターに書き、pushし、全員がちゃんと1つのリモートリポジトリにつながっているか確認する
6)全員がブランチを切って作業を開始する。それでは早速初めていきます。
1)チームの一人が自分のローカルでアプリケーションを立ち上げる。
チームの一人(基本的に誰でもOK)がローカルで普段何かアプリケーションを立ち上げる時にやっているように
rails newでアプリを立ち上げます。この際、できればバージョンを指定していた方が安全なので今回は5.2.3を指定して作っていく設定で行います。今回作るアプリの名前はsampleと言う名前で作る設定で行います。
$ rails _5.2.3_ new sample -d mysql2)オーナーがそのアプリケーションを自分のgithubリモートと繋げる。
次に、このアプリケーションをgithubに繋げます。
$ cd sample $ git init //現在のsampleをgit下に置きます $ git add . //全てのファイルを追加します $ git status //ちゃんと全てのファイルが入った確認できますすると、このように全てのファイルがgit下に入ったことが確認できます。
次に、このgit下に移動できたファイル達をgithub desktopに追加していきます。
$ git commit -m "initial commit"そして次にgithub desktopを開きます。
すると左上に
と言う表示があるので
Current Repositoryをクリックしてください。(この時点でsampleと表示されていますが気にしなくて大丈夫です)
その後
Add ボタンをクリックし、Add Existing Repository...
をクリックすると
このような表示が出てくるかと思います。
ここで
Choose...をクリックし、自分が作っているsampleファイルを選択し、
Add Repositoryを選択すると、
このような画面が出てくると思います。
ここで左の列の
の欄のSummary(required)のところに、initial commit と記載し、
下の青いボタンのCommit to masterが押せるようになりますので、クリックしてください。すると
このようにローカルに変更点はもうないよ。と言う表示が出ます。
そして、右側にある
で、Pubulish repositoryをクリックしてください。
すると
この表示が出ます。
Nameはそのままで大丈夫です。
Descriptionは空欄で大丈夫です。
その下のチェックボタンはこのコードをプライベートにする。と書いていますが、
今回はチーム開発をするため、このコードを共有しないといけません。よって、チェックボタンは外してください。
そしてPublish Repositoryをクリックしましょう。
そうすると、github ブラウザ(リモート)に、リモートリポジトリが作成されます。
おめでとうございます。
このように自分のアプリケーションが表示できましたでしょうか。
3)オーナーがチームメンバーを自分が作ったリモートリポジトリに招待する。
次に、このリモートリポジトリにメンバーを招待します。
まずこの画面でSetting ボタンをクリックしてください
するとこの画面に飛びますので、次に
Manage accessをクリックしてください。
するとパスワードを要求されますので入力してください。
すると
このような画面があるページに飛びます。
ここでInvite a collaboratorをクリックしましょう。
すると検索画面が出てきますので、メンバー達のgithubでのアカウント名を正しく記入し、追加していきます。追加されたメンバー達は、githubmに登録した時に使用したメールアドレスにメールが届きますので確認してください。
すると、メールには
View Invitationと書かれているのでクリックします。 (※メールはPCで閲覧しましょう)
すると、githubのページに飛びますので、そこで
Accept Invitationをクリックすると、無事、オーナーが作ったリポジトリに参加できます。4)メンバーたちがそのリモートリポジトリに入り、その雛形のコードを自分のローカルにコピーする。
お待たせしました。
ここからはやっとメンバー達も作業開始できます。
メンバー達はそのリポジトリに行ったあと、この
Clone or download
をクリックし、URLをコピーします。そしてgithub desktopに行きます。
そして左上にCurrent Repsitoryをクリックします。そして
Add
をクリックし
Clone Repositoryをクリックします。するとこのような画面が出てきます。
ここではURLを選択してください。
するとこのようなページに変わりますので
上の欄にはgithubブラウザでコピーしたURLをペーストします。
下のLocal Pathは、このコピーしたファイルをどこに入れるかを自分で決めることができます。
これで全員のローカル環境に、オーナーが作ったローカルと同じものがリモートを通じて繋げることができました。
ここからは実際に確認作業をします。
5)全員が1つのリモートリポジトリにつながっているか確認する.
これは簡単です。一人一人がマスターブランチで適当にREAD.Meなどに記載を加え、commit、pushしてください。
すると、一人一人が変えた場所がgithub desktopのhistryに反映されているはずです。6)全員がブランチを切って作業を開始する。
ここからは実際にコードをバリバリ書いていく作業です。
全員ブランチを切り、各々の作業をしてください。これで作業が開始できます。
以上になります。頑張ってください!
間違っている点やご指摘もお待ちしております。
- 投稿日:2020-02-27T14:18:15+09:00
COTOHA でキーワードの抽出 (Ruby)
COTOHA API Portal の使用例です。
key_word.rb#! /usr/bin/ruby # -*- encoding: utf-8 -*- # # key_word.rb # # Feb/27/2020 # # --------------------------------------------------------------------- require 'faraday' require 'json' # load 'get_config.rb' load 'get_token.rb' # --------------------------------------------------------------------- def read_string_proc (file_in) # str_out="" File.open(file_in,"r:UTF-8") do |ff| while line=ff.gets str_out += line end end # return str_out end # --------------------------------------------------------------------- STDERR.puts "*** 開始 ***" # file_in = ARGV[0] puts file_in doc = read_string_proc (file_in) # config = get_config_proc() # access_token = get_token_proc(config) # # headers={ "Content-Type": "application/json", "Authorization": "Bearer " + access_token } # data = { "document": doc, "type": "default" } str_json = JSON.generate(data) # url = config['url_base'] + "v1/keyword" # con = Faraday.new res = con.post do |req| req.url url req.headers = headers req.body = str_json end # puts res.status dict_aa=JSON.parse(res.body) # dict_aa['result'].each {|unit| str_out = unit['form'] + "\t" + unit['score'].to_s puts str_out } # STDERR.puts "*** 終了 ***" # ---------------------------------------------------------------------get_config.rb get_token.rb はこちら
COTOHA API で構文解析 (Ruby)実行結果
$ ./key_word.rb akai_rousoku.txt *** 開始 *** akai_rousoku.txt 200 猿 135.52966 蝋燭 83.9601 花火 78.08584 亀 43.078 火 42.81965 *** 終了 ***
- 投稿日:2020-02-27T14:04:13+09:00
COTOHA で固有名詞の抽出 (Ruby)
COTOHA API Portal の使用例です。
proper_noun.rb#! /usr/bin/ruby # -*- encoding: utf-8 -*- # # proper_noun.rb # # Feb/27/2020 # # --------------------------------------------------------------------- require 'faraday' require 'json' # load 'get_config.rb' load 'get_token.rb' # --------------------------------------------------------------------- STDERR.puts "*** 開始 ***" # config = get_config_proc() # access_token = get_token_proc(config) # sentence = "特急はくたかで富山に向かいます。それから、金沢に行って、兼六園に行きます。" # headers={ "Content-Type": "application/json", "Authorization": "Bearer " + access_token } # data = { "sentence": sentence, "type": "default" } str_json = JSON.generate(data) # url = config['url_base'] + "v1/ne" # con = Faraday.new res = con.post do |req| req.url url req.headers = headers req.body = str_json end # puts res.status dict_aa=JSON.parse(res.body) # dict_aa['result'].each {|unit| puts unit['form'] } # STDERR.puts "*** 終了 ***" # ---------------------------------------------------------------------get_config.rb get_token.rb はこちら
COTOHA API で構文解析 (Ruby)実行結果
$ ./proper_noun.rb *** 開始 *** 200 富山 金沢 兼六園 *** 終了 ***
- 投稿日:2020-02-27T13:47:00+09:00
COTOHA API で構文解析 (Ruby)
COTOHA API Portal の使用例です。
parsing.rb#! /usr/bin/ruby # -*- encoding: utf-8 -*- # # parsing.rb # # Feb/27/2020 # # --------------------------------------------------------------------- require 'faraday' require 'json' # load 'get_config.rb' load 'get_token.rb' # --------------------------------------------------------------------- STDERR.puts "*** 開始 ***" # config = get_config_proc() # access_token = get_token_proc(config) # sentence = "特急はくたか" # headers={ "Content-Type": "application/json", "Authorization": "Bearer " + access_token } # data = { "sentence": sentence, "type": "default" } str_json = JSON.generate(data) # url = config['url_base'] + "v1/parse" # con = Faraday.new res = con.post do |req| req.url url req.headers = headers req.body = str_json end # puts res.status dict_aa=JSON.parse(res.body) # dict_aa['result'].each {|unit| unit['tokens'].each {|token| str_out = token['form'] + "\t" + token['pos'] puts str_out } } # STDERR.puts "*** 終了 ***" # ---------------------------------------------------------------------get_config.rb# -*- encoding: utf-8 -*- # # get_config.rb # # Feb/27/2020 # # --------------------------------------------------------------------- require 'dotenv' # # --------------------------------------------------------------------- def get_config_proc() Dotenv.load config = {} config["grantType"] = "client_credentials" config["clientId"] = ENV["CLIENT_ID"] config["clientSecret"] = ENV["CLIENT_SECRET"] config["url_publish"] = ENV['ACCESS_TOKEN_PUBLISH_URL'] config["url_base"] = ENV['DEVELOPER_API_BASE_URL'] # return config end # ---------------------------------------------------------------------get_token.rb# -*- encoding: utf-8 -*- # # get_token.rb # # Feb/27/2020 # # --------------------------------------------------------------------- require 'faraday' require 'json' # # --------------------------------------------------------------------- def get_token_proc(config) str_json = JSON.generate(config) # headers={ "Content-Type": "application/json" } # con = Faraday.new res = con.post do |req| req.url config['url_publish'] req.headers['Content-Type'] = 'application/json' req.body = str_json end # dict_aa=JSON.parse(res.body) access_token = dict_aa['access_token'] # return access_token end # ---------------------------------------------------------------------実行結果
$ ./parsing.rb *** 開始 *** 200 特急 名詞 は 動詞語幹 く 動詞接尾辞 たか 名詞 *** 終了 ***
- 投稿日:2020-02-27T13:34:23+09:00
Before Rails Tutorial4章 ログイン機能
本投稿は講義資料であり、Rubyの基礎は理解しているが、rails tutorialで躓く読者を対象としています。
1章:環境構築
2章:Scaffold を用いた高速なアプリケーション構築 及び MVCの理解
3章:Scaffold を用いない開発方法 及び 応用
4章:ログイン機能3章で作成した、蔵書管理アプリ bukukore にログイン機能を付与していきます。
ログイン機能は、 Devise という GEM を用いて構築していきます。Devise
bukukore ディレクトリ内の、Gemfile を立ち上げて下記のコードを追記してください。
Gemfile(追記)gem 'devise'Gemfile に追記したら、 bundle install していきましょう。
terminal$ bundle install --path vendor/bundledevise のインストールが完了したら、deviseを適応させていきます。
terminal$ rails g devise:install (省略) =============================================================================== Some setup you must do manually if you haven't yet: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } In production, :host should be set to the actual host of your application. 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> 4. You can copy Devise views (for customization) to your app by running: rails g devise:views ===============================================================================deviseをインストールすると、上記のようなメッセージが表示されます。
1つ目のメッセージに従い、デフォルトのURL を設定します。今回は指示通りで良いので、
config/environments/development.rb の一番下に下記のコードを追加します。config/environments/development.rb(追加)(省略) config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }2つ目のメッセージは、3つ目のメッセージは、のちほど追加します。
4つ目のメッセージでViewを作成するのですが、そのまえにModelをつくっておきます。
devise で使いたいのは User登録機能なので 下記のコマンドを実行します。config/initializers/devise.rb(235行目あたりの該当箇所を書換)config.scoped_views = trueconfig.scoped_views を false から true に書き換えてください。
(devise をどのフォルダにインストールするかの設定です。)
使い方はこちらterminal$ rails g devise User create db/migrate/20200216064430_devise_create_users.rb create app/models/user.rb route devise_for :usersこれで user.rb の他に、devise に関するマイグレーションファイルと、ルーティングが追加されています。
ルーティングは、 rails routes を実行することで確認できます。
マイグレーションファイルは、 db/migrate の中にあります。
devise では機能毎に ON / OFF 設定可能です。
モジュール名 各機能の説明 database_authenticatable データベースに保存されたパスワードが正しいかどうかの検証とを行ってくれます。またパスワードの暗号化も同時に行ってくれます。 registerable ユーザー自身がアカウント登録、編集、削除することを許可します。 recoverable パスワードをリセットできるようにし、メールで通知します。 rememberable 30日間ログインしたままにするというような永続ログインを可能にします。ログイン画面の下のチェックボックスにチェックすることで永続ログインを有効化できます。 trackable ユーザーのサインイン回数や、サインイン時間、IPアドレスなどを記録できるようにします。 validatable Emailやパスワードのバリデーションを可能にします。独自に定義したバリデーションを追加することもできます。 confirmable メールに記載されているURLをクリックして本登録を完了する、といったよくある登録方式を可能にします。また、サインイン中にアカウントが認証済みかどうかを検証します。 lockable 一定回数ログインを失敗するとアカウントをロックします。ロック解除にはメールによる解除か、一定時間経つと解除するといった方法があります。 timeoutable 一定時間活動していないアカウントのログインを破棄します。 omniauthable TwitterやFacebookなどのSNS認証を追加したい場合に使用します。 db/migrate/2020(省略)_devise_create_users.rb# frozen_string_literal: true class DeviseCreateUsers < ActiveRecord::Migration[5.2] def change create_table :users do |t| ## Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" ## Recoverable t.string :reset_password_token t.datetime :reset_password_sent_at ## Rememberable t.datetime :remember_created_at ## Trackable t.integer :sign_in_count, default: 0, null: false t.datetime :current_sign_in_at t.datetime :last_sign_in_at t.string :current_sign_in_ip t.string :last_sign_in_ip ## Confirmable t.string :confirmation_token t.datetime :confirmed_at t.datetime :confirmation_sent_at t.string :unconfirmed_email # Only if using reconfirmable ## Lockable t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts t.string :unlock_token # Only if unlock strategy is :email or :both t.datetime :locked_at t.timestamps null: false end add_index :users, :email, unique: true add_index :users, :reset_password_token, unique: true add_index :users, :confirmation_token, unique: true add_index :users, :unlock_token, unique: true end end上記のようにすべての機能をコメントアウトしておきます。(講義終了後に、興味ある学生が拡張して遊べるための配慮)
今回はメール認証を行いたいので Confirmable を使用します。
user.rb もすべての機能が使用できるように変更しておきます。app/models/user.rbclass User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable, :timeoutable endマイグレーションファイル を変更したので適応させましょう。
マイグレーションファイルの実行は下記のコマンドでしたね。terminal$ rails db:migrate == 20200220202020 DeviseCreateUsers: migrating ================================ -- create_table(:users) -> 0.0021s -- add_index(:users, :email, {:unique=>true}) -> 0.0008s -- add_index(:users, :reset_password_token, {:unique=>true}) -> 0.0010s == 20200220202020 DeviseCreateUsers: migrated (0.0041s) =======================rails db:migrate した後は、 rails sever を再起動しておいてください。
マイグレーションを実行することでデータベースの中に、usersテーブルが作成されます。
4つ目のメッセージに書いてあるように、Devise が使用するView(アカウント作成関連) も作っていきます。terminal$ rails g devise:views user app/views/devise/shared/_links.html.erb (リンク用パーシャル) app/views/devise/confirmations/new.html.erb (認証メールの再送信画面) app/views/devise/passwords/edit.html.erb (パスワード変更画面) app/views/devise/passwords/new.html.erb (パスワードを忘れた際、メールを送る画面) app/views/devise/registrations/edit.html.erb (ユーザー情報変更画面) app/views/devise/registrations/new.html.erb (ユーザー登録画面) app/views/devise/sessions/new.html.erb (ログイン画面) app/views/devise/unlocks/new.html.erb (ロック解除メール再送信画面) app/views/devise/mailer/confirmation_instructions.html.erb (メール用アカウント認証文) app/views/devise/mailer/password_change.html.erb (メール用パスワード変更完了文) app/views/devise/mailer/reset_password_instructions.html.erb (メール用パスワードリセット文) app/views/devise/mailer/unlock_instructions.html.erb (メール用ロック解除文)上記コマンドを実行することで、 Devise の機能により、ユーザー作成関連の View が自動生成されます。
この時点でアカウント作成画面などにアクセスは可能ですが、メール認証機能は実装していないのでアカウントは作れません。
http://localhost:3000/users/sign_upいまのうちに、新規登録、ログインへのリンクを用意しておきましょう。
app/views/layouts/application.html.erb<!DOCTYPE html> <html> <head> <title>Bukukore</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <% if user_signed_in? %> <%= link_to 'ユーザー編集', edit_user_registration_path %> | <%= link_to "ログアウト", destroy_user_session_path, method: :delete %> <% else %> <%= link_to "新規登録", new_user_registration_path %> | <%= link_to "ログイン", new_user_session_path %> <% end %> <%= yield %> </body> </html>メール認証
Google 二段階認証
config/initializers/devise.rb の21行目あたりにある
config.mailer_sender を自分の gmail アドレスに変更します。config/initializers/devise.rbconfig.mailer_sender = '[自分のアドレスに置き換えます]@gmail.com'最後に開発環境の設定ファイルの最後に以下を追加します。
config/environments/development.rb(追記)(省略) ActionMailer::Base.smtp_settings = { address: 'smtp.gmail.com', port: 587, user_name: '[自分のアドレスに置き換えます]@gmail.com', password: '先程取得した二段階認証のアプリパスワード', authentication: 'plain', enable_starttls_auto: true }以上でメール認証処理は完了です。
「こんなの自力でわかるわけない!自力開発なんてできない」
と思うかもしれませんが、GEMの使い方はリファレンスにすべて書いてあるのでご安心ください。
今後、リファレンスを読む癖、調べる癖をつけていきましょう。
https://github.com/heartcombo/devise#getting-started
https://qiita.com/gakkie/items/6ef70c0788c3cbff81ee実際にユーザー登録を行い、メールが届くことを確認できます。
http://localhost:3000/users/sign_up
届いたメールに記載されている URL をクリックすることで、認証完了です。
rails server のログにも URL が書いてあるので、そちらをコピペしても認証可能です。どういう仕組みで、メールの認証やログイン・ログアウトが行われているのか詳しくは
https://railstutorial.jp/
で学べます。ユーザーの一覧と詳細表示ページ
Userの一覧をみるページ、詳細情報をみるページを作成していきましょう。
Model はすでに作っているので、 Controller と View を作成します。terminal$ rails g controller Users index show2つ目のメッセージにあったルート設定もここでしておきましょう。
ユーザーの一覧ページ(users#index)をTOPページにしたいので、下記コードを追加します。config/routes.rb(追加)(省略) root to: 'users#index'これで、root(最初のページ)にアクセスがあった時に、usersControllerのindexアクションを呼び出します。
http://localhost:3000/課題 MVCの復習
1, User Model を使い、users テーブルから全データを取り出し
2, user index ページに表示してみましょう。
3, user show ページにユーザー情報を表示してください http://localhost:3000/users/show/1ヒント: Model は Controller に記述します。
一度何も見ずにやってみてみると理解度チェックになります。
曖昧な場合は、前章の内容を確認してください。
1の解答例はここをクリックすると表示されます
app/controllers/users_controller.rbclass UsersController < ApplicationController def index @users = User.all end def show end end
2の解答例はここをクリックすると表示されます
app/views/users/index.html.erb<h1>ユーザーの一覧</h1> <% @users.each do |user| %> <p><%= user[:id] %></p> <p><%= user[:email] %></p> <% end %>
3の解答例はここをクリックすると表示されます
app/controllers/users_controller.rbclass UsersController < ApplicationController def index @users = User.all end def show @user = User.find(params[:id]) end endconfig/routes.rb(書き換え)# get 'users/show'(コメントアウト) get 'users/show/:id', to: 'users#show'app/views/users/show.html.erb<h1>ユーザーの情報</h1> <p><%= @user.id %></p> <p><%= @user.email %></p>新しいカラムの追加方法
現在 id,email と2つのカラムがあります。これだけでは誰か分かりづらいので
名前を登録するために、 name カラムを追加してみましょう。terminal$ rails g migration AddNameToUsers name:string上記のコマンドで、usersテーブルに name カラムを追加するためのマイグレーションファイルが自動生成されます。
db/migrate/2020(省略)_add_name_to_users.rb(自動生成)class AddNameToUsers < ActiveRecord::Migration[5.2] def change add_column :users, :name, :string end endマイグレーションファイルを実行します。
terminal$ rails db:migrate == 20200222020202 AddNameToUsers: migrating =================================== -- add_column(:users, :name, :string) -> 0.0017s == 20200222020202 AddNameToUsers: migrated (0.0018s) ==========================users テーブルに、nameカラムを追加することができました。
ストロングパラメータに name を許可する
しかし、追加しただけでは保存できないようになっています。
これは rails が自動的行っているセキュリティ対策の為です
ストロングパラメータについて保存できるようにするためには、ストロングパラメータへの追加が必要です。
app/controllers/application_controller.rbclass ApplicationController < ActionController::Base before_action :permitted_parameters, if: :devise_controller? private def permitted_parameters devise_parameter_sanitizer.permit :sign_up, keys: [:name] devise_parameter_sanitizer.permit :account_update, keys: [:name] end endpermitted_parameters アクションの中を見てください。
devise_parameter_sanitizer.permit 【許可する場所】, keys: 【許可するカラム名】
というようにして、許可を与えます。before_action は、このファイルが呼び出されたときに最初に実行されるものです。
これで新たに、名前を保存できるようになりました。
課題
1, 登録画面に、名前を登録するためのフォームを追加してください。
http://localhost:3000/users/sign_up
2, 実際に名前を登録し、 show ページで名前を表示してください。
http://localhost:3000/users/show/1 (必要があればidは登録した番号に変更してください)BookテーブルとUserテーブルの関連付け
続いて、2章で学習したテーブルの関連付けの復習をやっていきます。
詳細ページに、そのユーザーが登録した、本の情報を表示していきましょう。http://localhost:3000/users/show/1 ←ユーザーの詳細ページ
http://localhost:3000/books/new ←本の情報登録ページ
http://localhost:3000/books/show/1 ←登録内容を確認課題
ユーザーの詳細ページに、登録した本の情報が表示されるようにしてください。
解答例はここをクリックすると表示されます
app/models/user.rb(1行追加)class User < ApplicationRecord has_many :books # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable, :timeoutable endapp/models/book.rbclass Book < ApplicationRecord belongs_to :user endapp/controllers/users_controller.rbclass UsersController < ApplicationController def index @users = User.all end def show @user = User.find(params[:id]) @books = @user.books end endapp/views/users/show.html.erb<p><%= @user.id %></p> <p><%= @user.email %></p> <p><%= @user.name %></p> <% @books.each do |book| %> <p>本のタイトル: <%= book.title %></p> <p>著者: <%= book.author %></p> <% end %>
- 投稿日:2020-02-27T10:45:33+09:00
COTOHA アクセストークンの取得 (Ruby)
COTOHA API Portal の使用例です。
access_token.rb#! /usr/bin/ruby # -*- encoding: utf-8 -*- # # access_token.rb # # Feb/27/2020 # # --------------------------------------------------------------------- require 'faraday' require 'json' require 'dotenv' # # --------------------------------------------------------------------- STDERR.puts "*** 開始 ***" # Dotenv.load # data = { "grantType": "client_credentials", "clientId": ENV["CLIENT_ID"], "clientSecret": ENV["CLIENT_SECRET"] } # str_json = JSON.generate(data) # url = ENV['ACCESS_TOKEN_PUBLISH_URL'] headers={ "Content-Type": "application/json" } # con = Faraday.new res = con.post do |req| req.url url req.headers['Content-Type'] = 'application/json' req.body = str_json end puts res.status puts res.body puts "-----------" dict_aa=JSON.parse(res.body) puts dict_aa['access_token'] # STDERR.puts "*** 終了 ***" # ---------------------------------------------------------------------実行結果
$ ./access_token.rb *** 開始 *** 201 { "access_token": "oleleUiGwUIVjbvH*******", "token_type": "bearer", "expires_in": "86399" , "scope": "" , "issued_at": "1582767850104" } ----------- oleleUiGwUIVjbvHLonJD2OA3I8q *** 終了 ***使ったバージョン
$ ruby --version ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
- 投稿日:2020-02-27T10:30:17+09:00
Rubyでvalidationするdry-validationの基本のキ
はじめに
RubyでAPIを作成する際にvalidationをいい感じにしてくれるgemを探したところ、dry-validationに行き着きました。
ただし、公式のリファレンスではよく分からないとか調べても古いバージョンの話だったとかがあったので、メモとして執筆時点で分かったことをメモとして残します。環境
dry-validation 1.4
https://dry-rb.org/gems/dry-validation/1.4/アプリケーションで使用するための基底クラスの作成
デフォルトだとメッセージが英語なので、日本語にするためにはconfigの設定が必要です。
なので基底クラスを使ってまとめて設定します。class ApplicationContract < Dry::Validation::Contract config.messages.default_locale = :ja config.messages.backend = :yaml config.messages.load_paths << 'config/contract/error.yaml' endメッセージは
config.messages.load_paths
に設定した箇所に置いてください。
中身は以下のような感じです。
詳しいconfigの意味とかは公式のリファレンスで十分なので、そちらをご覧ください。https://dry-rb.org/gems/dry-validation/1.4/messages/#using-localized-messages-backend
ja: dry_validation: errors: filled?: '必須です' int?: '数字じゃありません' date?: '日付じゃありません' string?: '文字列じゃありません'一番上にロケールを書く以外はフォーマットに沿って書いてあげる必要があります。
validation class
基本的な設定ができたので、実際にvalidationするためのクラスを例に使い方を書いていきます。
まずはサンプルをご覧ください。class FormContract < ApplicationContract params do required(:start_date).filled(:date) required(:end_date).filled(:date) optional(:id).filled(:integer) required(:name).maybe(:string) end rule(:end_date, :start_date) do key(:start_date).failure('開始日は終了日よりも後ろにしてください') if values[:end_date] < values[:start_date] end単項目チェック
単項目はprams部分に記述します。
params do required(:start_date).value(:date) required(:end_date).filled(:date) optional(:id).filled(:integer) required(:name).maybe(:string) endパラメータチェック
パラメータが必須であるか任意であるかを記述します。
必須である場合はrequired
、任意である場合はoptional
で宣言します。値チェック
値チェックはいくつか種類があります。
ここでは簡単なチェックのみで、パラメータのチェックを正規表現使ってやりたいといったチェックは別で行う必要があります。(後述)filled
値の存在チェック + 型変換しての型チェックです。
値が存在しない場合は存在しないエラーとなり、値があり型変換後の型が違ったら型エラーとなります# emptyエラー {locale}.dry_validation.errors.filled? # 型エラー {locale}.dry_validation.errors.int? {locale}.dry_validation.errors.str? {locale}.dry_validation.errors.date?ちなみにfilledの引数に型を入れてるから型チェックしてくれるだけで、引数がなければ型チェックをスキップすることも可能です。
# 型チェックあり required(:end_date).filled(:date) # 型チェックなし required(:end_date).filled()value
厳密な型チェックです。
こちらはfilledと違って厳密な型チェックが行われます。
厳密な型チェックなので、formのパラメータをそのまま与えてvalidationするという用途には向いてません。
(formから渡ってきた値はstring扱いとなるため)型チェックのみのため、型が違ったエラーしか返ってきません。
{locale}.dry_validation.errors.int? {locale}.dry_validation.errors.str? {locale}.dry_validation.errors.date?maybe
こちらも厳密な型チェックですが、値がnilの場合はチェックされません。
ただし、stringのblankはチェック対象となるため、注意が必要となります。{locale}.dry_validation.errors.int? {locale}.dry_validation.errors.str? {locale}.dry_validation.errors.date?チェックをしたくない場合
チェックを行いたくない場合は何も書かなければOKです。
パラメータとしては必須だけど、2つの値のどちらかが入っていれば良いといったケースですね。相関チェックや複雑なチェック
そういうのは
rule
に記載していきます。
エラーが発生した場合は、どのkeyにどんなエラーがあったかを設定していく形です。
rule
に設定するキーも1〜n個引数が取れるので、全部こっちでvalidationさせることも可能です。rule(:end_date, :start_date) do key(:start_date).failure('開始日は終了日よりも後ろにしてください') if values[:end_date] < values[:start_date] end呼び出し方
呼び出しは
new
してcall
すれば良いです。
下のサンプルはrailsのparamsをそのまま引数として使う場合です。
call
にはHash
を引数としてあげればあとはやってくれます。FormContract.new.call(params.permit!.to_h)
- 投稿日:2020-02-27T10:28:57+09:00
バリデーションエラーの表示とredirect_toとrenderの違い
flashメッセージは表示されるけど、バリデーションエラーが表示されなくて困っているのでteratailに質問を投げてみたところ、エラーメッセージを表示させるにはrenderを使うというご指摘をいただいたので、備忘録として記事に致します。
before
questions.controller.rbclass QuestionsController < ApplicationController def new @questions = Question.all @question = Question.new end def create @question = Question.new(question_params) begin @question.save! flash[:notice] = '投稿に成功しました' redirect_to new_question_path rescue flash.now[:alert] = '投稿に失敗しました' redirect_to new_question_path end end private def question_params params.require(:question).permit(:title, :detail) endafter
questions.controller.rbdef new @questions = Question.all @question = Question.new end def create @questions = Question.all @question = Question.new(question_params) begin @question.save! flash[:notice] = '投稿に成功しました' redirect_to new_question_path rescue flash.now[:alert] = '投稿に失敗しました' render :new end end private def question_params params.require(:question).permit(:title, :detail) endbeforeでは例外処理になった場合に
redirect_to new_question_pathによって、newアクションまで遡ってしまっています。遡ってしまった結果、モデルのインスタンスが失われてしまうので、save!で格納されたエラーメッセージも無かったことになるみたいです。 更新ボタンを押した処理に近いです。
afterではリダイレクトしない場合もnewと同じ情報が必要なので、beginの前はnewと同じコードを入れています。
rescue flash.now[:alert] = '投稿に失敗しました' render :newここをrender :newとすることで、リダイレクトせずにnewのviewファイルを表示しています。こうすることでモデルのインスタンスも失われないので、エラーメッセージも無くなりません。
- 投稿日:2020-02-27T09:09:46+09:00
【Rails】Slackへの通知をActionMailerのようなerbテンプレートを使う形で実装する
以下のGemを利用してSlackで通知を実装する際ActionMailerのようにerbを使ってviewを分けられないかと検討した。
https://github.com/stevenosloan/slack-notifier
app/views/admin_slack_notifier/receive_message_from_user.text.erb【<%= @subject %>】 ■□–––––––––––––––––––––□■ ▼送信者情報 <%= @message.user.name %> ▼送信内容 <%= @message.content %> ■□–––––––––––––––––––––□■app/libs/slack_notifier.rbmodule SlackNotifier CONFIG = YAML.load_file(Rails.root.join('config', 'slack.yml'))[Rails.env] class << self def post(to, text, options = {}) options = options.symbolize_keys dry_run = options.key?(:dry_run) ? options[:dry_run] : CONFIG['dry_run'] post_options = format_options(to, text, options) notifier = Slack::Notifier.new CONFIG['webhook_url'] notifier.post post_options unless dry_run end private # rubocop:disable Metrics/AbcSize def format_options(to, text, options) post_options = { 'channel' => (options[:channel].presence || CONFIG[to.to_s]['channel']), 'icon_emoji' => (options[:icon_emoji].presence || CONFIG[to.to_s]['icon_emoji']), 'username' => (options[:username].presence || CONFIG[to.to_s]['username']), 'text' => text } post_options[:title] = options[:title] if options.key?(:title) post_options end # rubocop:enable Metrics/AbcSize end endapp/libs/admin_slack_notifier.rbmodule AdminSlackNotifier class << self def receive_message_from_user(message) @message = message @subject = 'ユーザーより新しいメッセージが送信されました' post_with_template 'admin_channel', __method__, binding end private def post_with_template(to, view_name, binding) erb = Rails.root.join('app', 'views', name.underscore, "#{view_name}.text.erb").read text = ERB.new(erb).result(binding) SlackNotifier.post to, text end end endconfig/slack.ymldevelopment: &default dry_run: true username: &username Admin webhook_url: WEBHOOK_URL admin_channel: channel: admin_channel icon_emoji: ":crystal_ball:" username: *username staging: <<: *default dry_run: false production: <<: *default dry_run: false test: <<: *default以下のような形でAction名と同様のviewを習得してSlackの通知を送信することができる。
sample.rbAdminSlackNotifier.receive_message_from_user(message)
- 投稿日:2020-02-27T07:16:18+09:00
Ruby on Rails チュートリアル学習記録 第3章
第2章については特に書く内容がなかったため学習記録は付けませんでした
3.1
heroku create
を実行するとbash: heroku: command not found
というエラーメッセージ。
https://qiita.com/RyuGotoo/items/7d44f7aa51f7c90ad0b7
↑こちらの記事参考に
nvm install node
npm install -g heroku-cli
を実行後、あらためてheroku create
を実行すると上手くいった。3.2
特になし
3.3
特になし
3.4
特になし
3.5
特になし
3.6
特になし
- 投稿日:2020-02-27T01:15:46+09:00
正規表現について 電話番号で解説
正規表現とは
正規表現とは、メタ文字と文字列を組み合わせてあらゆる文字列パターンを表現することです。
この記事では携帯電話番号を例にしてどのように書けばいいのか解説します。例
早速例を出します。以下は携帯電話番号の妥当性について検証しています。
・携帯電話の番号である条件
1. 先頭が070、080、090のいずれかであること
2. 4桁目が ハイフン であること
3. 5桁目から8桁目が数字であること
4. 9桁目が ハイフン であること
5. 10桁目から13桁目が数字であること5つの条件を満たす文字列パターンを書くと以下のようになります。
/^0[789]0-\d{4}-\d[4]\
解説
それでは1つずつ解説していきます。
・先頭の / と末尾の /
この中に表現したい文字列パターンを入力します。・^0
先頭がの文字が0であること
・[789]0
2文字目が7,8,9のいずれかであること
これで条件1の「先頭が070、080、090のいずれかであること」が表現できました。・ - (ハイフン)
4桁目がハイフンであること
これで条件2の「4桁目がハイフンであること」を満たすことができます。・ \d{4}
4桁の数字であること
この記述により、条件3の「5桁目から8桁目が数字であること」となります。9桁目から13桁目については解説が被ることになるた割愛します。
まとめ
以上で携帯電話番号の妥当性を確認できます。
画面から入力された値に対してこのチェックを入れることで、テーブルに予期せぬ値が格納されることを防ぐことが出来るわけですね!