Виновник лежит в этой части кода:
a.instance_eval do
b = 2
end
Хотя b = 2
оценивается в контексте вашего экземпляра, он не вызывает сеттер. Вместо этого он просто создает новую локальную переменную с именем b
в текущей области видимости. Чтобы позвонить сеттеру, вам необходимо уточнить код, чтобы устранить неоднозначность:
a.instance_eval do
self.b = 2
end