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

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

ただいまの
回答率

88.61%

module内で使用しているインスタンス変数を、継承先のクラスメソッドで使用したい。

受付中

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 4,826

qaz3330

score 113

次のようなmoduleとクラスがあります。

module Hoge
  class_methods do
    def hoge
      @piyo = "piyo" 
      Sample.create 
    end
  end
end



class Sample < ActiveRecord::Base
  after_save :save_sample
  include Hoge

  def save_sample
    if @piyo
      puts "ok"
    end
  end
end


Sample.hoge

Hogeというモジュールを作成しており、このモジュール内で、Sampleクラスのインスタンスを作成する処理が入ります。
また、Sampleクラスでは、after_saveを使用し、save後のメソッドを用意しております。

今回、Hogeというモジュール内で、Sampleクラスの保存を行った後に実行されるsave_sampleメソッド内にて
@piyoというインスタンス変数がnilになるため困っております。

Hogeモジュール内では、@piyoのインスタンス変数に格納しているものの、こういうケースでは、できないものでしょうか?

尚、実行においては、以下のように行っております。

Sample.hoge

宜しくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

0

(mix-inで作ったものかどうかにかかわらず)クラスメソッドからインスタンス変数を参照する場合、それはクラスそのもののインスタンス変数(クラスインスタンス変数)となってしまって、インスタンスメソッドからその値を読み書きすることはできません。

ということで、方法は2通り考えられます。

  1. @piyoをインスタンスごとに持たせることが必要な場合、hoge自体もインスタンスメソッドとして作る
  2. @piyoはクラスに1つで、それを各インスタンスから参照したい場合、クラス側にcattr_accessorを入れて、インスタンスメソッドからはアクセサ経由で参照する

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

rubyではインスタンス変数は代入した時に初めて生成される。
また基本的にインスタンス変数は継承されない。
したがってクラス変数にして継承させる。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

このような場合には一度newでオブジェクトをを作成してから、instance_eval内でインスタンス変数をセットし、その後saveする方法もあります。
その場合は以下のようになります。

module Hoge
  extend ActiveSupport::Concern

  class_methods do
    def hoge
      instance = self.new
      instance.instance_eval{ @piyo = "piyo" } # インスタンス変数をセット
      instance.save
    end
  end
end

また、instance_evalを使わずにこのような方法でもいいかもしれません。

module Hoge
  extend ActiveSupport::Concern

  class_methods do
    def hoge
      instance = self.new
      instance.set_default_piyo # インスタンスうにセットするメソッドを呼ぶ
      instance.save
    end
  end

  included do
    def set_default_piyo
      @piyo = "piyo"
    end
  end
end

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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