Ruby должно позволять назначать параметры конфигурации - PullRequest
2 голосов
/ 11 апреля 2020

Я пытаюсь реализовать класс, который использует ha sh в качестве конструктора как часть моего Ruby обучения.

Это то, что я имею до сих пор:

class Example

  attr_accessor :bar, :baz, :some

  def initialize args
     args.each do |k,v|
       instance_variable_set("@#{k}", v) unless v.nil?
     end
  end


  my_hash = Example.new(foo: {bar: "x", "baz" => "y"}, "some" => "other")

end

Вышеприведенное должно считывать значения следующим образом:

my_hash.foo.bar
=> "x"
my_hash.foo.baz
=> "y"
my_hash.some
=> "other"
my_hash.foo.class
=> Example
my_hash.unknown
=> nil

, а также переопределять значения и назначать новые. Однако после того, как я реализовал это, очевидно, этот фрагмент кода здесь:

def initialize args
         args.each do |k,v|
           instance_variable_set("@#{k}", v) unless v.nil?
         end
      end

не годится, потому что он не позволяет присваивать параметры? Не уверен, что это значит.

Это один из тестов, которые я не проходил

it 'should store my_hash from hash passed through constructor' do
    my_hash = Example.new({p1: 'test', 'p2' => {'p3' => [10, 12]}, p4: {}})

    expect(my_hash.p1).to eq('test')
    expect(my_hash.p2.p3).to eq([10, 12])
    expect(my_hash.p2).to be_a(Example)
  end

И тест, который не прошел мой метод initialize, таков:

it 'should allow assigning config params' do
    my_hash = Example.new

    my_hash.some = 'test'
    my_hash.other = 'test2'
    my_hash.yet_one_more = {}
    my_hash.yet_one_more.test = 'test'

    expect(my_hash.some).to eq('test')
    expect(my_hash.other).to eq('test2')
    expect(my_hash.yet_one_more.test).to eq('test')
  end

1 Ответ

1 голос
/ 11 апреля 2020

В вашем примере вы передаете ha sh методу initialize, а затем перебираете новую переменную экземпляра для каждой пары ключ-значение. Учитывая это, единственные переменные экземпляра, которые вы создаете:

@foo = {bar: "x", "baz" => "y"}
@some = 'other'

Поэтому вам нужны только средства доступа к атрибутам для указанных переменных.

# this allows you to access to whatever `foo` and `some` are holding,
# including nested properties.
attr_accessor :foo, :some

О, и вы получаете ошибку, потому что вы пытаетесь создать переменную my_ha sh внутри класса (вы пытаетесь создать экземпляр класса внутри его собственного определения). Вот как бы вы это определили:

class Example

  attr_accessor :foo, :some

  def initialize args
    args.each do |k, v|
      instance_variable_set("@#{k}", v) unless v.nil?
    end
  end
end

my_hash = Example.new(foo: {bar: "x", "baz" => "y"}, "some" => "other")

# Your @foo instance variable which you can access and modify
puts my_hash.foo
# your @foo's bar property which was defined as symbol
puts my_hash.foo[:bar]
# your @foo's baz property which was defined as string
puts my_hash.foo["baz"]
# your @some instance variable
puts my_hash.some
# Notice that even though `foo` was defined as symbol and `some` as
# string, the accessor allows you to get their values by using the
# dot notation.

Редактировать: Из добавленных вами тестов я предполагаю, что они ожидают, что вы создадите новый экземпляр, если переданный параметр является вложенным ha sh. Если это так, вы можете сделать это:

class Example
  def initialize args
    args.each do |k, v|
      # Create a new Example instance if the value is a hash
      v = self.class.new(v) if v.class == Hash
      instance_variable_set("@#{k}", v) unless v.nil?
      # Dynamically set the accessor for each attribute.
      self.class.__send__(:attr_accessor, k)
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...