ΠΠΎΠ½ΡΡΠ°Π½ΡΡ ΠΈ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ Π² Ruby β ΡΡΠΎ Π½Π΅ ΠΏΡΠΎΡΡΠΎ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ° Π΄Π°Π½Π½ΡΡ , Π° ΠΏΠΎΠ»Π½ΠΎΡΠ΅Π½Π½ΡΠ΅ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ ΠΌΠ΅ΡΠ°ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ. Π ΡΡΠ°ΡΡΠ΅ ΡΠ°Π·Π±Π΅ΡΡΠΌ ΠΌΠ΅ΡΠΎΠ΄Ρ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ Π½ΠΈΠΌΠΈ, ΠΈΡ ΠΏΠΎΠ΄Π²ΠΎΠ΄Π½ΡΠ΅ ΠΊΠ°ΠΌΠ½ΠΈ ΠΈ ΡΠ΅Π°Π»ΡΠ½ΡΠ΅ ΠΊΠ΅ΠΉΡΡ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΡ β ΠΎΡ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΊΠ»Π°ΡΡΠΎΠ² Π΄ΠΎ Ρ ΠΈΡΡΡΡ ΡΠΈΠΊΡΠΎΠ² legacy-ΠΊΠΎΠ΄Π°.
π ΠΠ²Π΅Π΄Π΅Π½ΠΈΠ΅: Π·Π°ΡΠ΅ΠΌ ΡΡΠΎ Π½ΡΠΆΠ½ΠΎ?
ΠΡΠ΅Π΄ΡΡΠ°Π²ΡΡΠ΅: Π²Ρ ΠΎΡΠΊΡΡΠ²Π°Π΅ΡΠ΅ ΡΡΠ°ΡΡΠΉ ΠΏΡΠΎΠ΅ΠΊΡ, Π° ΡΠ°ΠΌβ¦
class Magic
KLASS = case ENV['MODE']
when 'prod' then ProductionSpell
when 'test' then TestSpell
else DebugSpell
end
end
Π Π½ΡΠΆΠ½ΠΎ ΡΡΠΎ ΠΊΠ°ΠΊ-ΡΠΎ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ, ΠΌΠ΅Π½ΡΡΡ ΠΈΠ»ΠΈ Π²ΠΎΠΎΠ±ΡΠ΅ ΡΠ΄Π°Π»ΡΡΡ. ΠΠΎΡ ΡΡΡ-ΡΠΎ ΠΈ ΠΏΡΠΈΠ³ΠΎΠ΄ΡΡΡΡ ΠΌΠ΅ΡΠΎΠ΄Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΠΊΠΎΠ½ΡΡΠ°Π½ΡΠ°ΠΌΠΈ!
π ΠΠΎΠ½ΡΡΠ°Π½ΡΡ: Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΈΠΉ Π΄ΠΎΡΡΡΠΏ
const_get / const_set β ΡΠΈΡΠ°Π΅ΠΌ ΠΈ ΠΏΠΈΡΠ΅ΠΌ ΠΊΠΎΠ½ΡΡΠ°Π½ΡΡ
Π’Π΅ΠΎΡΠΈΡ:
ΠΡΠΈ ΠΌΠ΅ΡΠΎΠ΄Ρ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡ ΠΏΠΎΠ»ΡΡΠ°ΡΡ ΠΈ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°ΡΡ ΠΊΠΎΠ½ΡΡΠ°Π½ΡΡ ΠΏΠΎ ΡΡΡΠΎΠΊΠΎΠ²ΠΎΠΌΡ ΠΈΠΌΠ΅Π½ΠΈ.
ΠΡΠΈΠΌΠ΅Ρ: ΠΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠ»Π°ΡΡΠΎΠ² Π΄Π»Ρ ΠΏΠ»Π°Π³ΠΈΠ½ΠΎΠ²:
# ΠΠ°Π³ΡΡΠΆΠ°Π΅ΠΌ Π²ΡΠ΅ ΠΏΠ»Π°Π³ΠΈΠ½Ρ ΠΈΠ· ΠΏΠ°ΠΏΠΊΠΈ
Dir['plugins/*.rb'].each do |file|
plugin_name = File.basename(file, '.rb').camelize
klass = Object.const_set(plugin_name, Class.new(PluginBase))
klass.load(file)
end
ΠΠ½ΡΠΈΠΏΠ°ΡΡΠ΅ΡΠ½:
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ const_set Π΄Π»Ρ ΠΏΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΡ
ΠΊΠ»Π°ΡΡΠΎΠ²:
# β ΠΠ»ΠΎΡ
ΠΎ: ΡΠ»ΠΎΠΌΠ°Π΅Ρ Π²Π΅ΡΡ String Π² ΡΠΈΡΡΠ΅ΠΌΠ΅
Object.const_set(:String, MyWeirdString)
const_defined? β ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π° ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°Π½ΠΈΠ΅
Π’Π΅ΠΎΡΠΈΡ:
ΠΡΠΎΠ²Π΅ΡΡΠ΅Ρ, ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π° Π»ΠΈ ΠΊΠΎΠ½ΡΡΠ°Π½ΡΠ° Π² ΡΠ΅ΠΊΡΡΠ΅ΠΌ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ΅.
ΠΡΠΈΠΌΠ΅Ρ: ΠΠ΅Π·ΠΎΠΏΠ°ΡΠ½Π°Ρ Π·Π°Π³ΡΡΠ·ΠΊΠ° ΠΌΠΎΠ΄ΡΠ»Π΅ΠΉ:
unless Object.const_defined?(:Redis)
require 'redis'
Object.const_set(:Redis, Redis)
end
ΠΠΎΠ²ΡΡΠΊΠ°:
ΠΠ΅ΡΠΎΠ΄ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ Π²ΡΠΎΡΠΎΠΉ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡ inherit (ΠΈΡΠΊΠ°ΡΡ Π² ΡΠΎΠ΄ΠΈΡΠ΅Π»ΡΡΠΊΠΈΡ
ΠΊΠ»Π°ΡΡΠ°Ρ
):
module A; MY_CONST = 1; end
class B; include A; end
B.const_defined?(:MY_CONST) #=> false
B.const_defined?(:MY_CONST, true) #=> true
remove_const β ΡΠ΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΡΠ°Π½Ρ
Π’Π΅ΠΎΡΠΈΡ:
Π£Π΄Π°Π»ΡΠ΅Ρ ΠΊΠΎΠ½ΡΡΠ°Π½ΡΡ ΠΈΠ· ΡΠ΅ΠΊΡΡΠ΅Π³ΠΎ ΠΌΠΎΠ΄ΡΠ»Ρ/ΠΊΠ»Π°ΡΡΠ°.
ΠΡΠΈΠΌΠ΅Ρ: ΠΡΠΈΡΡΠΊΠ° Π² ΡΠ΅ΡΡΠ°Ρ :
RSpec.describe MyGem do
after do
MyGem.send(:remove_const, :Config) if MyGem.const_defined?(:Config)
end
end
ΠΠ°ΠΆΠ½ΠΎ:
Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΡΠ°Π½Ρ β ΠΎΠΏΠ°ΡΠ½Π°Ρ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ! Π‘ΡΡΠ΅ΡΡΠ²ΡΡΡΠΈΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ ΡΡΠΎΠ³ΠΎ ΠΊΠ»Π°ΡΡΠ° ΠΎΡΡΠ°Π½ΡΡΡΡ Π² ΠΏΠ°ΠΌΡΡΠΈ.
ποΈ ΠΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ°
instance_variable_get / instance_variable_set
Π’Π΅ΠΎΡΠΈΡ:
Π§ΡΠ΅Π½ΠΈΠ΅ ΠΈ Π·Π°ΠΏΠΈΡΡ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ (Π²ΠΊΠ»ΡΡΠ°Ρ @).
ΠΡΠΈΠΌΠ΅Ρ: ΠΠ΅ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ:
json = { "@name" => "John", "@age" => 30 }
user = User.new
json.each do |key, value|
user.instance_variable_set(key, value)
end
ΠΠ½ΡΠΈΠΏΠ°ΡΡΠ΅ΡΠ½:
ΠΠ»ΠΎΡΠΏΠΎΡΡΠ΅Π±Π»Π΅Π½ΠΈΠ΅ Π² production-ΠΊΠΎΠ΄Π΅ Π²ΠΌΠ΅ΡΡΠΎ Π½ΠΎΡΠΌΠ°Π»ΡΠ½ΡΡ
ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² Π΄ΠΎΡΡΡΠΏΠ°.
instance_variables β ΡΠΏΠΈΡΠΎΠΊ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
Π’Π΅ΠΎΡΠΈΡ:
ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΠΌΠ°ΡΡΠΈΠ² ΠΈΠΌΠ΅Π½ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° (Ρ @).
ΠΡΠΈΠΌΠ΅Ρ: ΠΡΠ»Π°Π΄ΠΊΠ° ΡΠΎΡΡΠΎΡΠ½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ°:
def debug(obj)
puts "Variables: #{obj.instance_variables.join(', ')}"
end
ποΈ ΠΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΊΠ»Π°ΡΡΠ°
class_variable_get / class_variable_set
Π’Π΅ΠΎΡΠΈΡ:
ΠΠ½Π°Π»ΠΎΠ³ΠΈΡΠ½ΠΎ instance-ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌ, Π½ΠΎ Π΄Π»Ρ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
ΠΊΠ»Π°ΡΡΠ° (@@).
ΠΡΠΈΠΌΠ΅Ρ: ΠΠ°ΡΠ»Π΅Π΄ΡΠ΅ΠΌΡΠΉ ΠΊΠ΅Ρ:
class Base
@@cache = {}
def self.add_to_cache(key, value)
class_variable_set(:@@cache, class_variable_get(:@@cache).merge(key => value))
end
end
ΠΡΡΠΎΡΠΎΠΆΠ½ΠΎ:
ΠΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΊΠ»Π°ΡΡΠ° Π²ΠΈΠ΄Π½Ρ Π²ΠΎ Π²ΡΠ΅ΠΉ ΠΈΠ΅ΡΠ°ΡΡ
ΠΈΠΈ Π½Π°ΡΠ»Π΅Π΄ΠΎΠ²Π°Π½ΠΈΡ!
class_variables β ΡΠΏΠΈΡΠΎΠΊ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
ΠΊΠ»Π°ΡΡΠ°
Π’Π΅ΠΎΡΠΈΡ:
ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΠΌΠ°ΡΡΠΈΠ² ΠΈΠΌΠ΅Π½ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
ΠΊΠ»Π°ΡΡΠ°.
ΠΡΠΈΠΌΠ΅Ρ: ΠΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π° βΠ·Π°ΡΠΎΡΠ΅Π½ΠΈΠ΅β ΠΊΠ»Π°ΡΡΠ°:
if MyClass.class_variables.any?
logger.warn "Class variables detected in #{MyClass}"
end
π― ΠΡΠ²ΠΎΠ΄: ΠΊΠΎΠ³Π΄Π° ΡΡΠΎ ΡΠ΅Π°Π»ΡΠ½ΠΎ Π½ΡΠΆΠ½ΠΎ?
- ΠΠ΅ΡΠ°ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅: ΠΏΠ»Π°Π³ΠΈΠ½Ρ, Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΠΊΠ»Π°ΡΡΡ
- Π’Π΅ΡΡΡ: ΠΌΠΎΠΊΠΈ, ΡΡΠ°Π±Ρ, ΠΎΡΠΈΡΡΠΊΠ° ΡΠΎΡΡΠΎΡΠ½ΠΈΡ
- ΠΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ: Π΄Π΅Π±Π°Π³Π³Π΅ΡΡ, ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΎΡΡ
- Legacy-ΠΊΠΎΠ΄: ΠΊΠΎΠ³Π΄Π° Π΄ΡΡΠ³ΠΎΠ³ΠΎ Π²ΡΡ ΠΎΠ΄Π° Π½Π΅Ρ
ΠΠΎΠ»ΠΎΡΠΎΠ΅ ΠΏΡΠ°Π²ΠΈΠ»ΠΎ:
ΠΡΠ»ΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±ΠΎΠΉΡΠΈΡΡ ΠΎΠ±ΡΡΠ½ΡΠΌΠΈ ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌΠΈ β ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ ΠΈΡ
. ΠΡΠΈ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ β ΠΊΠ°ΠΊ Ρ
ΠΈΡΡΡΠ³ΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΡΠΊΠ°Π»ΡΠΏΠ΅Π»ΠΈ: ΠΌΠΎΡΠ½ΡΠ΅, Π½ΠΎ ΠΎΠΏΠ°ΡΠ½ΡΠ΅.
# ΠΠ½ΠΎΠ³Π΄Π° Π»ΡΡΡΠ΅ ΡΠ°ΠΊ:
MyClass.const_get(:Settings) #=> π
# Π§Π΅ΠΌ ΡΠ°ΠΊ:
eval "MyClass::Settings" #=> π₯