хэш ruby ​​внутри хеша и переменная экземпляра с одноэлементным методом - не может получить доступ - PullRequest
0 голосов
/ 15 октября 2010
#!/usr/bin/env ruby

# this is the data I have
@data = {
  :student => {
    :id => '123477',
    :first_name => 'Lazlo',
    :last_name =>'Fortunatus',
    :email=>'Lazlo@fortunatus.org' 
  },
  :contact_info => {
    :telephone=>'1 415 222-2222',
    :address => '123 Main St',
    :city =>'Beverly Hills',
    :state=>'California',
    :zip_code=>90210,
    :social_security_number =>'111-11-1111' 
  }
} 

class Student  
  # not fully implemented - this is what I need help on.
  def get_id_original
    # I need this to return the value @data[:student][:id]
  end 

  def get_city_original
    # I need this to return the value @data[:contact_info][:city]
  end
end 

s = Student.new
# this is the original method
# how can I access the @data variable here I tried @data[:student][:id] doesnt work
# I realize that data is outside of the scope of this method. However, is there any way!
s.get_id_original

# My goal is to have a singleton method that acts exactly like get_id_original,
# but get_id_original doesn't work.
def s.id
  get_id_original
end

Ответы [ 6 ]

1 голос
/ 15 октября 2010

Это можно сделать!


Сначала это не сработало, потому что @data является атрибутом экземпляра объекта верхнего уровня, поэтому даже если Student является производным от Object, атрибут не находится в новом экземпляр.

Но вы можете передать self в s.id, и тогда единственное, что вам нужно добавить, - это метод доступа к атрибуту данных.

Однако, это немного сложно, потому что attr_reader и другие методы закрытого класса , поэтому вы не можете использовать их напрямую, и вы не можете (потому что это личное) просто сказать self.class.attr_reader, вы нужно открыть Object и сделать это ... с этими изменениями ваша программа работает ...

@data = { :student => { :id => '123477'} } 

class Student
end 
s = Student.new

def s.id o
   o.data[:student][:id]
  #how can I access the @data variable here I tried @data[:student][:id] doesnt work
  #I realize that data is outside of the scope of this method. However, is there any way!
end 

class Object
  attr_reader :data
end

puts s.id self
1 голос
/ 15 октября 2010

Прежде всего, ваш метод id действительно должен войти в класс.

Вы можете попробовать что-то вроде этого:

@data = { :student => { :id => '123477'} }

class Student
  attr_accessor :id

  def initialize(student)
    self.id = student[:id]
  end
end

s = Student.new(@data[:student])
puts s.id
0 голосов
/ 01 июня 2012

Этот код эквивалентен вашему собственному ответу с некоторыми улучшениями.(Только прочитав это, я понял, что вы пытались выполнить.) Чтобы избежать чрезмерной сложности, я старался избегать динамического генерирования имен методов.

#!/usr/bin/env ruby

require 'forwardable'

@data = {
  :student => {
    :id => '123477',
    :first_name => 'Lazlo',
    :last_name =>'Fortunatus',
    :email=>'Lazlo@fortunatus.org' 
  },
  :contact_info => {
    :telephone=>'1 415 222-2222',
    :address => '123 Main St',
    :city =>'Beverly Hills',
    :state=>'California',
    :zip_code=>90210,
    :social_security_number =>'111-11-1111' 
  }
} 

class ContactInfo
  def initialize( data )
    @data = data
  end
  def get_telephone_override
    @data[:telephone]
  end 
  def get_city_override
    @data[:city]
  end 

  def get_state_override
    @data[:state]
  end 

  def get_zip_code_override
    @data[:zip_code]
  end 

  def get_social_security_number_override
    @data[:social_security_number]
  end 
end

class Student  
  extend Forwardable # enables delegation (see ruby-doc.org's standard library)

  # delegates multiple methods to @contact_info, so they can be called on Student.
  # Remember to have the leading colon.
  def_delegators :@contact_info,
    :get_telephone_override,
    :get_city_override,
    :get_state_override,
    :get_zip_code_override,
    :get_social_security_number_override

  def initialize( data )
    @data = data[:student]
    # this is an example of composing objects to achieve separation of concerns.
    # we use delegators so ContactInfo methods are available on the Student instance.
    @contact_info = ContactInfo.new(data[:contact_info])
  end

  def get_id_override
    @data[:id]
  end 

  def get_first_name_override
    @data[:first_name]
  end 

  def get_last_name_override
    @data[:last_name]
  end 
  def get_email_override
    @data[:email]
  end 
end 

s = Student.new(@data)
class << s
  alias_method :id, :get_id_override
  alias_method :first_name, :get_first_name_override
  alias_method :last_name, :get_last_name_override
  alias_method :email, :get_email_override
  alias_method :contact_info, :get_telephone_override
  alias_method :city, :get_city_override
  alias_method :state, :get_state_override
  alias_method :zipcode, :get_zip_code_override
  alias_method :ssn, :get_social_security_number_override
end

puts s.id
puts s.first_name
puts s.last_name
puts s.email
puts s.contact_info
puts s.city
puts s.state
puts s.zipcode
puts s.ssn

Думаю, ваш вопрос был бы яснее, если быВы отправили код, как вы хотели, чтобы он работал.Я собираюсь предложить редактирование.

0 голосов
/ 01 июня 2012

Вы действительно должны передавать объект данных, чтобы он s имел собственную ссылку на него.

@data = { :student => { :id => '123477'} }

class Student
  attr_accessor :data
  def initialize(data)
    @data = data
  end
end

s = Student.new(@data)
# or you can use s.data = @data

def s.id
  @data[:student][:id]
end

puts s.id

Слово предостережения.Любые изменения в @data во внешней области будут отражены в s, поскольку обе @data переменные указывают на один и тот же объект в памяти.

Но что, если вы не хотите изменять ученика?учебный класс?Вы можете просто добавить средство доступа к s:

@data = { :student => { :id => '123477'} }

class Student
end

s = Student.new
class << s
  attr_accessor :data
end
def s.id
  @data[:student][:id]
end

s.data = @data
puts s.id
0 голосов
/ 15 октября 2010

#!/usr/bin/ruby
@data = { :student => { :id => '123477', :first_name => 'Lazlo', :last_name =>'Fortunatus', :email=>'Lazlo@fortunatus.org' }, :contact_info => { :telephone=>'1 415 222-2222', :address => '123 Main St', :city =>'Beverly Hills', :state=>'California', :zip_code=>90210, :social_security_number =>'111-11-1111' } } 

 class Student  
    def initialize( data )
        @data = data
    end

    def get_id_override
        @data[:student][:id]
    end 

    def get_first_name_override
        @data[:student][:first_name]
    end 

    def get_last_name_override
        @data[:student][:last_name]
    end 
        def get_email_override
        @data[:student][:email]
    end 

    def get_telephone_override
        @data[:contact_info][:telephone]
    end 
        def get_city_override
        @data[:contact_info][:city]
    end 

    def get_state_override
        @data[:contact_info][:state]
    end 

    def get_zip_code_override
        @data[:contact_info][:zip_code]
    end 

    def get_social_security_number_override
        @data[:contact_info][:social_security_number]
    end 




end 

s = Student.new(@data)

def s.id
    get_id_override
end 
def s.first_name
    get_first_name_override
end 

def s.last_name
    get_last_name_override
end 

def s.email
    get_email_override
end 

def s.contact_info
    get_telephone_override
end 

def s.city
    get_city_override
end

def s.state
    get_state_override
end

def s.zipcode
    get_zip_code_override
end

def s.ssn
    get_social_security_number_override
end

puts s.id
puts s.first_name
puts s.last_name
puts s.email
puts s.contact_info
puts s.city
puts s.state
puts s.zipcode
puts s.ssn

Вот ответ после некоторой работы.У кого-нибудь есть лучший ответ, чем у меня, дайте мне знать.

0 голосов
/ 15 октября 2010

Если вы определяете переменную экземпляра (с префиксом "@") вне определения класса?

Кроме того, вы не можете определить метод с точкой в ​​имени

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...