RGJ
(Richard - Communiteq)
12월 17, 2021, 7:54오전
1
수정: 버그로 재분류했습니다.
전체 재현 방법은 아래 에 있습니다.
테마 컴포넌트에서 api.modifyClass를 사용 중입니다.
대부분의 페이지에서는 정상적으로 작동하지만, 일부 주제에서는 페이지를 새로 고침할 때 사용자 모델에 해당 속성이 추가되지 않습니다. 대부분의 주제에서는 작동하는데 일부 주제에서는 작동하지 않는 이유, 혹은 작동하지 않는 주제들이 어떤 공통점을 가지고 있는지 파악하지 못하고 있습니다.
여기서 제가 무엇을 잘못하고 있는지 이해하시는 분 계신가요?
요약: modifyClass 아래에 모델을 위한 api.container.lookup을 추가하면 이 문제를 우회할 수 있습니다.
1개의 좋아요
pfaffman
(Jay Pfaffman)
12월 17, 2021, 9:49오전
2
아, 맞다! 혹시 이거 아닐까요?
pluginId를 추가해야 하는 것 같습니다.
<script type="text/discourse-plugin" version="0.1">
api.modifyClass('model:user', {
pluginId: 'my-plugin',
testProperty: function() {
return 1;
}
});
</script>
나중 버전에서는 필수 항목입니다. 실제로 어제 몇몇 테마에 이 항목을 추가하기 위해 PR을 제출했습니다. 드디어 플러그인/테마 개발자가 되는 것 같네요.
2개의 좋아요
RGJ
(Richard - Communiteq)
12월 17, 2021, 11:06오전
3
제이, 감사합니다! 실제로 제 테스트 인스턴스에서 효과가 있었어요.
하지만 unfortunately, 만능 해결책은 아니고 문제는 여전히 남아 있어요
1개의 좋아요
네, pluginId는 수정이 두 번 적용되는 것을 방지하기 위한 것으로 생각됩니다. 이것이 없다면 한 번도 실행되지 않은 이유를 설명할 수 없지 않나요?
1개의 좋아요
pfaffman
(Jay Pfaffman)
12월 17, 2021, 11:21오전
5
아니, 정말. 뭔가 아는 줄 알았는데.
혹시 다른 곳에서 클래스를 수정하고 있어서, 누가 먼저 수정하는지에 따라 레이스 컨디션이 발생하는 건가 싶었습니다. 하지만 자바스크립트는 여전히 저에게 미스터리입니다.
2개의 좋아요
여전히 코드 관련 문제이므로 언급하는 것은 당연합니다.
1개의 좋아요
RGJ
(Richard - Communiteq)
12월 17, 2021, 11:30오전
7
pfaffman:
경쟁 조건(race condition)
네, 저도 그 생각이 났습니다. 하지만 이 테스트 사이트에서는 이 것이 유일한 테마 컴포넌트임에도 불구하고 여전히 실패합니다.
1개의 좋아요
궁금한 점이 하나 있는데, 만약 이 코드를 다음 경로에 있는 테마 컴포넌트에 추가하면:
/javascripts/discourse/initializers/test-init.js.es6
동작이 달라지거나 개선될까요?
이 두 가지가 의미론적으로 동일한지 확신이 서지 않습니다 …
… 이론적으로는 브라우저가 새로고침될 때 둘 다 평가되어야 하며, 그 시점 이후에는 수정 사항이 이미 적용되었으므로 라우트 전환 시 레이스 컨디션은 무의미해야 합니다 …
1개의 좋아요
RGJ
(Richard - Communiteq)
12월 17, 2021, 12:15오후
9
merefield:
동작이 변경되거나 개선되나요?
아니요, 동작은 동일합니다.
javascripts/discourse-test/initializers/initialize-discourse-test.js.es6를 사용하여 테마 컴포넌트를 만들었습니다:
import { withPluginApi } from "discourse/lib/plugin-api";
export default {
name: 'discourse-test-initializer',
initialize(){
console.log('here1');
withPluginApi("0.1", api => {
console.log('here2');
api.modifyClass('model:user', {
pluginId: 'test',
testFunction: function() {
console.log('here3');
return 2;
}
});
});
}
}
모든 페이지에서 다음과 같이 출력됩니다.
here1
here2
일부 토픽에서는 콘솔에 Discourse.currentUser.testFunction()을 입력하면 작동하며 here3과 2가 출력됩니다.
일부 토픽에서는 작동하지 않습니다(Uncaught TypeError: Discourse.currentUser.testFunction is not a function).
2개의 좋아요
RGJ
(Richard - Communiteq)
12월 18, 2021, 9:20오전
11
네, 도움이 되는 게시글에 대한 알림을 확인했는데, 해당 게시글은 이미 삭제된 상태였습니다.
제안은 작동하지 않았지만, 문제를 해결하는 데 도움이 되는 단서를 제공해 주었습니다.
다음 스니펫을 작동하지 않는 코드 아래 에 추가하면 제가 겪고 있던 문제가 일관되게 해결되었습니다. 이 방법은 안정 버전(stable)과 테스트 통과 버전(tests-passed) 모두에서 여러 독립적인 포럼을 통해 테스트해 보았습니다. 이 문제를 #contribute:bug로 재분류해야 한다고 생각합니다 …
<script type="text/discourse-plugin" version="0.1">
const userModel = api.container.lookup("model:user");
</script>
@Johani 도움 주셔서 감사합니다!
2개의 좋아요
RGJ
(Richard - Communiteq)
12월 20, 2021, 5:54오후
12
이를 버그로 재분류합니다.
플러그인 API 코드인 app/assets/javascripts/discourse/app/lib/plugin-api.js에 console.log를 추가하여 modifyClass가 호출될 때마다 로그를 기록하도록 했습니다.
어딘가에 충돌이 없는지 확인하기 위해 모든 외부 플러그인을 제거했습니다.
재현 방법:
#1 작동
<script type="text/discourse-plugin" version="0.1">
api.modifyClass('model:user', {
pluginId: 'test-tc',
testFunction: function() {
return 1;
}
});
</script>
홈 페이지를 로드합니다
콘솔에 modifyClass called for model:user _application-08d9058ddd37ba80992f770509f4919ad0738a17f14fb85167b1dc1f32f8b56e.js:23490:16 Object { pluginId: "test-tc", testFunction: testFunction() }가 표시됩니다
콘솔에 Discourse.currentUser.testFunction()을 입력합니다
"1"이 출력됩니다
#2 실패
예를 들어 'Welcome to Discourse’와 같은 토픽으로 이동하여 페이지를 새로고침합니다
콘솔에 동일한 “modifyClass called” 로그가 표시됩니다
콘솔에 Discourse.currentUser.testFunction()을 입력합니다
Uncaught TypeError: Discourse.currentUser.testFunction is not a function가 출력됩니다
#3 경고와 함께 실패
테마 컴포넌트 맨 위에 한 줄을 추가하여 다음과 같은 모양으로 만듭니다:
<script type="text/discourse-plugin" version="0.1">
const userModel = api.container.lookup("model:user");
api.modifyClass('model:user', {
pluginId: 'test-tc',
testFunction: function() {
return 1;
}
});
</script>
예를 들어 'Welcome to Discourse’와 같은 토픽으로 이동하여 페이지를 새로고침합니다
콘솔에 동일한 “modifyClass called” 로그가 표시됩니다
콘솔에 경고 "model:user" was already cached in the container. Changes won't be applied.가 표시됩니다
콘솔에 Discourse.currentUser.testFunction()을 입력합니다
Uncaught TypeError: Discourse.currentUser.testFunction is not a function가 출력됩니다
#4 작동
lookup 줄을 테마 컴포넌트 하단 으로 이동하여 다음과 같은 모양으로 만듭니다:
<script type="text/discourse-plugin" version="0.1">
api.modifyClass('model:user', {
pluginId: 'test-tc',
testFunction: function() {
return 1;
}
});
const userModel = api.container.lookup("model:user");
</script>
예를 들어 'Welcome to Discourse’와 같은 토픽으로 이동하여 페이지를 새로고침합니다
콘솔에 동일한 “modifyClass called” 로그가 표시됩니다
콘솔에 Discourse.currentUser.testFunction()을 입력합니다
"1"이 출력됩니다
4개의 좋아요
RGJ
(Richard - Communiteq)
6월 23, 2022, 9:32오전
13
다시 살펴봅니다:
Discourse 2.8 이상에서 Discourse.User.current().testFunction()을 사용할 때, 경우 #2가 여전히 실패합니다.
1개의 좋아요
david
(David Taylor)
4월 18, 2023, 10:39오전
18
이러한 상황에 대한 경고 메시지를 개선했습니다:
main ← modify-class-warning
merged 10:41AM - 18 Apr 23 UTC
- Print warning when it affects user/currentUser
- Improve description and link… to Meta topic
또한 원인과 해결 방법을 설명하는 문서를 작성했습니다:
고급 테마와 플러그인의 경우, Discourse는 modifyClass 시스템을 제공합니다. 이를 통해 코어 JavaScript 클래스의 많은 기능을 확장하고 오버라이드할 수 있습니다.
modifyClass를 사용할 때
modifyClass는 Discourse의 보다 안정적인 커스터마이징 API(예: plugin-api 메서드, plugin outlets, transformers)를 통해 커스터마이징을 할 수 없는 경우를 제외하고는 최후의 수단으로 사용해야 합니다.
코어의 코드는 언제든지 변경될 수 있습니다. 따라서 modifyClass를 통해 만든 커스터마이징도 언제든지 깨질 수 있습니다. 이 API를 사용할 때는 프로덕션 사이트에 문제가 도달하기 전에 이를 포착할 수 있는 제어가 이루어지도록 해야 합니다. 예를 들어, 테마/플러그인에 자동화된 테스트를 추가하거나, 스테이징 사이트를 사용하여 Discourse 업데이트를 테마/플러그인에 대해 테스트할 수 있습니다.
기본 사용법
…
이로써 이 주제에 대한 모든 우려 사항을 해결할 수 있을 것으로 생각합니다. 그렇지 않다면 실패하는 코드 예시를 공유해 주시면 확인해 보겠습니다.
11개의 좋아요
david
(David Taylor)
에 닫힘
4월 22, 2023, 7:00오전
19
이 주제는 3일 후 자동으로 닫혔습니다. 새로운 답글은 더 이상 허용되지 않습니다.