instance_variable_set (: @attributes, {: brand.to_s => "Apple"}) перезаписывает все атрибуты вместо добавления - PullRequest
1 голос
/ 08 декабря 2010

Фоновая ...

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

class Token < ActiveRecord::BaseWithoutTable

  attr_accessor :regex
  attr_accessor :values

end

Пример токена:

Token.new(:regex => /apple iphone 4/, :values => { :brand => "Apple", :product => "iPhone", :version => 4})

(где все хеш-ключи соответствуют столбцам базы данных в таблице продуктов.)

Вот проблема: в моем Parser, когда обнаружен Token, я пытаюсь добавить связанные значения в экземпляр Product, например, так:

token.values.each do |v|
   attrib, value = v[0], v[1]
   my_product.instance_variable_set(:@attributes, { attrib.to_s => value })
end

Это работает, за исключением того, что мне кажется, что я должен установить все свои атрибуты одновременно. Если я делаю это поэтапно (то есть, когда я обнаруживаю новые токены), он перезаписывает любые неуказанные атрибуты nil. Я что-то пропустил? Есть ли лучший способ сделать это?

Ответы [ 2 ]

1 голос
/ 08 декабря 2010

Изменить существующее значение (если оно существует) вместо того, чтобы перезаписать его:

if attr = my_product.instance_variable_get :@attributes
  attr[attrib.to_s] = value
else
  my_product.instance_variable_get :@attributes, { attrib.to_s => value }
end

Использование instance_variable_set кажется отрывочным; почему у вас нет аксессора на самом Product?

class Product
  def attributes
    @attributes ||= {}
  end
end

...

token.values.each do |attr,v|
   my_product.attributes.merge!( attr.to_s => v )
end
0 голосов
/ 08 декабря 2010

Если my_product является active_record объектом, вы можете использовать write_attribute вместо instance_variable_set.Обратите внимание, что при этом будут записываться только атрибуты, то есть столбцы базы данных:

token.values.each do |v|
   attrib, value = v[0], v[1]
   my_product.write_attribute attrib.to_s, value # attrib.to_sym would work too
end

Также, если token.values возвращает Hash, вы можете выполнить итерацию следующим образом:

token.values.each do |k, v|
   my_product.write_attribute k, v
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...