Объединение двух объектов ruby
вопрос: есть ли краткий способ в Ruby (и/или Rails) объединить два объекта вместе?
в частности, я пытаюсь выяснить что-то похожее на jQuery $.extend()
метод, тогда как первый объект, который вы передаете, будет иметь свои свойства, переопределенные вторым объектом.
Я работаю с моделью бестабличные в Rails 3.2+. При отправке формы параметры из отправки используются для динамического заполнения объекта пользователя. Этот объект пользователя сохраняется между запросами страниц, используя класс Pstore Ruby, сортируя объекты на плоские файлы, которые можно легко получить в будущем.
соответствующий код:
module Itc
class User
include ActiveModel::Validations
include ActiveModel::Conversion
include ActionView::Helpers
extend ActiveModel::Naming
def set_properties( properties = {} )
properties.each { |k, v|
class_eval("attr_reader :#{k.to_sym}")
self.instance_variable_set("@#{k}", v)
} unless properties.nil?
end
end
end
создание объекта пользователя происходит следующим образом:
user = Itc.User.new( params[:user] )
user.save()
на save()
метод выше-это не метод сохранения ActiveRecord, а метод, который я написал для сохранения через PStore.
если у меня есть загруженный объект пользователя, и у меня есть представление формы, я хотел бы сделать что-то вроде это:
merged = existingUserObject.merge(User.new(params[:user])
и иметь результат merged
быть объектом пользователя, только свойства, которые были изменены в представлении формы, будут обновлены.
если у кого-нибудь есть идеи о лучшем способе сделать это в целом, я все уши.
3 ответов
сделайте это, piggybacking на поведении хэша. Создайте класс, который принимает хэш для параметра new()
метод, а затем to_h
метод, который принимает объект и генерирует хэш из текущего состояния экземпляра:
class Foo
def initialize(params={})
@a = params[:a]
@b = params[:b]
end
def to_h
{
a: @a,
b: @b
}
end
end
instance_a = Foo.new(a: 1, b:2)
instance_b = Foo.new(a: 1, b:3)
instance_c = Foo.new(instance_a.to_h.merge(instance_b.to_h))
сброс его в IRB:
irb(main):001:0> class Foo
irb(main):002:1> def initialize(params={})
irb(main):003:2> @a = params[:a]
irb(main):004:2> @b = params[:b]
irb(main):005:2> end
irb(main):006:1>
irb(main):007:1* def to_h
irb(main):008:2> {
irb(main):009:3* a: @a,
irb(main):010:3* b: @b
irb(main):011:3> }
irb(main):012:2> end
irb(main):013:1> end
nil
irb(main):014:0>
irb(main):015:0* instance_a = Foo.new(a: 1, b:2)
#<Foo:0x1009cfd00
@a = 1,
@b = 2
>
irb(main):016:0> instance_b = Foo.new(a: 1, b:3)
#<Foo:0x1009ead08
@a = 1,
@b = 3
>
irb(main):017:0>
irb(main):018:0* instance_c = Foo.new(instance_a.to_h.merge(instance_b.to_h))
#<Foo:0x100a06c60
@a = 1,
@b = 3
>
Is Hash#merge
Не то, что вы ищете? http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-merge. Кажется, вы могли бы просто пойти
merged = existingUserObject.merge(params[:user])
Я не думаю, что вам нужно создать совершенно новый User
object так как предположительно это то, что existingUserObject и вы просто хотите перезаписать некоторые свойства.
вот как я достиг аналогичной вещи с 1 моей модели
# merge other_config.attrs into self.attrs, only for nil attrs
def merge!(other_object)
return if other_object.nil? || other_object.class != self.class
self.assign_attributes(self.attributes.slice ('id').merge(other_object.attributes.slice!('id')){|key, oldval, newval|
oldval.nil? ? newval: oldval
})
end