- 投稿日:2019-08-11T23:35:42+09:00
【Ruby】Ruby初心者がよく使うと思う配列のメソッド
はじめに
いま、Rubyプログラマに勧めてもらったチェリー本を使って学習を進めています。
Rubyの勉強を開始してから1週間くらいしか経っていない初心者が、覚えておきたい配列のメソッドを調べました。
個人的な振り返りメモも兼ねています。
ぜひ間違えていたら、コメントや編集リクエストで教えていただけると嬉しいです。参考文献
プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで Software Design plus | 伊藤 淳一 | コンピュータ・IT | Kindleストア | Amazon
start_with? (String) - Rubyリファレンス
class Array (Ruby 2.6.0)
Rubyのeachでindexを取得する:each_with_index | UX MILK
【Ruby】each_with_indexは知ってたけどeach.with_indexは知らなかった… - 訳も知らないで
class Enumerator (Ruby 2.6.0)動作確認環境
- Windows 10
- ruby 2.5.5p157
eachメソッドでループする
今回勉強に使わせてもらっているチェリー本によると、for文ではなく、eachメソッドを使用することが多いとのことです。
arr = ['Spring', 'Summer', 'Autumn', 'Winter'] arr.each do |n| puts n end実行結果
Spring Summer Autumn Wintereachメソッドでindex(添字)を取得したい
Enumerableモジュールのメソッドの一つである
each_with_index
を使用します。arr = ['Spring', 'Summer', 'Autumn', 'Winter'] arr.each_with_index do |n, index| puts "#{index}, #{n}" end実行結果
0, Spring 1, Summer 2, Autumn 3, Winterindex(添字)の始まりの値を設定したい
Enumeratorクラスのメソッドの一つである
with_index
メソッドを使用します。
サンプルは、2からindexを開始するという意味です。arr = ['Spring', 'Summer', 'Autumn', 'Winter'] arr.each.with_index(2) do |n, index| puts "#{index}, #{n}" end実行結果
2, Spring 3, Summer 4, Autumn 5, Winter配列同士を比較したい
サンプルコード
arr = ['Spring', 'Summer', 'Autumn', 'Winter'] arr_compare = ['Spring', 'Summer', 'Autumn'] puts arr.eql?arr_compare # false arr_compare.push('Winter') # 要素を追加してから比較 puts arr.eql?arr_compare # true配列が空かどうか確認
arr = ['Spring', 'Summer', 'Autumn', 'Winter'] arr_empty = [] puts arr_empty.empty? # true puts arr.empty? # false指定した範囲の配列要素を取得する
サンプルコード
arr = ['Spring', 'Summer', 'Autumn', 'Winter'] p arr[1...3] # 3を含まない p arr[1..3] # 3を含む実行結果
["Summer", "Autumn"] ["Summer", "Autumn", "Winter"]条件に一致する要素を取り出して新しい配列を作る
サンプルコード
arr = ['Spring', 'Summer', 'Autumn', 'Winter'] # 文字列の先頭がSの要素を抽出 p arr.select { |n| n.start_with?("S") }実行結果
["Spring", "Summer"]条件と不一致の要素を取り出して新しい配列を作る
サンプルコード
arr = ['Spring', 'Summer', 'Autumn', 'Winter'] # 文字列の最後尾がrの要素を抽出 p arr.reject { |n| n.end_with?("r") }実行結果
["Spring", "Autumn"]全要素に対してブロック内で評価した結果で新しい配列を作る
p arr.map { |n| n.start_with?("S") }実行結果
[true, true, false, false]条件に一致する最初の要素を返す
サンプルコード
# uを含む文字列を検索 p arr.find { |n| n.index("u")}実行結果
"Summer"おわりに(おまけ)
実はチェリー本を購入する前に、
この記事の下書きを作っていたのですが、
だいたい(もしかしたら全部)チェリー本に書いていました。まとめた意味がなくなってしまい、すごく悲しくなりました。
- 投稿日:2019-08-11T21:56:22+09:00
Ruby プログラミングノート 1~3章
はじめに
Ruby on Rails チュートリアルの実施と並行してRubyの学習を行い
自身の記憶定着のためプログラミングノートとして書き起こす。RubyとRuby on Railsとの違い
Ruby Rails プログラミング言語
(Python等と同様)Rubyを用いたWebアプリケーションの
開発用のフレームワーク文字列、数値、true/false、nilのすべてがオブジェクト
(オブジェクトに対してメソッドが呼べる)MVCモデルの提供
M=Model(モデル) データの処理
V=View(ビュー) 見た目の処理
C=Controller(コントローラ) ModelとViewを制御するRubyの基本
Rubyファイルの実行
$ ruby ファイル名(~.rb) Ex. $ ruby sample.rbライブラリの種類
- インストール不要
- 標準ライブラリ(date,csvなど https://docs.ruby-lang.org/ja/latest/library/index.html)
- 標準ライブラリ(Array,Hashなど https://docs.ruby-lang.org/ja/latest/library/_builtin.html)
- インストール必要
- gem
ライブラリのインポート
- インストール不要
require "ライブラリ名" require "ファイルパス" ※ファイル名指定時に拡張子の「.rb」は不要 Ex. require "date" (Dateクラス) require "./home/start" (home/start.rbファイル)
- インストール必要 gem(外部ライブラリ)
変数宣言
変数名 = 値(型の宣言が不要)
※変数名だけ定義はできないコンソールへの入出力(putsとgets)
- コンソールへの表示
puts 文字列 puts 変数
- コンソールへの入力
変数名 = gets (改行付き) 変数名 = gets.chomp (改行外し)文字列
定義
クオーテーション「""」と「''」変数の埋め込み
"・・・#{変数名}・・・"文字列の連結
文字列 + 文字列
※数値 + 文字列は使えない文字列 ⇔ 数値の変換
(→文字列)変数.to_s
(→数値) 変数.to_iEx. num_age = 19 str_age = '19' puts num_age + "歳" → エラー puts "#{num_age}歳" → 19歳 puts 'str_age' + '歳' → 19歳「""」と「''」の違い
- 文字列に埋め込んだ変数を展開する・・・「""」
- 文字列に埋め込んだ変数を展開しない・・・「''」
Ex. name = "田中" puts "やあ#{name}さん" → やあ田中さん puts 'やあ#{name}さん' → やあ#{name}さんif文のフォーマット
- 年号からうるう年を判別する
Ex. year = 2019 if year % 4 != 0 puts "うるう年ではありません" elsif year % 100 == 0 && year % 400 != 0 puts "うるう年ではありません elsif year % 100 == 0 || year % 4 == 0 puts "うるう年です" end - if文の判定結果をTrue,false if shipping_free?(3000) puts "3000以上の数" else puts "3000より小さい" endテストの自動化
Minitestの利用
- Fizzbuzzのテストを作成する メソッドから出力される値が期待通りかを検証できる
FizzBuzz.rbdef fizzbuzz(input_num) if input_num % 15 == 0 'Fizz Buzz' elsif input_num % 5 == 0 'Buzz' elsif input_num % 3 == 0 'Fizz' else input_num.to_s end endFizzBuzz_test.rbrequire 'minitest/autorun' require 'FizzBuzz' class FizzBuzzTest < Minitest::Test def test_fizz_buzz assert_equal '1', fizzbuzz(1) assert_equal 'Fizz', fizzbuzz(3) assert_equal 'Buzz', fizzbuzz(5) assert_equal 'Fizz Buzz', fizzbuzz(15) end end
- 投稿日:2019-08-11T21:56:22+09:00
Ruby プログラミングノート Part1
はじめに
Ruby on Rails チュートリアルの実施と並行してRubyの学習を行い
自身の記憶定着のためプログラミングノートとして書き起こす。Progateおよびチェリー本の1~3章での学習結果の書き起こしになる
RubyとRuby on Railsとの違い
Ruby Rails プログラミング言語
(Python等と同様)Rubyを用いたWebアプリケーションの
開発用のフレームワーク文字列、数値、true/false、nilのすべてがオブジェクト
(オブジェクトに対してメソッドが呼べる)MVCモデルの提供
M=Model(モデル) データの処理
V=View(ビュー) 見た目の処理
C=Controller(コントローラ) ModelとViewを制御するRubyの基本
Rubyファイルの実行
$ ruby ファイル名(~.rb) Ex. $ ruby sample.rbライブラリの種類
- インストール不要
- 標準ライブラリ(date,csvなど https://docs.ruby-lang.org/ja/latest/library/index.html)
- 標準ライブラリ(Array,Hashなど https://docs.ruby-lang.org/ja/latest/library/_builtin.html)
- インストール必要
- gem
ライブラリのインポート
- インストール不要
require "ライブラリ名" require "ファイルパス" ※ファイル名指定時に拡張子の「.rb」は不要 Ex. require "date" (Dateクラス) require "./home/start" (home/start.rbファイル)
- インストール必要 gem(外部ライブラリ)
変数宣言
変数名 = 値(型の宣言が不要)
※変数名だけ定義はできないコンソールへの入出力(putsとgets)
- コンソールへの表示
puts 文字列 puts 変数
- コンソールへの入力
変数名 = gets (改行付き) 変数名 = gets.chomp (改行外し)文字列
定義
クオーテーション「""」と「''」変数の埋め込み
"・・・#{変数名}・・・"文字列の連結
文字列 + 文字列
※数値 + 文字列は使えない文字列 ⇔ 数値の変換
(→文字列)変数.to_s
(→数値) 変数.to_iEx. num_age = 19 str_age = '19' puts num_age + "歳" → エラー puts "#{num_age}歳" → 19歳 puts 'str_age' + '歳' → 19歳「""」と「''」の違い
- 文字列に埋め込んだ変数を展開する・・・「""」
- 文字列に埋め込んだ変数を展開しない・・・「''」
Ex. name = "田中" puts "やあ#{name}さん" → やあ田中さん puts 'やあ#{name}さん' → やあ#{name}さんif文のフォーマット
- 年号からうるう年を判別する
Ex. year = 2019 if year % 4 != 0 puts "うるう年ではありません" elsif year % 100 == 0 && year % 400 != 0 puts "うるう年ではありません elsif year % 100 == 0 || year % 4 == 0 puts "うるう年です" end - if文の判定結果をTrue,false if shipping_free?(3000) puts "3000以上の数" else puts "3000より小さい" endテストの自動化
Minitestの利用
- Fizzbuzzのテストを作成する メソッドから出力される値が期待通りかを検証できる
FizzBuzz.rbdef fizzbuzz(input_num) if input_num % 15 == 0 'Fizz Buzz' elsif input_num % 5 == 0 'Buzz' elsif input_num % 3 == 0 'Fizz' else input_num.to_s end endFizzBuzz_test.rbrequire 'minitest/autorun' require 'FizzBuzz' class FizzBuzzTest < Minitest::Test def test_fizz_buzz assert_equal '1', fizzbuzz(1) assert_equal 'Fizz', fizzbuzz(3) assert_equal 'Buzz', fizzbuzz(5) assert_equal 'Fizz Buzz', fizzbuzz(15) end end
- 投稿日:2019-08-11T21:26:58+09:00
オブジェクト指向とは
今日は中々打ち合わせやらで、自分の勉強が進まなかったんだけど、
極力毎日ブログは書きたいので、簡単なものを書こうかなと。しばらくAWSの流れだったんだけど、AWSは理解が難しいので今日はオブジェクト指向ってやつについて書くよ。
僕はプログラミング初学者なわけでRubyをずっと使ってきたんだけど、Rubyはオブジェクト指向言語と言われているらしい。
で、オブジェクト指向ってそもそもなんだよっていう話。今回はRubyを用いてまとめていこうかと思うよ。
オブジェクト指向とは
オブジェクト指向とは、複数のオブジェクトを組み合わせてプログラムを構築する考え方。
オブジェクトとはデータと処理の集まりのことですが、漠然として集合体のことではなく、一つのテーマを持った集合体のことです。
人であれば「名前」、「年齢」、「出身地」などのデータを持ちます。
オブジェクト(今回のテーマは人)であれば、こういったデータの他に「振る舞い」があります。
例えば名前を聞くという「振る舞い」と、それに対して、自分の名前を返すという「振る舞い」。
ここでいう「振る舞い」をオブジェクト指向で考えると処理にあたるということです。概念的ではありますが、特別理解できないということではないと思います。
オブジェクト指向って何?という問いに対して、「現実と一緒だ」なんて回答もあるくらいです。
オブジェクト指向とクラス
オブジェクト指向の概念を説明しても、じゃあプログラミングに落とし込んだらどうなるか中々想像できないかと思います。
そこで必要になるのがクラスの概念です。
クラスとは
オブジェクト指向言語において、データと処理をひとまとめにしたもの。
オブジェクトの設計図とも呼ばれる。実際にRubyで書いてみます。
class Person def initialize(name, age , birthplace) @name = name @age = age @birthday = birthday end def answer_name puts @name end end人(person)クラスを定義して、名前や生年月日を持たせています。これがオブジェクト指向におけるデータのことです。
人(person)クラスで定義された人は、answer_nameメソッドという「振る舞い」をします。これがオブジェクト指向における処理のことです。
ここで定義されたクラスもオブジェクト、@nameといったインスタンス変数もオブジェクト、answer_methodもオブジェクトということになります。
結局、オブジェクト指向で生まれたものは全てオブジェクトと呼ばれることになります。
その中でもクラスは設計図、インスタンスは実体化したデータ、メソッドは実体化した処理とでもイメージすればいいのかなと思います。
いいか?結局、現実と一緒だ
- 投稿日:2019-08-11T15:00:23+09:00
【Ruby】 自己学習メモ まとめ
前置き
転職活動をキッカケに始めた新しい言語の勉強が思いのほか楽しくなってきたので、Rubyにも手をつけることにしました。
最終目標としては、「Rubyで何かシステムを作り、一般公開する」ですが、Qiitaへの投稿内容としては、勉強したコトのまとめです。このエントリは、今後投稿していく自己学習メモや、それに関する情報へのリンク集、その他Tips集のような内容としたいと思います。
開発環境
端末:MacBook Pro(macOS 10.14.5)
Macの場合は初期段階ですでにRuby導入済のため、「ソースを書いて、ターミナルで実行してみる」というレベルであれば追加でなにかインストールや設定を行う必要はなし。Hello World
ターミナルでの実行方法、および稼動確認をかねて、ごく基本的なソースの書き方を確認。
インストール済みのRubyバージョン確認
$ ruby -v ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin18]ファイルの実行
Rubyソースファイルの拡張子は"rb"
"Hello World"を表示するごく簡単なソースを書きます。HelloWorld.rbmessage = "Hello World!" puts messageファイルを指定して実行するには、rubyコマンドの後に、ファイル名を指定するだけ。
実行結果は以下の通り。$ ruby HelloWorld.rb Hello World!
puts
は改行ありの標準出力。
よって、以下のようなソースでも上記と同様の出力結果となる。
HelloWorld2.rbmessage = "Hello" print message message = " World!" puts message$ ruby HelloWorld2.rb Hello World!学習メモ リンク
これから追加していきます。
関連リンク集
これから追加していきます。
時間の都合上、いったんここまで。
改めて随時加筆修正予定。
- 投稿日:2019-08-11T13:31:09+09:00
Ruby on Railsの環境構築した時に出たエラーとか
はじめに
サーバーサイドの知識があまりなかったため、Railsをなんとなーく導入してみようと思い、なんとなーく環境構築を勧めていたら、無知も相まって色々と悩んだのでメモを残しておく。今回予め、Gitlab,Redmineあたりを勉強ついでに導入しており、その関係でRails側の設定やインストール工程を一部省いたりもしたため、rubyとかbundlerとかpostgresqlとかをrailsのためにインストールし直したりはしていない。
Railsを導入するにあたって参考にしたサイト
環境
- OS (CentOS7)
- ruby (2.4.1)
- bundler (1.17.3)
- gem (3.0.4)
- rails (5.2.3)
- postgresql (9.2.24)
本題
bundler command not found: spring
Bundle complete! 18 Gemfile dependencies, 60 gems now installed. Gems in the groups development and test were not installed. Bundled gems are installed into `./vendor/bundle` run bundle exec spring binstub --all bundler: command not found: spring Install missing gem executables with `bundle install`rails new 'アプリ名' -d postgresqlを実行した時に出たエラー。
単純にspringというコマンドがなく、次の工程に進めないという話なのだけど、なぜ存在しないのかが分からなかった。
結論から言うとbundlerのconfigに問題があり、developmentとtestグループがBUNDLE_WITHOUTに設定されていたため、Gemfileの特定の行を通っていなかった。
参考URL(http://ruby.studio-kingdom.com/bundler/bundle_config/).bundle/config--- BUNDLE_PATH: "vendor/bundle" BUNDLE_WITHOUT: "development:test"ひとまず以下の様に修正
.bundle/config--- BUNDLE_PATH: "vendor/bundle" BUNDLE_WITHOUT: "test"これでspringコマンド含め、諸々インストールされた。
Could not find a JavaScript runtime
JSのランタイムがないとかなんとか。nodejsインストールで解決した。
参考URL(http://djandjan.hateblo.jp/entry/2018/07/25/224929)Address already in use
正しくは
Address already in use - bind(2) for "127.0.0.1" port 3000 (Errno::EADDRINUSE)と出力されていた。
多分3000番ポートが既に使用されているので、ポートの使用状況を lsof -i:3000 で確認してみたら、どうやらGitlabで使われてるっぽい...のでRailsのポートを変更することにした。
以下のコマンドでひとまず解決。$ rails s -p 3001Linux上ではひとまず起動したようなので、よしこれでページアクセスできるわ!と思い、ブラウザーにアドレス入力。エンターキーに渾身の力をこめてターンッしたら想定していたページが表示されない。このサイトにアクセスできませんとのこと。
これについては、下のURLに詳しいことが書いてあった。
参考URL
結果$ rails s -b 0.0.0.0 -p 3001これでアクセス"は"できるようになった。
あとファイアウォールのポートの設定忘れてるとアクセスできないので注意。
role "ユーザー名" does not exist
データベース側の設定ができておらんのでアクセスできてもページの表示ができなかった。
まずはユーザーが存在しないところから。下記URLの通りにすれば作成できた。ユーザー名はRails sを実行しているユーザー名にすればいい思う。(多分)
自分の場合はrootでやっていたので、$ sudo su – postgres $ createuser -s -r rootで作成は完了。
参考URL(https://kirohi.com/rails_pg_error_role_doesnotexist)データベースが存在しない。
下記URLの通り設定していきましょう。"Rails の設定とか"の辺りに詳しく書いてある。
データベースの名前はエラーページに表示されている通り。(***の部分はrails new で作成したアプリの名前)
***_development
***_test
***_production
参考URL余談
改めて記事にしてみて、アドレスの指定のところとか、そもそもDBまわりの知識があまりないとかちらほらあったので改めて調べ直したら記事にして考えを整理したいと思う。
また、もし誤った情報があれば、ご指摘いただけると幸いです。
- 投稿日:2019-08-11T11:59:39+09:00
Rubyで競プロ、ちょっと高速化テク(ABC137D)
abc137d, abc128eのネタバレを含むので、
ネタバレ無しで解きたい方は説いてから御覧ください。問題
https://atcoder.jp/contests/abc137/tasks/abc137_d
解説
https://img.atcoder.jp/abc137/editorial.pdf
手順
解答フロー
[報酬がもらえるまでの日付, 報酬]を日付で昇順ソートして、
今日からM日後
までにもらえる報酬を最大化するための仕事の割り振りを、
今日から考えるのではなくM-1日後の仕事の予定から埋めていくイメージになります。M-1日後にやって、1日後(今日からM日後)までに報酬がもらえる仕事の内最大の報酬の仕事を取る、
M-2日後にやって、2日後(今日からM日後)までに報酬がもらえる仕事の内最大の報酬の仕事を取る、
...
今日やってM日後までに報酬がもらえる仕事の内最大の報酬の仕事を取る。という形で報酬の最大化ができます。(自明)
1日後に報酬がもらえる仕事の報酬を最大Heap(親ノードの方が必ずでかい)にぶっこんで、1個pop(最大値を取り出す)、
2日後に報酬がもらえる仕事の報酬を最大Heapに全部ぶっこんで、1個pop
...
という形で時間内に答えることが出来るはずです。こういうデータ構造はABCのDぐらいだとちょくちょく求められるので予め作っておいた方が無難です。
https://github.com/k-karen/ruby-samples/blob/master/heap/pop_heap.rb
私の最大Heapを置いておきます、よろしければご利用ください。高速化テク
ということで今回は[日付, 報酬]の配列を日付でsortしたいという場面が出てくると思います。
普通にやるとn, m = gets.split.map(&:to_i) datas1 = [] n.times do datas1 << gets.split.map(&:to_i) end datas1.sort_by!(&:first)と書くと思いますが、
sort_by!(&:first)
は(後述の方法より)早くないです。
今回は入力が全部正の値で、その上限が10^5程度とわかっていますので、
これを利用して以下のように書くことができます# (10**5).bit_length #=> 17 # 17ビットずらせば、2つの値を独立に保存できる n, m = gets.split.map(&:to_i) datas2 = [] n.times do tmp = gets.split.map(&:to_i) datas2 << (tmp[0] << 17) + tmp[1] end datas2.sort!これだと気持ち早くなります。
値を取り出すときは予めビットマスクを用意しておいて、それとandを取れば良いです。
mask = (1 << 17) - 1 datas.each do |day_salary| day = day_salary >> 17 salary = day_salary & mask endどんぐらい早くなるか
before( max 817ms )
https://atcoder.jp/contests/abc137/submissions/6816390
after ( max 775ms )
https://atcoder.jp/contests/abc137/submissions/6840374
今回はあまり効果がありませんが、
多重キーソートも値の順番を正しく配置すればいい感じに行えます(ABC128E)
降順と昇順が入り交じる場合は、入力の上限から引いた値を入れるなどの工夫が必要になります。俗に言うイベントソートで大活躍する手法です。
そもそもそんな小手先の高速化を行うなら、
RubyじゃなくてC++でかけという話、ごもっともなので勘弁してください。最後に、同じような手法で出来る問題置いておきます。
https://atcoder.jp/contests/abc128/tasks/abc128_e
- 投稿日:2019-08-11T11:51:50+09:00
Ruby ハッシュの取り出し
ハッシュの取り出しの復習!!
配列の内部に、複数のユーザーの情報をハッシュとして持つ変数user_data
ターミナルでの結果を以下としたい。
George
Alice
Taro問題
、、、rb
user_data = [
{
user: {
profile: {
name: 'George'
}
}
},
{
user: {
profile: {
name: 'Alice'
}
}
},
{
user: {
profile: {
name: 'Taro'
}
}
}
]
、、、答え
、、、
user_data.each do |u|
puts u[:user][:profile][:name]
end
、、、
あるいは
、、、
user_data.each{ |u| puts u.dig(:user, :profile, :name) }
、、、
- 投稿日:2019-08-11T11:49:06+09:00
配列の範囲指定をうっかり間違えたために本当にあった怖い話
要点
- Rubyの配列の要素取り出しは
ary[p..q]
とary[p...q]
という表記があって、Python のary[p:q]
に相当するのは後者。- オーディオサンプリング周波数 44100 を 4 倍して 1 足すと素数になる (←知ってました?)。
- FFT の一番広く使われている Cooley-Tukey のアルゴリズムはデータを因数分解した数に分けて細切れにしていく。
以上で何がいいたいかわかった方はそれで十分です。気をつけましょう…
本当にあった怖くて恥ずかしい話
Python の numpy で 4 s のオーディオ信号を FFT するプログラムがありました。
ぼくは Python が嫌いなので、それを mrkn 氏の素晴らしい Pycall (https://github.com/mrkn/pycall.rb) を使って Ruby に移植しました。その際、Python で 4 s 切り出す
data[ptr:ptr + 44100 * 4]
という感じの部分を、うっかりdata[ptr..(ptr + 44100 * 4)]
と書いてしまった のです。もちろん正解は..
ではなく...
です。その結果 謎のフリーズ。いや実際は単に計算に時間がかかっていただけなんですが、10 s 以上も固まれば、そりゃ
^C
押しますって。そして何は原因なんだろうpycallかな、などとあらぬ疑いを頓珍漢な方向に向けたりして リアルに3-4時間くらい時間を無駄にしました。(恥ずかしい。)衝撃の再現コード
巷では Python の方が人気と聞くので Python のみで動くように書きました。実行すれば驚きを体験できます。
#!/usr/bin/python3 import numpy as np fs = 44100 duration = 4 data = np.random.randn(fs * 10) # dummy data print("test 1") y = np.fft.fft(data[0:fs * duration]) print("test 2") y = np.fft.fft(data[0:fs * duration + 1])本当はいろいろ Ruby で書きたいんだけど numpy とか keras とかがないから必要悪と割り切って Python を使っている人は pycall.rb (やそれを使った numpy.rb) を使いましょう!上記のコードならこんな↓感じにほぼベタ移植できます。すごい > pycall
#!/usr/bin/ruby require "numpy" # gem install numpy fs = 44100 duration = 4 data = Numpy.random.randn(fs * 10) # dummy data puts "test 1" y = Numpy.fft.fft(data[0...fs * duration]) puts "test 2" y = Numpy.fft.fft(data[0..fs * duration])おわりに
- Ruby は文法がきれいで書きやすくて好きなんですが、まさかこういうハマり方をするとは思ってもいませんでした。自分が悪いんですけど。
- $44100\times4+1$ という大きめの覚えやすい素数が手に入ったのは収穫。ちなみに $44100\times4-1 = 419\times 421$ も ふたつの素数の積なので注意。
- 投稿日:2019-08-11T10:05:39+09:00
Rails Tutorialの知識から【ポートフォリオ】を作って勉強する話 #7 ログイン下準備編
こんな人におすすめ
- プログラミング初心者でポートフォリオの作り方が分からない
- Rails Tutorialをやってみたが理解することが難しい
- ポートフォリオを作成しながら勉強したい
リードミー
- 目的:ポートフォリオを作成して会社に面接を受ける準備をする
- AWSによるCloud9で作成
- 間違いの可能性大、一緒に勉強させてください
![]()
ログインまでの色々を実装する
Tutorialは8.1 セッションに突入。
これからログインするまでのあれこれを実装していこう
流れとしては下記の3つを行う。
- コントローラ生成
- ビュー生成
- それらのテスト生成
機能としてのログインは次回#8。
ログインのためのコントローラ生成
とりあえずTutorial通りにSessionsコントローラを生成する。
くどいけどコントローラテストはRequest specで書く。bash$ rails g controller Sessions new $ rails g rspec:request sessionspec/requests/sessions_spec.rbrequire 'rails_helper' RSpec.describe "Sessions", type: :request do describe "GET /login" do it "returns http success" do get login_path expect(response).to have_http_status(:success) end end endあとはホーム画面の'Login'ボタンのリンク先も書く。
app/views/layouts/_header.html.erb<!-- 中略 --> <div id="menu" class="collapse navbar-collapse"> <ul class="navbar-nav ml-auto"> <li class="nav-item"> <%= link_to "Login", login_path, class: "btn btn-info btn-md" %> </li> </ul> </div> <!-- 中略 -->以前failureとなったテストがようやくこれで通る。
ではSessionsコントローラを実装しよう。app/controllers/sessions_controller.rbclass SessionsController < ApplicationController def new end def create user = User.find_by(email: params[:session][:email].downcase) if user && user.authenticate(params[:session][:password]) # ユーザーログイン後にユーザー情報のページにリダイレクトする else # エラーメッセージを作成する render 'new' end end def destroy end endcreateアクションにこんな記述があると思うけど、
if user && user.authenticate(params[:session][:password])Tutorialではこんな風に述べてくれている。
Rubyではnilとfalse以外のすべてのオブジェクトは、真偽値ではtrueになる
だからUserクラスが真偽値っぽくなくてもif文が通るのね。
あと何気にuserがインスタンスじゃないのも特徴。
createアクションに対するビューとかが必要なく(ログインできましたよ!みたいな画面を別で作るなら考慮してよい)アクション内で収まるのでインスタンスでない。ログインのためのビュー生成
form_for(:session, url: login_path)について考える
続いてログイン画面を作ろうと思うんだけど、Tutorialでこんな記述がある。
form_for(@user)Railsでは上のように書くだけで、「フォームのactionは/usersというURLへのPOSTである」と自動的に判定しますが、セッションの場合はリソースの名前とそれに対応するURLを具体的に指定する必要があります。
form_for(:session, url: login_path)なにこれ??最初は意味が分かりませんでした。
で調べたわけだけど、リソース名を'session'にすることでparams[:session]にキーと値が保存されるのね。つまり渡しているのはそれぞれこう。
form_for(@user) → params[:user] form_for(:session, url: login_pash) → params[:session]このあたりはこちらが分かりやすい!↓
rails ログイン機能のform_forの作りについての疑問
[Rails4.0] フォームの基本とStrongParametersを理解するform_withで書き換える
このポートフォリオではform_forではなくform_withを使う(理由は#6)。
その際はリソース名をscopeに指定するので、最終的にはこうなる。app/views/sessions/new.html.erb<% provide(:title, "ログイン") %> <div class="container form-container login-container"> <div class="row"> <div class="col"> <div class="form-logo-img"> <%= link_to image_tag('lantern_lantern_logo.png', width: 100), root_path, class: "logo-img" %> </div> <h1 class="form-title">ログイン</h1> <%= form_with(scope: :session, url: login_path, local: true) do |form| %> <div class="form-group"> <%= form.email_field :email, class: 'form-control', placeholder: "メールアドレス" %> </div> <div class="form-group"> <%= form.password_field :password, class: 'form-control', placeholder: "パスワード" %> </div> <div class="form-group"> <%= form.submit "ログイン", class: "btn btn-info btn-lg form-submit" %> </div> <% end %> <p class="form-go-to-signup-or-login">新しくはじめる方は<%= link_to "こちら", signup_path %></p> </div> </div> </div>書き換えでお世話になりました↓
【Ruby】チュートリアルのform_forをform_withで書き換え (おまけ:capybaraでのテスト)ログインのE2Eテスト生成
Tutorial 8.1.5 フラッシュのテストにならってテストをSystem specで書こう。
Tutorialとの差分も用意する。bash$ touch spec/systems/login_spec.rbspec/systems/login_spec.rb(RSpec:ポートフォリオ)require 'rails_helper' RSpec.describe "Logins", type: :system do context "login with invalid information" do it "is invalid because it has no information" do visit login_path expect(page).to have_selector '.login-container' fill_in 'メールアドレス', with: '' fill_in 'パスワード', with: '' click_on 'ログイン' expect(page).to have_selector '.login-container' expect(page).to have_selector '.alert-danger' end it "disappears flash messages when users input invalid information then other links" do visit login_path expect(page).to have_selector '.login-container' fill_in 'メールアドレス', with: '' fill_in 'パスワード', with: '' click_on 'ログイン' expect(page).to have_selector '.login-container' expect(page).to have_selector '.alert-danger' visit root_path expect(page).not_to have_selector '.alert-danger' end end endtest/integration/users_login_test.rb(Minitest:Tutorial)require 'test_helper' class UsersLoginTest < ActionDispatch::IntegrationTest test "login with invalid information" do get login_path assert_template 'sessions/new' post login_path, params: { session: { email: "", password: "" } } assert_template 'sessions/new' assert_not flash.empty? get root_path assert flash.empty? end end大きな変更点は5つ。
- テストは1つから2つに
- getはvisitに
- assert_templateはhave_selectorに
- postはfill_inに
- flash_empty?はhave_selectorに
1.
・フォームに入力しない場合エラーが発生する
・その場合別ページでflashが消える
を独立させたかったので2つに分けた。2.
System specでgetやpostを指定するとうまくいかない。
代わりにvisitを使おう。3.
assert_templateもRequest specでしか動作が確認できないので、have_selectorを使用しdivを検証することで描画をテストする。4.
E2Eテストの性格上、直接postをリクエストするのではなくフォームに値を入力する方がテストらしいのでfill_inを使う。5.
flashに対してbe_emptyを使用したテストは実装できなかった。
System specではこういう書き方もできない。expect(flash[:danger]).to be_truthybashNoMethodError: undefined method `flash' for nil:NilClass(Request specでは無事機能する)
Request specと異なりSystem specはコントローラで使用できるFlashHashオブジェクトと紐づいていないっぽい??
代わりにalert時に生成されるdiv要素を検証した。参考にさせていただきました↓
Ruby on Rails ガイド 5.2 Flash次回はいよいよ機能としてのログイン実装
おそらく次回がログインのメインです。
Sessionsヘルパーに各メソッドを与えます。
(超初心者向け)解説が載っているのでぜひご参考に〜
- 投稿日:2019-08-11T09:38:58+09:00
Railsチュートリアル1章まとめ
はじめに
Railsチュートリアルで発生したエラーとか詰まったところをまとめていこうと思います。
備忘録として。
2週目の今回はbitbucketではなくgithubで進めていこうと思います。rails newの時点でエラー発生
$rails _5.1.6_ new hello_app2 #エラー発生 can't find gem railties (= 5.1.6) with executable rails (Gem::GemNotFoundException)対処方法が下記コマンド
$gem install rails -v 5.1.6こちらで再度rails newコマンドすれば無事作成できました。
githubでのリポジトリ作成
いつもはgithubからローカルにクローンするやり方でやってたので今回はこちらで。
ローカルからプッシュするやり方で。まずgithubでリポジトリ作成する。
名前はhello_app2にしました。# ローカルリポジトリを作成するディレクトリに移動する cd hello_app2 # ローカルリポジトリを作成する $ git init $ git add . $ git commit -m "first commit # リモートリポジトリのアクセス先を設定する $ git remote add origin https://github.com/GitHubのユーザ名/GitHubのリポジトリ名(こちらではhello_app2).git # pushする $ git push -u origin mastergit push heroku でエラー
エラー文
remote: ! remote: ! Could not detect rake tasks remote: ! ensure you can run `$ bundle exec rake -P` against your app remote: ! and using the production group of your Gemfile. remote: ! Activating bundler (2.0.1) failed: remote: ! Could not find 'bundler' (2.0.1) required by your /tmp/build_b85aaac02a3a812e844f20844711c628/Gemfile.lock. remote: ! To update to the latest version installed on your system, run `bundle update --bundler`. remote: ! To install the missing version, run `gem install bundler:2.0.1` remote: ! Checked in 'GEM_PATH=vendor/bundle/ruby/2.5.0', execute `gem env` for more information remote: ! remote: ! To install the version of bundler this project requires, run `gem install bundler -v '2.0.1'` remote: !こちらのエラー分の中にあるように下記コマンド
$ gem install bundler -v 2.0.1 $ rm Gemfile.lock $ bundle install $ git add . $ git commit -m 'hoge' $ git push heroku masterこちらで解決し無事デプロイ完了しました。