이전에 미세 조정을 사용한 적이 없다면 아마 놀랄 것입니다. 원숭이 패치를 대체하기 위해 개선 사항이 도입되었다는 소식을 들었을 것입니다. 따라서 ActiveSupport의 hours
방법:
module TimeExtension
refine Fixnum do
def hours
self * 60
end
end
end
class MyFramework
using TimeExtension
end
class MyApp < MyFramework
def index
1.hours
end
end
MyApp.new.index # undefined method `hours' for 1:Fixnum (NoMethodError)
위의 코드를 실행하면 작동하지 않는다는 것을 알 수 있습니다. 그래서 무엇을 제공합니까?
다른 많은 훌륭한 아이디어와 마찬가지로 냉정한 현실에서 작동하도록 하려면 개선의 원래 개념을 조정해야 했습니다.
위에서 살펴본 코드의 놀라운 동작은 이러한 조정 중 하나로 인해 발생합니다. 구체적으로, 구체화는 어휘 범위를 지정한다는 규칙입니다.
어휘 범위 지정이란 무엇입니까?
어떤 것이 어휘적이라고 말할 때 그것은 텍스트와 관련이 있음을 의미합니다. 즉, 그 코드가 의미하는 것과는 대조적으로 화면에 표시되는 코드입니다.
두 줄의 어휘 범위가 지정되면 해당 코드 블록이 평가할 대상에 관계없이 동일한 코드 블록 내에서 발생한다는 의미입니다.
이야기하는 것보다 예제를 보는 것이 훨씬 쉽습니다.
class B
# x and y share the same lexical scope
x = 1
y = 1
end
class B
# z has a different lexical scope from x and y, even though it's in the same class.
z = 3
end
세련 항목은 어휘 범위가 지정됩니다.
using 키워드로 구체화를 적용하면 구체화는 어휘 범위 내에서만 볼 수 있습니다.
다음은 내가 의미하는 바를 보여주는 예입니다.
module TimeExtension
refine Fixnum do
def hours
self * 60
end
end
end
class MyApp
using TimeExtension
def index
1.hours
end
end
class MyApp
def show
2.hours
end
end
MyApp.new.show # undefined method `hour' for 1:Fixnum (NoMethodError)
index
및 show
메소드는 동일한 클래스의 일부이며 index
만 메소드는 using
과 어휘 범위를 공유하기 때문에 구체화에 액세스할 수 있습니다. 성명서.
Ruby의 다른 거의 모든 것이 동적으로 범위가 지정되기 때문에 이것은 아마도 약간 이상하게 보일 것입니다. 클래스에 메서드를 추가하면 클래스 정의를 종료할 때 메서드가 그대로 유지됩니다. 그러나 개선 작업은 그렇지 않습니다.
이것은 처음에는 분명하지 않을 수 있는 여러 가지 결과입니다.
정제 방법을 동적으로 호출할 수 없습니다.
send
메소드가 using 문이 포함된 동일한 코드 블록 내에서 정의되지 않아 세분화를 볼 수 없습니다.
그래서 이것은 작동하지 않습니다:
class MyApp
using TimeExtension
def index
1.send(:hours)
end
end
세련 방법의 존재를 쿼리할 수 없습니다.
respond_to?
메소드도 동일한 코드 블록 내에 있지 않습니다. 따라서 send
와 같은 이유로 작동하지 않습니다. 방법이 없습니다.
class MyApp
using TimeExtension
def index
1.respond_to?(:hours)
end
end
결론
이것이 사람들이 개선에 대해 가지고 있는 혼란을 해결하기를 바랍니다. 확실히 Ruby의 잠재적으로 유용한 기능이지만 이전에 사용해 본 적이 없다면 약간 까다로울 수 있습니다.