質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

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

Ruby

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

Q&A

解決済

1回答

428閲覧

Rails5で変数のスコープ理解が曖昧で呼び出しが出来ない

kozica

総合スコア58

Ruby on Rails 5

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

Ruby

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

0グッド

0クリップ

投稿2018/09/13 09:08

編集2018/09/20 09:53

Rails5で
app/models/event.rb
内のメソッドで変数を定義しました。
それをコントローラー内で下記のように使用したいです。

ruby

1#app/controllers/events_controller.rb 2 def create 3 @event = Event.new() 4 @event.probe_data_investigate 5 send_data 6 end 7 8 def send_data 9 Spark.new().webex_rooms_get 10 entry = Entry.new() 11 entry.entry_data_in_txt 12 entry.exit_data_in_txt 13 entry.webex_send_txt 14 15 entry.entry_exit_situation_update 16 EntryLog.new().entry_exit_log_save 17 end 18

上記において、
probe_data_investigateメソッドで色々は変数を定義しております
その定義した変数をsend_dataメソッド内のEntryモデルのメソッドで使用したいのですが、
それが出来ません。
グローバル変数は使わずに済む方法はないでしょうか?

回答から追記

ruby

1def create 2 @apple = new_data 3 @orenge = before_data 4 @bunana = max_data 5   ・ 6   ・ 7   ・ 8end

上記のような@appleなどの変数を下記のメソッド内で使用したいです。

ruby

1#app/models/entry.rb 2def entry_data_in_txt 3 $entry_txt = "" 4 @apple.each do |mac,time| 5 personal_info = [] 6 personal_info = @orenge[mac].map{|k,v| v.present? ? "┃ ・#{k} : #{v}" : nil}.sort 7 if personal_info.empty? 8 $entry_txt << "┣━#{mac}さんが入室しました(#{time})\n" 9 else 10 personal_info.map!{|x| x.split(",").join("\n┃ ")} 11 $entry_txt << "┣━#{mac}さんが入室しました(#{time})\n#{personal_info.join("\n")}\n" 12 end 13 end 14end 15 16#app/controllers/events_controller.rb 17 def create 18 @event = Event.new(data: params[:data]) 19 $timenow = Time.now 20 21 respond_to do |format| 22 if @event.save 23 format.html { redirect_to @event, notice: 'Event was successfully created.' } 24 format.json { render :show, status: :created, location: @event } 25 else 26 format.html { render :new } 27 format.json { render json: @event.errors, status: :unprocessable_entity } 28 end 29 end 30 31 Entry.new().probe_data_investigate 32 33 Spark.new().webex_rooms_get 34 entry = Entry.new() 35 entry.entry_data_in_txt 36 entry.exit_data_in_txt 37 entry.webex_send_txt 38 39 entry.entry_exit_situation_update 40 EntryLog.new().entry_exit_log_save 41 end 42 43

仮に別モデルの定義したものをすべてmodels/entry.rbに移動させてもコントローラーからモデルメソッド呼び出しなのでインスタンス変数でも出来ませんでした。
(コントローラーから呼び出しだからインスタンス変数では使えないからかな??)
別モデル内の変数なので、やっぱりグローバル変数が適切なような気がしてきてますがいかがでしょうか?


追記 バッチ処理した際の変数をモデルで使用したい

ruby

1#config/schedule.rb 2rails_env = ENV['RAILS_ENV'] || :development 3set :output, 'log/crontab.log' 4set :environment, rails_env 5 6every 30.minute do 7 runner "Tasks::PersonalLogArrange.execute" 8end 9 10 11# webex/lib/tasks/personal_log_arrange.rb 12require 'webex/app/models/personal_log' 13class Tasks::PersonalLogArrange 14 def self.execute 15 PersonalLog.new.arrange 16 end 17end 18 19#app/models/personal_log.rb 20 def arrange 21 array = Array.new 22 personal_log = PersonalLog.all 23 personal_log.find_each do |x| 24 hash = Hash.new 25 begin 26 test = JSON.parse(x.decrypted_data) 27 rescue => error 28 test = JSON.parse(x.data) 29 end 30 if test.keys.include?("uid") 31 test["uid"] = "#{test["uid"]}(#{x.provider})" 32 end 33 hash[x.macaddr] = test 34 array.push(hash) 35 end 36 @new_data = array.each_with_object(Hash.new{|h,k|h[k] = Hash.new}){|it,memo| 37 it.each{|mac,val| 38 memo[mac].merge!(val){|_,s,o| s + ',' + o} 39 } 40 } 41 @new_data.transform_values!{|val| val.transform_values{|v| v.to_s.split(',').uniq.join(',')}} 42 puts @new_data 43 end 44 45 def export 46 {new_data: @new_data} 47 end 48 49 attr_reader :new_data 50 51#app/controllers/events_controller.rb 52 53 def send_data 54 entry = Entry.new() 55 event = Event.new 56 event.probe_data_investigate 57 data = event.export 58 59 #追加したコード 60 personal_log = PersonalLog.new 61 new_data = personal_log.export 62 data.merge!(new_data) 63 64 entry.import(data) 65 Spark.new().webex_rooms_get 66 entry.entry_data_in_txt 67 entry.exit_data_in_txt 68 entry.webex_send_txt 69 70 entry.entry_exit_situation_update 71 entry.entry_exit_log_save 72 end 73

バッチ処理の際にインスタンス変数を渡しようにすればよいと思うのですがわかりますでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

果たして、

rb

1 @event.probe_data_investigate 2 send_data

から、send_dataを呼ぶ前には
@event.probe_data_investigateを呼ぶ必要があるなんて制約をこのコードから読み取れますか?

1週間後・1ヶ月後の自分に「読み解け」と言えますか?

多分3日後あたりで既に怪しいと思いますよ。


とりあえず、このコードの部分に手を加えずにやるならばEntryクラスのクラス変数を利用する案があります。
上述したように全くオススメはしませんので解説はしません。

一般的には

rb

1 def create 2 @event = Event.new() 3 data = @event.probe_data_investigate 4 send_data data 5 end 6 7 def send_data(data) 8 Spark.new().webex_rooms_get 9 entry = Entry.new() 10 ## ここらでなんらかの方法でdataを渡す ## 11 # 例: entry.push data 12 # 例: entry = Entry.new(data) 13 entry.entry_data_in_txt 14 entry.exit_data_in_txt 15 entry.webex_send_txt 16 17 entry.entry_exit_situation_update 18 EntryLog.new().entry_exit_log_save 19 end

のようにprobe_data_investigateメソッドに戻り値を持たせます。

rb

1def probe_data_investigate 2 return {name: "namae", hoge: [:foo, :bar]} 3end

のように、ハッシュで返せば複数の値を返す事ができます。


とりあえずシンプルな例にしてみたつもり

rb

1class Event 2 def create 3 @apple = "りんご" 4 end 5 # データ取り出しメソッド 6 def export 7 {apple: @apple} 8 end 9 10 # @appleを外部から取り出せるようにする 11 attr_reader :apple 12end 13 14class Entry 15 # 受け取り側 16 def push(data) 17 puts data[:apple] 18 end 19 def push_model(evt) 20 puts evt.apple 21 end 22end 23 24# 以下、コントローラーとして 25event = Event.new 26event.create 27entry = Entry.new 28 29# データ取り出しメソッドを作る 30data = event.export 31entry.push(data) 32 33# いっそモデルのインスタンスごと渡してしまうのも手 34entry.push_model(event)

投稿2018/09/13 22:30

編集2018/09/19 05:04
asm

総合スコア15147

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

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

kozica

2018/09/18 08:35

制約をコードから読み取れるか?という所はものすごく納得しました! 自分はまだコードの可読性を高めるためにどのようにコーディングすればよいかまだしっかりわかっていないのでこの指摘はすごく勉強になります。 回答で、なんらかの方法でdataを渡すとありますが、ここがわからないです、、、 記載している通りmodels/event.rbのメソッド内で定義した変数をmodels/entry.rbで使用したいです。 上記では単純にdataとなってますが、実際には投稿追記のように@apple,@orenge,@bunanaなどいくつものインスタンス変数を使いたいです。
asm

2018/09/18 09:05

Eventのメソッドから return {apple: @apple, orenge: @orenge, bunana: @bunana} な感じで必要なインスタンス変数をハッシュに格納して返します。 コントローラーは受け取ったものをローカル変数に格納してEntryモデルのメソッドに渡します。
kozica

2018/09/19 02:02

やってみた所、インスタンス変数の中身が空になっているようです。 本来returnで返したら、空にはならないものなのでしょうか?
kozica

2018/09/19 09:07

非常にわかりやすく書いて頂きありがとうございます 実行したところエラーがでてしまいました。 おそらく、この状態だとEntryクラスのメソッド内で、puts @appleが実行できない。つまり@appleは使えないようです。 puts @appleができるようにすることは可能でしょうか?
kozica

2018/09/19 09:58

現状ですと、 puts @apple をするためには puts @data[:apple] とpush(data)メソッド内で@data = dataと定義して上記のように書けばうまくいきますが、インスタンス全部で@data[:xxx]とするのも見栄えがよくないので改善策はないでしょうか?
asm

2018/09/19 09:59

手っ取り早いのは def push(data) @apple = data[:apple] end こんなん 大量にあってめんどくさい場合は def import(data) data.each{|name, val| instance_variable_set "@#{name}", val } end
asm

2018/09/19 10:01

後者の場合は、exportの方を { "@apple": @apple} みたいにして def import(data) data.each{|name, val| instance_variable_set name, val } end でもよい
kozica

2018/09/19 10:21

後者で puts @apple をしましたが、空になってました、、、 これは後者のを実装しても puts @appleで使用できるようになるということではないということでしょうか?
kozica

2018/09/19 10:24

あ、すいません。 勘違いでちゃんとできてました!!
kozica

2018/09/20 09:45

ちなみになんですが、今バッチ処理をしていてそのインスタンス変数もEntryモデル内で使用したい場合はどのように書けばいいでしょうか? 同じ用に書いてやってみましたが、うまくいきません。 記述内容は投稿に追記しております。
asm

2018/09/20 17:03

どこからどこに渡したいのか皆目見当がつきません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問