20211126のRubyに関する記事は6件です。

M1でrails db:createが出来ない no suitable image found. Did find: (LoadError)諸々

M1でのrailsアプリ環境構築方法についてはこちらでまとめています。 環境 rbenv 1.2.0 ruby 3.0.2 Bundler 2.2.32 yarn 1.22.17 DBはpostgresql rails db:createが出来ない問題 rails db:createをすると このようなエラーが大量発生してしまいました。 no suitable image found. Did find: (LoadError)とあります。 何かがないのでしょう。(かなり曖昧) 対処法 arch -arm64 gem install msgpack bootsnap bindex zeitwerk activesupport spring webpacker railties rack thor nio4r puma bootsnap activesupport ffi でインストールし直すとrails db:createが成功しました。 M1で出てしまうエラーなのか、もしくは私のMacがいけないのかわかりませんが 同じようなエラーで悩まれている方がいたら参考にしてください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rbenv global を出力してもversionが切り替わらない!

背景 AWSへのデプロイ中に EDITOR=vim bin/rails credentials:editをしたらversionが古いと言われたので bundle install を実行すると ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write permissions for the /Library/Ruby/Gems/2.3.0 directory. 訳: 許可がありません(ざっくり) と言われました。 ↑の記事を見ると、これが起こる原因はrbenvのversionがデフォルトのシステムを使っていて権限がないからエラーになると聞いたので、確かめてみるとシステムのversionを使っていました。 そこでGemfileに記載されているrubyのversion3.0.2をセットしようと rbenv global 3.0.2 を実行したが、できず、rubyの参照先や実行パスを通してみたもののversionを切り替えることができなかった。 いきなり結論 rbenv local 3.0.2 と出力すると、すんなりversion切り替えができました。 rbenv globalとrbenv localの違いは、rbenvが開発する時のデフォルトのrubyのversionを指定するのがglobalであり、特定のディレクトリ下のみのrubyのversionを指定するのがlocalでした。覚えてないですが、おそらく以前にlocalでversionを指定しまったのでしょう…。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ruby on rails の環境設定をしたよ。

railsの環境設定にかなり手こずったので、記録。 これが初めての環境設定。 Mac:11.2.2 Ruby:3.0.0 Rails:6.1.4.1 rbenv:3.0.0 まず  progate に沿ってやろうとしたものの、ファイルを作る事ができず詰まる。 rubyとrbenvのバージョンが合わないからではないかと仮説を立てた。 この記事を参考にバージョンを合わせる。 必要なgem(?)がないとエラーメッセージが出たので、指示に従う。 合わせてエラーメッセージの読み取れなかった箇所を検索し、下記の記事に出会う。 私のrubyはバージョン3.0.0だったので、  Ruby 3.0.0 リリース を参考に BUNDLER_VERSION=2.2.3 bundle install を実行したらなんとかなった。 あとは rails s したらyarnとwebpackerってのがインストールできてないってエラーが出たので これの通りにしたらなんとかなった。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【rubyでcomet2を作る】④プログラムを実行する

はじめに 【rubyでcomet2を作る】③CPUオブジェクト、メモリオブジェクトを定義する2の続きです。 今回は、前回までに作成したCPUオブジェクト、メモリオブジェクトを使って、下記4つのプログラムを実行していきます。 - 単純加算処理 - 条件分岐処理 - 繰返処理 - サブルーチン処理 普段簡単に書いているこのような処理をCPUではどのように処理しているのか見ていきたいと思います。 完成コード 実行状況を見やすくする プログラムの実行状況を見やすくするために、下記変更を加えます。 - 命令読出(フェッチ)後、実行する命令を表示する - 命令実行後、レジスタの状況を表示する cpu.rb # 命令の読み出し(フェッチ) ir = memory.send("m#{pr}") self.pr += 1 # 実行する命令を表示する if ir[2].instance_of?(Array) puts "#{ir[0]} #{ir[1]} #{ir[2].join(',')}" elsif ir[2].nil? puts "#{ir[0]} #{ir[1]}" else puts "#{ir[0]} #{ir[1]} #{ir[2]}" end cpu.rb # レジスタの状況を表示する def observe_register puts "PR:#{self.pr}, SP:#{self.sp}, FR[ZF,SF,OF]:#{self.fr}" puts "gr0:#{self.gr0}, gr1:#{self.gr1}, gr2:#{self.gr2}, gr3:#{self.gr3}" puts "-------------------------------------------------------" end プログラムを実行する 例として4つのプログラムを実行していきます。実行するプログラムはどこに書いてもいいのですが、今回はmain.rbに書いていくことにします。 ①加算結果を取得する 定数Aと定数Bの加算処理を行い、結果をANSに保存します。 main.rb require './lib/cpu' require './lib/memory' memory = Memory.new cpu = CPU.new # 例①加算結果を取得する # ラベル オペコード  オペランド memory.m0 = ['', 'START' ] memory.m1 = ['', 'LD', ['gr0','A'] ] # GR0にAの値を格納 memory.m2 = ['', 'LD', ['gr1','B'] ] # GR1にBの値を格納 memory.m3 = ['', 'ADDA', ['gr0','gr1'] ] # GR0とGR1の値を加算 memory.m4 = ['', 'ST', ['gr0','ANS'] ] # GR0の値をANSに格納 memory.m5 = ['A', 'DC', '123' ] # 定数Aを定義 memory.m6 = ['B', 'DC', '456' ] # 定数Bを定義 memory.m7 = ['ANS', 'DS', '1' ] # 領域ANSを確保 memory.m8 = ['', 'END' ] # m40-m49をスタック領域として確保 memory.m40 = [''] memory.m41 = [''] memory.m42 = [''] memory.m43 = [''] memory.m44 = [''] memory.m45 = [''] memory.m46 = [''] memory.m47 = [''] memory.m48 = [''] memory.m49 = [''] cpu.control(memory) puts "参考:memory7の状況 #{memory.m7}" 実行結果は以下の通りです。 START PR:1, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:, gr1:, gr2:, gr3: ------------------------------------------------------- LD gr0,A "gr0に123を読み込みました。" PR:2, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:123, gr1:, gr2:, gr3: ------------------------------------------------------- LD gr1,B "gr1に456を読み込みました。" PR:3, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:123, gr1:456, gr2:, gr3: ------------------------------------------------------- ADDA gr0,gr1 "gr0にgr0のデータ+gr1のデータを格納しました。" PR:4, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:579, gr1:456, gr2:, gr3: ------------------------------------------------------- ST gr0,ANS "ANSにgr0のデータを格納しました。" PR:5, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:579, gr1:456, gr2:, gr3: ------------------------------------------------------- A DC 123 PR:6, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:579, gr1:456, gr2:, gr3: ------------------------------------------------------- B DC 456 PR:7, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:579, gr1:456, gr2:, gr3: ------------------------------------------------------- ANS DS 579 PR:8, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:579, gr1:456, gr2:, gr3: ------------------------------------------------------- END 参考:memory7の状況 ["ANS", "DS", "579"] 意図した通りに動いています。普段であれば下記の1行で済むことですが、CPUはこの計算をこれだけの工程を踏んで実行しているということが分かります。 ans = 123 + 456 ②絶対値を取得する(条件分岐) 定数Aの絶対値を取得し、結果をANSに保存します。プログラム領域のコードのみ記載します。 main.rb # 例②絶対値を取得する(条件分岐) # ラベル オペコード  オペランド memory.m0 = ['ABS', 'START' ] memory.m1 = ['', 'LAD', ['gr0','0'] ] # GR0に0を格納 memory.m2 = ['', 'LD', ['gr1','A'] ] # GR1にAの値を格納 memory.m3 = ['', 'CPA', ['gr0','gr1'] ] # GR0とGR1を比較 memory.m4 = ['', 'JMI', ['LABEL'] ] # GR0 < GR1ならLABELへジャンプ memory.m5 = ['', 'XOR', ['gr1','65535'] ] # GR1のビットの並びを反転 memory.m6 = ['', 'ADDA', ['gr1','1'] ] # GR1の値に1を加算 memory.m7 = ['LABEL', 'ST', ['gr1','ANS'] ] # GR1の値をANSに格納 memory.m8 = ['A', 'DC', '-123' ] # 定数Aを定義 memory.m9 = ['ANS', 'DS', '1' ] # 領域ANSを確保 memory.m10 = ['', 'END' ] 実行結果 m5,m6にて絶対値に変換しています。 ABS START PR:1, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:, gr1:, gr2:, gr3: ------------------------------------------------------- LAD gr0,0 "gr0に0を格納しました。" PR:2, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:, gr2:, gr3: ------------------------------------------------------- LD gr1,A "gr1に-123を読み込みました。" PR:3, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:-123, gr2:, gr3: ------------------------------------------------------- CPA gr0,gr1 "gr0のデータとgr1のデータの算術比較を行いました。" PR:4, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:-123, gr2:, gr3: ------------------------------------------------------- JMI LABEL PR:5, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:-123, gr2:, gr3: ------------------------------------------------------- XOR gr1,65535 "gr1にgr1のデータと65535の排他的論理和を格納しました。" PR:6, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:122, gr2:, gr3: ------------------------------------------------------- ADDA gr1,1 "gr1にgr1のデータ+1を格納しました。" PR:7, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:123, gr2:, gr3: ------------------------------------------------------- LABEL ST gr1,ANS "ANSにgr1のデータを格納しました。" PR:8, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:123, gr2:, gr3: ------------------------------------------------------- A DC -123 PR:9, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:123, gr2:, gr3: ------------------------------------------------------- ANS DS 123 PR:10, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:123, gr2:, gr3: ------------------------------------------------------- END 参考:memory9の状況 ["ANS", "DS", "123"] 実行結果(A=123、元から整数の時) m3の結果を元に、m4の処理でm7にジャンプしています。(m5,m6を飛ばしています) ABS START PR:1, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:, gr1:, gr2:, gr3: ------------------------------------------------------- LAD gr0,0 "gr0に0を格納しました。" PR:2, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:, gr2:, gr3: ------------------------------------------------------- LD gr1,A "gr1に123を読み込みました。" PR:3, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:123, gr2:, gr3: ------------------------------------------------------- CPA gr0,gr1 "gr0のデータとgr1のデータの算術比較を行いました。" PR:4, SP:49, FR[ZF,SF,OF]:[0, 1, 0] gr0:0, gr1:123, gr2:, gr3: ------------------------------------------------------- JMI LABEL "PRを7に変更しました。" PR:7, SP:49, FR[ZF,SF,OF]:[0, 1, 0] gr0:0, gr1:123, gr2:, gr3: ------------------------------------------------------- LABEL ST gr1,ANS "ANSにgr1のデータを格納しました。" PR:8, SP:49, FR[ZF,SF,OF]:[0, 1, 0] gr0:0, gr1:123, gr2:, gr3: ------------------------------------------------------- A DC 123 PR:9, SP:49, FR[ZF,SF,OF]:[0, 1, 0] gr0:0, gr1:123, gr2:, gr3: ------------------------------------------------------- ANS DS 123 PR:10, SP:49, FR[ZF,SF,OF]:[0, 1, 0] gr0:0, gr1:123, gr2:, gr3: ------------------------------------------------------- END 参考:memory9の状況 ["ANS", "DS", "123"] ③1からNUMまでの合計を求める(繰返処理) 1からNUMに定義した定数までの合計を取得し、ANSに保存します。条件を満たすまで、m3~m7の処理が繰り返し実行されています。今回は合計を求めているだけですが、m6が繰り返しの中身になりますので、m6を調整すると色々なことができるようになります。 main.rb # 例③1からNUMまでの合計を求める(繰返処理) # ラベル オペコード  オペランド memory.m0 = ['SUM', 'START' ] memory.m1 = ['', 'LAD', ['gr0','0'] ] # 0をGR0に格納 memory.m2 = ['', 'LAD', ['gr1','0'] ] # 0をGR1に格納 memory.m3 = ['LABEL1','ADDA', ['gr0','1'] ] # GR0に1を加算 memory.m4 = ['', 'CPA', ['gr0','NUM'] ] # GR0とNUMを算術比較 memory.m5 = ['', 'JPL', ['LABEL2'] ] # GR0 > NUM の場合LABEL2にジャンプ memory.m6 = ['', 'ADDA', ['gr1','gr0'] ] # GR1にGR0を加算 memory.m7 = ['', 'JUMP', ['LABEL1'] ] # 無条件にLABEL1へジャンプ memory.m8 = ['LABEL2','ST', ['gr1','ANS'] ] # ANSにGR1を格納 memory.m9 = ['NUM', 'DC', '3' ] # 定数NUMを定義 memory.m10 = ['ANS', 'DS', '1' ] # 領域ANSを確保 memory.m11 = ['', 'END' ] 実行結果 SUM START PR:1, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:, gr1:, gr2:, gr3: ------------------------------------------------------- LAD gr0,0 "gr0に0を格納しました。" PR:2, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:, gr2:, gr3: ------------------------------------------------------- LAD gr1,0 "gr1に0を格納しました。" PR:3, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:0, gr1:0, gr2:, gr3: ------------------------------------------------------- LABEL1 ADDA gr0,1 "gr0にgr0のデータ+1を格納しました。" PR:4, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:1, gr1:0, gr2:, gr3: ------------------------------------------------------- CPA gr0,NUM "gr0のデータと3の算術比較を行いました。" PR:5, SP:49, FR[ZF,SF,OF]:[0, 1, 0] gr0:1, gr1:0, gr2:, gr3: ------------------------------------------------------- JPL LABEL2 PR:6, SP:49, FR[ZF,SF,OF]:[0, 1, 0] gr0:1, gr1:0, gr2:, gr3: ------------------------------------------------------- ADDA gr1,gr0 "gr1にgr1のデータ+gr0のデータを格納しました。" PR:7, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:1, gr1:1, gr2:, gr3: ------------------------------------------------------- JUMP LABEL1 "PRを3に変更しました。" PR:3, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:1, gr1:1, gr2:, gr3: ------------------------------------------------------- LABEL1 ADDA gr0,1 "gr0にgr0のデータ+1を格納しました。" PR:4, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:2, gr1:1, gr2:, gr3: ------------------------------------------------------- CPA gr0,3 "gr0のデータと3の算術比較を行いました。" PR:5, SP:49, FR[ZF,SF,OF]:[0, 1, 0] gr0:2, gr1:1, gr2:, gr3: ------------------------------------------------------- JPL LABEL2 PR:6, SP:49, FR[ZF,SF,OF]:[0, 1, 0] gr0:2, gr1:1, gr2:, gr3: ------------------------------------------------------- ADDA gr1,gr0 "gr1にgr1のデータ+gr0のデータを格納しました。" PR:7, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:2, gr1:3, gr2:, gr3: ------------------------------------------------------- JUMP LABEL1 "PRを3に変更しました。" PR:3, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:2, gr1:3, gr2:, gr3: ------------------------------------------------------- LABEL1 ADDA gr0,1 "gr0にgr0のデータ+1を格納しました。" PR:4, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:3, gr1:3, gr2:, gr3: ------------------------------------------------------- CPA gr0,3 "gr0のデータと3の算術比較を行いました。" PR:5, SP:49, FR[ZF,SF,OF]:[1, 0, 0] gr0:3, gr1:3, gr2:, gr3: ------------------------------------------------------- JPL LABEL2 PR:6, SP:49, FR[ZF,SF,OF]:[1, 0, 0] gr0:3, gr1:3, gr2:, gr3: ------------------------------------------------------- ADDA gr1,gr0 "gr1にgr1のデータ+gr0のデータを格納しました。" PR:7, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:3, gr1:6, gr2:, gr3: ------------------------------------------------------- JUMP LABEL1 "PRを3に変更しました。" PR:3, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:3, gr1:6, gr2:, gr3: ------------------------------------------------------- LABEL1 ADDA gr0,1 "gr0にgr0のデータ+1を格納しました。" PR:4, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:4, gr1:6, gr2:, gr3: ------------------------------------------------------- CPA gr0,3 "gr0のデータと3の算術比較を行いました。" PR:5, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:4, gr1:6, gr2:, gr3: ------------------------------------------------------- JPL LABEL2 "PRを8に変更しました。" PR:8, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:4, gr1:6, gr2:, gr3: ------------------------------------------------------- LABEL2 ST gr1,ANS "ANSにgr1のデータを格納しました。" PR:9, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:4, gr1:6, gr2:, gr3: ------------------------------------------------------- NUM DC 3 PR:10, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:4, gr1:6, gr2:, gr3: ------------------------------------------------------- ANS DS 6 PR:11, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:4, gr1:6, gr2:, gr3: ------------------------------------------------------- END 参考:memory10の状況 ["ANS", "DS", "6"] ④平均値を取得する(サブルーチン) DATA1とDATA2の平均値を取得し、AVEに保存します。CALL命令,RET命令を使ってサブルーチンに一部処理を渡しています。 main.rb # ラベル オペコード  オペランド memory.m0 = ['MAIN', 'START' ] # メインルーチンの先頭 memory.m1 = ['', 'LD', ['gr0','DATA1'] ] # DATA1をGR0に格納 memory.m2 = ['', 'LD', ['gr1','DATA2'] ] # DATA2をGR1に格納 memory.m3 = ['', 'CALL', ['SUB'] ] # サブルーチン呼出 memory.m4 = ['', 'ST', ['gr0','AVE'] ] # 処理結果をAVEに格納 memory.m5 = ['DATA1', 'DC', '100' ] # 定数DATA1を定義 memory.m6 = ['DATA2', 'DC', '200' ] # 定数DATA2を定義 memory.m7 = ['AVE', 'DS', '1' ] # 領域AVEを確保 memory.m8 = ['', 'END' ] # メインルーチンの末尾 memory.m9 = ['SUB', 'START' ] # サブルーチンの先頭 memory.m10 = ['', 'ADDA', ['gr0','gr1'] ] # GR0とGR1を加算しGR0に格納 memory.m11 = ['', 'SRA', ['gr0','1'] ] # GR0を1ビット右シフト(1/2にする) memory.m12 = ['', 'RET' ] # メインルーチンに戻る memory.m13 = ['', 'END' ] # サブルーチンの末尾 実行結果 サブルーチンに処理を渡していますので、下記の順番でPRが動いています。 0→1→2→3→9→10→11→12→4→5→6→7→8 また、CALL命令とRET命令でSPの値を変更することで、この処理を実現していることが分かります。 MAIN START PR:1, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:, gr1:, gr2:, gr3: ------------------------------------------------------- LD gr0,DATA1 "gr0に100を読み込みました。" PR:2, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:100, gr1:, gr2:, gr3: ------------------------------------------------------- LD gr1,DATA2 "gr1に200を読み込みました。" PR:3, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:100, gr1:200, gr2:, gr3: ------------------------------------------------------- CALL SUB "スタック領域:m48に4を格納しました。" "PRを9に変更しました。" PR:9, SP:48, FR[ZF,SF,OF]:[0, 0, 0] gr0:100, gr1:200, gr2:, gr3: ------------------------------------------------------- SUB START PR:10, SP:48, FR[ZF,SF,OF]:[0, 0, 0] gr0:100, gr1:200, gr2:, gr3: ------------------------------------------------------- ADDA gr0,gr1 "gr0にgr0のデータ+gr1のデータを格納しました。" PR:11, SP:48, FR[ZF,SF,OF]:[0, 0, 0] gr0:300, gr1:200, gr2:, gr3: ------------------------------------------------------- SRA gr0,1 "gr0のデータを1 左シフトしました。" PR:12, SP:48, FR[ZF,SF,OF]:[0, 0, 0] gr0:150, gr1:200, gr2:, gr3: ------------------------------------------------------- RET PR:4, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:150, gr1:200, gr2:, gr3: ------------------------------------------------------- ST gr0,AVE "AVEにgr0のデータを格納しました。" PR:5, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:150, gr1:200, gr2:, gr3: ------------------------------------------------------- DATA1 DC 100 PR:6, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:150, gr1:200, gr2:, gr3: ------------------------------------------------------- DATA2 DC 200 PR:7, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:150, gr1:200, gr2:, gr3: ------------------------------------------------------- AVE DS 150 PR:8, SP:49, FR[ZF,SF,OF]:[0, 0, 0] gr0:150, gr1:200, gr2:, gr3: ------------------------------------------------------- END 参考:memory7の状況 ["AVE", "DS", "150"] 以上4つのサンプルプログラムを実行しました。 おわりに COMET2を作ってみようと思ったのは、次の2点からでした。 1. CPUの理解を深める 2. railsではなく、rubyの理解を深める 動画や書籍を見て分かったつもりになっていた機能も実際にコードに落とし込んでみると、理解が浅いところが多々あり、CPUの理解はとても深まったのではないかと思います。また、一からオブジェクトを作るという作業を初めて行なったのでrubyについても学習を進めることができたと思っています。 今後の学習については、 作成したシミュレータをより厳密にする(ビットの次元で考える) プロセス管理や割込処理、周辺機器やOSなど理解を広げる などを考えていますが、ソフトウェアのエンジニアになりますので、どちらかというと後者の学習を進め、広く知識を習得していきたいかなと思っています。 参考資料 放送大学/コンピュータの動作と管理 全15回 日経XTECH/アセンブラで学ぶコンピュータ基礎のキソ 全5回 Arcanum/CASL2 キャッスルシミュレータ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS SAM ローカルでいろんな角度からhello worldする

やりたいこと サーバーレスな処理を実装するのに備えて、ひとまずSAMを使ってローカル環境にてブラウザやcurlコマンドでhello worldをしたいです。 $ sam --version SAM CLI, version 1.22.0 実装! sam initする sam initして、プロジェクトを新規作成します。 SAMからの質問に対して、下のように答えました。 template: AWS Quick Start Templates package: type: Zip (artifact is a zip uploaded to S3) runtime: ruby2.7 Project name [sam-app]: identify_user quick start application templates: Hello World Example ↓(参考)上記の詳細、質疑応答の全貌。 $ sam init Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 What package type would you like to use? 1 - Zip (artifact is a zip uploaded to S3) 2 - Image (artifact is an image uploaded to an ECR image repository) Package type: 1 Which runtime would you like to use? 1 - nodejs14.x 2 - python3.8 3 - ruby2.7 4 - go1.x 5 - java11 6 - dotnetcore3.1 7 - nodejs12.x 8 - nodejs10.x 9 - python3.7 10 - python3.6 11 - python2.7 12 - ruby2.5 13 - java8.al2 14 - java8 15 - dotnetcore2.1 Runtime: 3 Project name [sam-app]: identify_user AWS quick start application templates: 1 - Hello World Example 2 - Step Functions Sample App (Stock Trader) Template selection: 1 ----------------------- Generating application: ----------------------- Name: identify_user Runtime: ruby2.7 Dependency Manager: bundler Application Template: hello-world Output Directory: . Next steps can be found in the README file at ./identify_user/README.md Lambdaとtemplate.yamlを編集 Hello worldするためのLambdaとtemplate.yamlを整えます。 この後、AWS Rekognitionで顔認証するという個人的な事情で、LambdaはIdentifyUserFunctionという関数名にしました。 app.rb require 'json' def lambda_handler(event:, context:) message = 'hello world' { statusCode: 200, body: { message: message }.to_json } end template.yaml AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > identify_user Sample SAM Template for identify_user Globals: Function: Runtime: ruby2.7 Timeout: 30 Resources: IdentifyUserFunction: Type: AWS::Serverless::Function Properties: CodeUri: identify_user/ Handler: app.lambda_handler Runtime: ruby2.7 Events: IdentifyUser: Type: Api Properties: Path: /identify_user Method: get ローカルで動作確認 SAMのサーバーをローカルで起動します。(そう、サーバーレスなのに。) ポート番号は指定しないと3000になるのですが、僕の場合はRailsサーバーを3000で動かしていたので、-p 3001とオプションで3001を指定。 sam local start-api -p 3001 ブラウザで動作確認 ブラウザでhttp://127.0.0.1:3001/identify_userにアクセス。 { message: "hello world" } ↑うまく行くとブラウザにこう表示されます。 { message: "Missing Authentication Token" } ↑なんか間違えているとこんなのが帰ってきます。 例えばtemplate.yamlにてLambdaがmethod: postになってるとか curlで動作確認 curlとは?client for urlの略らしいです。 公式? https://curl.se/ e-words https://e-words.jp/w/CURL.html 次にcurlでパラメーターを渡してAPIを呼び出しても、きちんと動作するかを確認していきます。 が、まずはとりまパラーメーター無しでGETでcurlを実行してみます。 とりまパラメーター無しでcurlでhello world curl -X GET http://127.0.0.1:3001/identify_user // {"message":"hello world"}% きちんと返ってきました! 末尾の%がよくわからんが、まぁいいか。。 いよいよcurlでパラメーターを渡してhello world ここでは、メソッドをPOSTに変更します。 なんかよくわからないけど、自分のメモにunixtimeも残ってたのでそれも渡してみます。 app.rb require 'json' def lambda_handler(event:, context:) # 追加。パラーメーターを取得する params = JSON.parse(event['body'], symbolize_names: true) { statusCode: 200, body: { message: params[:message], unixtime: params[:unixtime] }.to_json } end template.yaml Resources: UpdateAttendanceResultFunction: Type: AWS::Serverless::Function Properties: (中略) Events: HelloWorld: Type: Api Properties: Path: /hello_world Method: post # ここをちゃんと変更! で、実行。 curl -X POST --data '{"message":"hello world", "unixtime": 1634532494}' http://127.0.0.1:3001/identify_user // {"message":"hello world","unixtime":1634532494}% きちんと返してくれています。 ちなみにここまでローカルで確認するだけなら、sam deployはもちろん、sam buildも必要ないです。 最後に これはサーバーレスにRekognitionに問い合わせをするという自分の過去の課題のSAM部分です。 Rekognition部分に関しては、弊社ブログにまとめました↓
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】グローバル変数を使わずにメソッドの外のスコープにあるローカル変数を使う方法

はじめに メソッドの外にある変数を利用したいがために、グローバル変数を使っているコードを見かけた。 今回はこういったコードに対してグローバル変数を使わずに済む方法を考える。 題材となるコード 題材となるのは以下のコードだ。 def test_Processor_runメソッドのタイムアウトの検証 p = Processor.new # 重い処理にする $process_time = 5 def p.process sleep $process_time end start_time = Time.now p.run(4) # 4秒でタイムアウトする end_time = Time.now # タイムアウトになるのは重い処理にかかる時間よりも早いはず assert((end_time - start_time) < $process_time) end Processor#runに指定したタイムアウトの時間で処理が終わるかどうかを確認しているようだ。 Processor#runからはProcessor#processが呼ばれるため、そのメソッドを特異メソッドで再定義し、長時間のsleepを入れることで擬似的に重い処理を行うようにしているようだ。 $process_timeというグローバル変数が使われており、今回はこのグローバル変数を使わないようにしたい。 なぜグローバル変数を使っているのか そもそもなぜグローバル変数を使っているのだろうか。 $process_timeをprocess_timeに変更してローカル変数にしてみよう。 def test_Processor_runメソッドのタイムアウトの検証 p = Processor.new # 重い処理にする process_time = 5 # グローバル変数をやめてローカル変数にした def p.process sleep process_time end start_time = Time.now p.run(4) # 4秒でタイムアウトする end_time = Time.now # タイムアウトになるのは重い処理にかかる時間よりも早いはず assert((end_time - start_time) < process_time) end これを実行すると以下のようなエラーが表示される。 undefined local variable or method `process_time' for #<Processor:0x0000000000a7b520> (NameError) 特異メソッド内で参照しているprocess_timeがメソッドとして解釈されてしまっている。 これはRubyではdefからendまでの間がスコープと解釈され、そのスコープ外のローカル変数を参照できないからだ。 以下のようなサンプルコードで確認してみよう。 my_var1 = "1" def sample_method my_var2 = "2" local_variables end p local_variables p sample_method 実行結果 [:my_var1] [:my_var2] Kernel#local_variablesを呼び出すことで、現在のスコープで定義されているローカル変数を確認することができる。 実行結果を見てわかる通り、sample_methodというメソッドのスコープではその外にあるmy_var1はローカル変数に存在しないことが分かる。 グローバル変数を使わずにメソッドの外にあるローカル変数を使う defを使ってしまうとそこからスコープが始まってしまうため、ローカル変数にアクセスできない。 こういう場合はdefine_methodを使ってブロックを使ってメソッドを定義するようにする。(今回の場合は特異メソッドを定義するため、define_singleton_methodを使う。) def test_Processorのrunメソッドのタイムアウトの検証 p = Processor.new # 重い処理にする process_time = 5 # グローバル変数をやめてローカル変数にした p.define_singleton_method(:process) do sleep process_time end start_time = Time.now p.run(4) # 4秒でタイムアウトする end_time = Time.now # 重い処理にかかる時間よりも早く終わるはず assert((end_time - start_time) < process_time) end こうすることで、processメソッドを定義する際はprocess_timeが定義されたスコープと同じスコープとなるため、ローカル変数のまま使用できる。 まとめ グローバル変数を使わずにメソッドの外のスコープにあるローカル変数を使う方法についてまとめた。 グローバル変数は無闇に使い出すと、どこで変更されているのか分からない保守性の低いコードができてしまうため、グローバル変数を使わない方法があるのであればそちらを採用してほしいと思う。 それではまた。 TomoProg 参考 メタプログラミング Ruby 第4章 ブロック
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む