The __index
metafield is triggered when you try to 'get' a field from your table the doesn't exist.
ring.bonuses.damageBonus = 0.25
is trying to 'get' bonuses from ring, and since it doesn't exist, goes to the metatable and returns your bonuses table, and then its damageBonus index is set to 0.25.
Understand that just declaring variables in the Item table doesn't mean your Item instances will inherit them as instance variables. For that, you would need to declare/initialize them in your Item:new() function:
function Item:new(o)
local item = o or {}
setmetatable(item, self)
self.__index = self
item.bonuses={} -- create instance bonuses table and give default values
for k,v in pairs(self.bonuses) do
item.bonuses[k]=v
end
return item
end