2017-11-07 6 views
1

私のすべての配列をループして、私のjson idの値を真のメソッドを渡すものと比較しようとしています。私はそれをしようとする場合でも、私はエラーを取得する:インスタンス変数でそれぞれを使用するとエラーが発生する

undefined method 'each' for nil:NilClass

heroe.rb

require 'json' 

class Hero 
    attr_accessor :hp 

    json = File.read('skill_list.json') 
    @skills = JSON.parse(json) 

    def initialize(name, level, job, hp, strength) 
    @name = name 
    @level = level.to_i 
    @job = job 
    @hp = hp.to_i 
    @strength = strength.to_i 
    end 

    def get_name 
    @name 
    end 

    def profile 
    puts "#{@name} level is #{@level} and hp: #{@hp}" 
    end 

    def attack(id) 
    @skills.each do |s| 
     if s['id'] == id 
     puts true 
     else 
     puts false 
     end 
    end 
    end 

    def get_hp 
    puts @hp 
    end 
end 

skill_list.json

[ 
    { 
    "id": 0, 
    "name": "Double Slash", 
    "element": "fighter", 
    "amp": 1.1, 
    "mp": 1 
    }, { 
    "id": 1, 
    "name": "Slash", 
    "element": "fighter", 
    "amp": 1, 
    "mp": 1 
    }, { 
    "id": 2, 
    "name": "Falling Ashes", 
    "element": "psychic", 
    "amp": 1, 
    "mp": 1 
    } 
] 

その後、私は攻撃を持つオブジェクトと呼ばれます方法:hero.attack(1)

私はちょっとここに詰まっていますpは高く評価されます〜

答えて

0

主な問題は、@skillsがない任意のインスタンスで、そのクラスのプロパティになり、クラスのコンテキスト内で宣言されていることです。インスタンスメソッドには、これとは無関係の独自のコンテキストがあります。 MyClass.aMyClass#aのようなものは異なるものですが、ここでも同じです。これを修正

は、単に怠惰な初期化子をクラスメソッドに一度、そのデータをロードする場合です:

class Hero 
    attr_accessor :name 
    attr_accessor :hp 
    attr_accessor :level 
    attr_accessor :strength 

    def self.skills 
    @skills ||= JSON.parse(File.open('skill_list.json')) 
    end 

    def initialize(name, level, job, hp, strength) 
    @name = name 
    @level = level.to_i 
    @job = job 
    @hp = hp.to_i 
    @strength = strength.to_i 
    end 

    def profile 
    puts "#{name} level is #{level} and hp: #{hp}" 
    end 

    def attack(id) 
    self.class.skills.each do |s| 
     if s['id'] == id 
     puts true 
     else 
     puts false 
     end 
    end 
    end 
end 

ます。またhp正しくattr_accessorを使用したが、その後は非常に非ルビーを行くと定義しています完全に無関係なget_hpの方法である。あなたは、すべてのプロパティのアクセサを使用して、それと他のget_メソッドを取り除くことができます。

+0

ありがとうございました!これはうまくいった! || =何を意味するのか説明できますか?初めて私はこれをルビーで見たことがあります。 – Blinhawk

+0

'x || = y'は' x = x ||と同じです。 'x'がすでに非*論理的 - 偽*値でない限り' 'y''を' 'x 'に割り当てるのが便利な方法です。つまり、 'x'が既に初期化されていない場合にのみ' x'を初期化します。これは、ブロックが1回だけ実行されることを意図しているため、「遅延ロード」と呼ばれます。スレッドが関与している場合、これは難解ですが、自動ロックを使用して同じ原則を適用することができます。 – tadman

+0

'&& ='のような変種もありますが、これも同じ拡張の原則を使って動作しますが、珍しいことに、 'x'に割り当てたいのは、すでに割り当てられている場合のみです。プロダクションコードを参照してください。 '+ ='、 ' - ='、 '* ='と '/ ='がより一般的ですが、 'x + = 1'は' x = x + 1'と同じです。 – tadman

0

インスタンス変数は、クラス内だけでなく、initializeメソッドまたは他のインスタンスメソッドで宣言する必要があるためです。 私はの初期化メソッドの中に次のものを置くべきだと思います。それは一度だけ呼び出されるように

json = File.read('skill_list.json') 
    @skills = JSON.parse(json) 

または動きが代わりに一定のスキルに@skills。

class Hero 
    attr_accessor :hp 

    SKILLS = JSON.parse(File.read('skill_list.json')) 

    # ... 
end 
関連する問題