Components can be provided a key, via the special key parameter that ensures when rendering lists of components the ordering does not change, and speeds up the rendering of the list.
...
UL do
MyModel.each do |record|
DisplayRecord(record: record, key: record.id)
end
end
...
typically you can use some data associated with the values being displayed (like record.id above) or the ruby object_id, or some other unique identifier depending on the contents of the list item.
For HyperModels (and probably other places too) this can be difficult. The above example for instance only works if all the records are saved (i.e. have ids). You can't use record.object_id since there is no guarantee that on the next rendering the record instance will be the same object_id, so you have use record.backing_record.object_id which is gross and relies on knowing the inards of HyperModel.
The solution is to add a to_key method to the base ruby Object class and to have the key parameter automatically have to_key applied to it. The default to_key method will return self.object_id, but this can be overwritten as needed. I.e. ActiveRecord::Base can override as self.backing_record.object_id.
Now we can write DisplayRecord(record: record, key: record) shorter, sweeter, and works.
Also in keeping with POLS, strings, symbols, booleans and number objects will return themselves.
class Object
def to_key
object_id
end
end
class String
def to_key
self
end
end
class Number
def to_key
self
end
end
class Boolean
def to_key
self
end
end
class Foo
end
class Bar
def self.new_bar_counter
@bar_counter = (@bar_counter && @bar_counter+1) || 0
end
def initialize
@to_key = "Bar ##{Bar.new_bar_counter}"
end
attr_reader :to_key
end
puts Object.new.to_key
puts "hello".to_key
puts 12.to_key
puts true.to_key
puts Foo.new.to_key
puts Bar.new.to_key
puts Bar.new.to_key
This is nice. The way it's laid out is also backwards compatible because record.id or record.object_id in existing code returns a number, and Number#to_key == self.
Components can be provided a key, via the special
key
parameter that ensures when rendering lists of components the ordering does not change, and speeds up the rendering of the list.typically you can use some data associated with the values being displayed (like
record.id
above) or the ruby object_id, or some other unique identifier depending on the contents of the list item.For HyperModels (and probably other places too) this can be difficult. The above example for instance only works if all the records are saved (i.e. have ids). You can't use
record.object_id
since there is no guarantee that on the next rendering the record instance will be the same object_id, so you have userecord.backing_record.object_id
which is gross and relies on knowing the inards of HyperModel.The solution is to add a
to_key
method to the base rubyObject
class and to have the key parameter automatically haveto_key
applied to it. The defaultto_key
method will returnself.object_id
, but this can be overwritten as needed. I.e. ActiveRecord::Base can override asself.backing_record.object_id
.Now we can write
DisplayRecord(record: record, key: record)
shorter, sweeter, and works.Also in keeping with POLS, strings, symbols, booleans and number objects will return themselves.
Produces
run it!
As well as adding the method to the classes per above, you also have to add these lines here