🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

1回答

812閲覧

Railsで、Rubyプログラムをバッククォートを用いて実行した時の問題

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2019/12/11 12:21

##開発環境
macOS(catalina version10.15.1)
Ruby 2.4.1
Ruby on Rails 5.2

##背景
入力画面の入力値に依存して、publicディレクトリ以下にあるRubyプログラムを条件分岐して実行し、その結果を取得してインスタンス変数に代入し、結果画面に表示するということをやっています。

##わからないこと
コントローラーで外部コマンドからRubyプログラムを実行する際に、実行した結果がインスタンス変数に代入されておらず、原因がわからないこと。なお、質問しながら自分でも調査を進めています。
今回、確かめているコードは以下の条件分岐以下の処理になります。

Ruby

1 if user_location == "x駅・y駅" && time_3 != 6 && time_3 != 7;

##ソースコード

Ruby

1def result 2 #日時、曜日関係 3 time = Time.now 4 time_1 = time.hour #Ex.0,1,2,3,4,5,/~/,19,20,21,22,23 5 time_2 = time.min #Ex,0,1,2,3,4,/~/55,56,57,58,59 6 time_3 = time.wday#[1:Mon,2:Tue,3:Wed,4:Thurs,5:Fri,6:Sat,7:Sun] 7 @time_4 = time_1.to_s + ':' + time_2.to_s 8 9 #paramsから取得する現在地情報、つまり、駅名 10 user_location = params[:present_location] 11 if user_location == "x駅・y駅" && time_3 != 6 && time_3 != 7; 12 @result = `ruby /Users/~省略~/public/test.rb #{time_1} #{time_2}` 13 p "--------------------------------------" 14 p $? 15 p "--------------------------------------" 16 #↑上記コマンドが正常に実行されているかを確認するために出力させた。 17 18 19 elsif user_location == "z駅" && time_3 != 6 && time_3 != 7; 20 @result = `ruby /Users/~省略~/public/test_2.rb #{time_1} #{time_2}` 21 else; 22 @result = "平日以外は本アプリケーションの適応範囲外となります。" 23 end 24 25 end

##まず、コマンドは正常に動いているのか??

terminal

1p $? 2#<Process::Status: pid 12064 exit 1>

参照:Ruby 2.6.0 リファレンスマニュアル ライブラリ一覧 組み込みライブラリ Process::Statusクラス
上記によると、出力されたものは、どうやら以下のようなものに合致しそう・・・?

[引用]

正常終了の時 <Process::Status: pid=18262,exited(nnn)>

exitが過去形ではないのが気になるが・・まあ、プログラムは正常に動いていそうだ。
と判断していますが、これが間違いであればご指摘願います。
→確認方法がこれでは不十分!であるとかであればバシバシご指摘ください。

##「まず、コマンドは動いているのか?」が正しいと仮定する。
Rails側の処理に問題がないと仮定するのであれば、次に考えられる原因は、プログラムの中身で返しているものがおかしい可能性が考えられる。

#####動かしているプログラムのソースコード

Ruby

1can_take = [] #試しているのは、空の状態 2can_take_2 = [] #同様に空の状態 3 if can_take.empty? && can_take_2.empty?; 4 return '今日のバスはもうありません。' 5 elsif !can_take.empty? && can_take_2.empty?; 6 return 'x駅発大学行きバスダイヤです。y駅発はもうありません。',can_take_takasaka 7 elsif !can_take.empty? && !can_take_2.empty?; 8 return can_take_takasaka,can_take_kita_sakado 9 else; 10 return takasaka_daiya,kita_sakado_daiya 11 end

上記Rubyプログラムソースコードの、

Ruby

1return '今日のバスはもうありません。'

が、コントローラーの、

Ruby

1@result = `ruby /Users/~省略~/public/test.rb #{time_1} #{time_2}`

@resultに入っていて欲しい。が、入っていない(泣)ので、returnについてググることを決定する。

##最後に
ここまでの過程では、returnの使い方に問題があるのではないか?というのが論理的に原因となりそうである。しかし、returnについてググっても情報収集に時間がかかりそう、且つ、ここまでのデバッグで少々疲れてしまったので、こちらでお力を貸していただければと思います。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

exit 1

なので、エラーで終了しています。

Ruby

1@result = `ruby /Users/~省略~/public/test.rb #{time_1} #{time_2} 2>&1`

にすると、エラーメッセージが変数に入ります。

また、プログラムを書くときは、わからないなりに何とか書いて、全部まとめてえいやっと動かすのは、期待通りにいかないときに、調べるのが大変です。
分からない部分は、事前に簡単なプログラムで確認してから、目的のプログラムに組み込みましょう。

あなたの場合は、バッククォートによる実行とreturnの関係がわかっていないので、まずは、

Ruby

1x = `ruby -e "return '結果'"` 2p x

とやってみれば、あなたの理解が間違っていることがわかります。
正しくは、こうです。

Ruby

1x = `ruby -e "print '結果'"` 2p x

そもそも、なぜ外部コマンドを実行してその結果を取り込む必要があるのでしょうか?
Ruby同士なら普通に実行すればいいのでは?

投稿2019/12/11 13:23

otn

総合スコア85882

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/12/11 14:52

>exit 1 これはエラーを示す内容だったのですね。初めて知りました。 >また、プログラムを書くときは、わからないなりに何とか書いて、全部まとめてえいやっと動かすのは、期待通りにいか>ないときに、調べるのが大変です。 >分からない部分は、事前に簡単なプログラムで確認してから、目的のプログラムに組み込みましょう。 おっしゃる通りです。組み込む前に、プログラム単位では切り分けてテストしてからpublic/以下に持ってきたのですが、returnのテストはせずに、できるだろ?という思い込みでやってしまいました。反省です。 >あなたの場合は、バッククォートによる実行とreturnの関係がわかっていないので、まずは、とやってみれば、あなた >の理解が間違っていることがわかります。正しくは、こうです。 なるほどです。外部コマンドは、printしたものについてしか受け取れないのですね。 https://docs.ruby-lang.org/ja/latest/doc/spec=2frubycmd.html 何故、コマンドに-eをつけるのか気になって調べてみたのですが、以下の説明があまり理解できないです。 「コマンドラインからスクリプトを指定します。-eオプションを付けた時には引数からスクリプトファイル名を取りません。」 今回のように、外部コマンドでファイルを絶対パスで指定して実行する場合(=ruby フルパス)も、フルパス はスクリプトに該当するのでしょうか?それとも、スクリプトというのは「print "結果"」のような記述のみを指しているのでしょうか? >そもそも、なぜ外部コマンドを実行してその結果を取り込む必要があるのでしょうか? >Ruby同士なら普通に実行すればいいのでは? 外部コマンドとして実行するのは、コントローラーに冗長なプログラムを載せるのはよくないのでは?と考えたためです。 Ruby同士なら普通に実行すればいいのでは?というアドバイスに対する回答になっていれば良いですが、違った場合はご指摘いただけると嬉しいです。
otn

2019/12/11 15:04

-e ですが、 Rubyの実行方法は、たとえば、10.times{|i| puts i} という内容のファイル foo を作って、 ruby foo とするのが普通の方法です。 ファイルを作らないで済まそうとすると、 ruby -e "10.times{|i| puts i}" のようにすると、同じ結果が得られます。とはいえ、複雑な処理を1行で書くのは難しい(見にくい)ので、短い場合だけですが(システム的には長くても実行できるが)。 > コントローラーに冗長なプログラムを載せるのはよくないのでは? ここはよく事情がわかりません。 外部コマンドにするのは「絶対無し」ではないですが、質問文のコードのような単純なものだと、外部にする理由が無いと思います。
退会済みユーザー

退会済みユーザー

2019/12/11 15:12

-eの説明について納得しました。件のサイトでは、短いプログラムのことをどうやらスクリプトと呼称しているようですね。 >ここはよく事情がわかりません。 >外部コマンドにするのは「絶対無し」ではないですが、質問文のコードのような単純なものだと、外部にする理由が無いと思います。 この部分については、私の説明不足です。質問文に掲載した量よりもさらに多いコードが、can_takeとcan_take_2のリストを作成するために存在しています。総数で、120行程度です。
otn

2019/12/11 15:19

外部コマンドにすることで、何が良くなるのかわかりません。 まあ、駄目というわけではないですが。
退会済みユーザー

退会済みユーザー

2019/12/11 15:25 編集

コントローラーに直接書く必要がなくて、見やすくなる程度しか答えられないです。 →これって大して嬉しくないですか?一応、ユーザーの入力値によって実行するプログラムが分かれているので、その分岐もやりやすいなあと感じて外部コマンドにしたのですが、、 しかし、確かにこの程度で詰まってしまうくらいであれば、同じコントローラー内にメソッドとして書いてしまうという方法の方がアリかもしれません。(検討はずれだったら恥ずかしいですが)
otn

2019/12/11 15:33

ファイルを分ければいいだけでは?
退会済みユーザー

退会済みユーザー

2019/12/11 15:39 編集

「ファイルを分ける」と「外部コマンドを利用して、分けたファイルを実行する」が同義だと捉えてしまっています、、、 具体的にお願いします。私の方で提供できていない情報はなんでも提供いたしますので、教えてください!
otn

2019/12/11 15:42

別ファイルに、 class FOO def self.foo   ~~~ return "結果" end end と書いて、それをrequireして、 @result = Foo.foo とか。
退会済みユーザー

退会済みユーザー

2019/12/11 15:47

ありがとうございます。 あー、require!使えばいいのか! 確かに、その、通り、です。
退会済みユーザー

退会済みユーザー

2019/12/11 15:47

低レベルで申し訳ないです。精進します。
asm

2019/12/11 16:49

外部コマンドにするとだめな理由として rubyインタプリタの起動には相応のコスト(メモリ・CPUリソースおよび時間)が必要になるので避けられるならば避けたいですね。 確か、インタプリタ言語の中でもrubyは最重量級だったはず
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問