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

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

ただいまの
回答率

88.04%

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,116

score 58

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

#app/controllers/events_controller.rb
  def create
    @event = Event.new()
    @event.probe_data_investigate
    send_data
  end

    def send_data
      Spark.new().webex_rooms_get
      entry = Entry.new()
      entry.entry_data_in_txt
      entry.exit_data_in_txt
      entry.webex_send_txt

      entry.entry_exit_situation_update
      EntryLog.new().entry_exit_log_save
    end


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

 回答から追記

def create
  @apple = new_data
  @orenge = before_data
  @bunana = max_data
   ・
   ・
   ・
end


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

#app/models/entry.rb
def entry_data_in_txt
     $entry_txt = ""
     @apple.each do |mac,time|
       personal_info = []
       personal_info = @orenge[mac].map{|k,v| v.present? ? "┃     ・#{k} : #{v}" : nil}.sort
       if personal_info.empty?
           $entry_txt << "┣━#{mac}さんが入室しました(#{time})\n"
       else
           personal_info.map!{|x| x.split(",").join("\n┃               ")}
           $entry_txt << "┣━#{mac}さんが入室しました(#{time})\n#{personal_info.join("\n")}\n"
       end
     end
end

#app/controllers/events_controller.rb
  def create
    @event = Event.new(data: params[:data])
    $timenow = Time.now

    respond_to do |format|
      if @event.save
        format.html { redirect_to @event, notice: 'Event was successfully created.' }
        format.json { render :show, status: :created, location: @event }
      else
        format.html { render :new }
        format.json { render json: @event.errors, status: :unprocessable_entity }
      end
    end

    Entry.new().probe_data_investigate

    Spark.new().webex_rooms_get
    entry = Entry.new()
    entry.entry_data_in_txt
    entry.exit_data_in_txt
    entry.webex_send_txt

    entry.entry_exit_situation_update
    EntryLog.new().entry_exit_log_save
  end


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


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

#config/schedule.rb
rails_env = ENV['RAILS_ENV'] || :development
set :output, 'log/crontab.log'
set :environment, rails_env

every 30.minute do
  runner "Tasks::PersonalLogArrange.execute"
end


# webex/lib/tasks/personal_log_arrange.rb
require 'webex/app/models/personal_log'
class Tasks::PersonalLogArrange
  def self.execute
    PersonalLog.new.arrange
  end
end

#app/models/personal_log.rb
    def arrange
      array = Array.new
      personal_log = PersonalLog.all
      personal_log.find_each do |x|
          hash = Hash.new
          begin
             test = JSON.parse(x.decrypted_data)
          rescue => error
             test = JSON.parse(x.data)
          end
          if test.keys.include?("uid")
               test["uid"] = "#{test["uid"]}(#{x.provider})"
          end
          hash[x.macaddr] = test
          array.push(hash)
      end
      @new_data = array.each_with_object(Hash.new{|h,k|h[k] = Hash.new}){|it,memo|
          it.each{|mac,val|
          memo[mac].merge!(val){|_,s,o| s + ',' + o}
          }
      }
      @new_data.transform_values!{|val| val.transform_values{|v| v.to_s.split(',').uniq.join(',')}}
      puts @new_data   
    end

    def export
      {new_data: @new_data}
    end

    attr_reader :new_data

#app/controllers/events_controller.rb

    def send_data
      entry = Entry.new()
      event = Event.new
      event.probe_data_investigate
      data = event.export

      #追加したコード
      personal_log = PersonalLog.new
      new_data = personal_log.export
      data.merge!(new_data)

      entry.import(data)
      Spark.new().webex_rooms_get
      entry.entry_data_in_txt
      entry.exit_data_in_txt
      entry.webex_send_txt

      entry.entry_exit_situation_update
      entry.entry_exit_log_save
    end

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

果たして、

    @event.probe_data_investigate
    send_data

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

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

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


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

一般的には

  def create
    @event = Event.new()
    data = @event.probe_data_investigate
    send_data data
  end

  def send_data(data)
    Spark.new().webex_rooms_get
    entry = Entry.new()
    ## ここらでなんらかの方法でdataを渡す ##
    # 例: entry.push data
    # 例: entry = Entry.new(data)
    entry.entry_data_in_txt
    entry.exit_data_in_txt
    entry.webex_send_txt

    entry.entry_exit_situation_update
    EntryLog.new().entry_exit_log_save
  end


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

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


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


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

class Event
  def create
    @apple = "りんご"
  end
  # データ取り出しメソッド
  def export
    {apple: @apple}
  end

  # @appleを外部から取り出せるようにする
  attr_reader :apple
end

class Entry
  # 受け取り側
  def push(data)
    puts data[:apple]
  end
  def push_model(evt)
    puts evt.apple
  end
end

# 以下、コントローラーとして
event = Event.new
event.create
entry = Entry.new

# データ取り出しメソッドを作る
data = event.export
entry.push(data)

# いっそモデルのインスタンスごと渡してしまうのも手
entry.push_model(event)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/19 19:24

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

    キャンセル

  • 2018/09/20 18:45

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

    キャンセル

  • 2018/09/21 02:03

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

    キャンセル

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

  • ただいまの回答率 88.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る