이 게시물에서는 Rails 애플리케이션을 위한 기본 ActionText 테이블 편집기를 구현합니다. 그 방법은 다음과 같습니다:
- ActionText 및 Trix가 첨부 파일을 처리합니다.
- 자체
Attachable구현 입력하고 이를 활용하여 기본 테이블 편집기를 구축합니다. - 터보 프레임을 사용하여 표를 편집할 수 있습니다.
- 터보는 도움이 되는 동시에 방해가 됩니다
이 기사는 2020년에 게시된 뛰어난 'Stimulus.js를 사용하여 ActionText에 테이블 추가' 블로그 게시물에서 영감을 얻었습니다. 하지만 이는 Turbo가 등장하기 전에 작성되었으므로 문제가 상당히 단순화될 것으로 예상됩니다.
가자!
Rails 101의 ActionText 첨부 파일
참고 :이 데모에서는 Trix 및 Turbo Frame에 대해 어느 정도 이해하고 있다고 가정합니다. Hotwire 및 Turbo Frames의 기본 사항을 학습하는 데 'Ruby on Rails 앱에서 Hotwire 시작하기' 게시물이 도움이 될 수 있습니다.
이 GitHub 저장소에서 코드 데모를 따라갈 수 있습니다.
ActionText 문서에 설명된 대로:
Action Text는 풍부한 텍스트 콘텐츠와 편집 기능을 Rails에 제공합니다. 여기에는 서식 지정부터 링크, 인용문, 목록, 삽입된 이미지 및 갤러리에 이르기까지 모든 것을 처리하는 Trix 편집기가 포함되어 있습니다.
높은 수준에서 첨부 파일은 ActionText 문서 모델의 일부입니다. SGID(서명된 전역 ID)로 확인할 수 있는 모든 리소스에 대한 사용자 정의 템플릿을 렌더링합니다. 즉, ActionText는 특정 SGID에 대한 참조를 <action-text-attachment>으로 저장합니다. 요소:
ActionText는 이러한 요소를 발견할 때마다 to_attachable_partial_path를 호출합니다. 해당 리소스에 대한 메서드입니다. 기본적으로 이 메서드는 to_partial_path에 위임됩니다. .
미리보기로 Table는 다음과 같습니다. ActionText에서의 의 표현은 HTML로 다시 렌더링될 때 보일 것입니다:
ActionText Attachment API를 준수하려면 클래스는 두 가지 작업만 수행하면 됩니다:
to_sgid구현GlobalID::Identification를 포함하여 . 기본적으로 모든ActiveRecord::Base후손들은 이미 이 일을 하고 있습니다.ActionText::Attachable포함 모듈.
ActionText::Attachable 모듈은 attachable_sgid를 통해 모든 모델을 SGID로 변환하거나 SGID에서 변환하는 정식 방법을 제공합니다. 및 from_attachable_sgid 방법. 나중에 이 기능을 활용하겠습니다.
또한 파일 크기, 이름, 콘텐츠 유형 등 첨부 파일 메타데이터에 대한 편리한 접근자를 제공합니다.
마지막으로 편집기 및 서식 있는 텍스트 보기에서 첨부 파일을 렌더링하는 데 사용되는 부분의 기본 위치를 제공합니다.
테이블 모델 추가
ActionText의 Attachment API를 활용하여 테이블 솔루션을 구현하겠습니다. 이를 위해 테이블의 데이터를 캡처하고 Attachable를 포함하는 사용자 정의 모델을 만들어야 합니다. . 간단한 JSON(B) 열을 사용하여 테이블 데이터에 대한 2차원 배열을 보유하겠습니다.
탐색을 시작하려면 ActionText가 활성화된 새 Rails 앱을 만들어 보겠습니다.
오늘은 창의력이 없으니까 Article를 발판으로 삼자 제목과 서식 있는 텍스트 콘텐츠가 있는 모델:
조심하세요, 여기에 놀라운 문제가 있습니다! 위의 설치 명령으로 CreateActionTextTables가 생성되었습니다. 마이그레이션이므로 이름을 CreateActionTextTablesTable으로 바꿔야 합니다. . 또한 null: false, default: [["", ""], ["", ""]]을 사용하여 2x2 테이블을 기본값으로 설정합니다. .
Rails ActionText 모델에 테이블 추가
실제로 서식 있는 텍스트에 표를 추가하기 전에 Trix의 도구 모음을 패치해야 합니다.
여기서는 Trix의 toolbarElement에 수동으로 버튼을 추가합니다. . 이것을 trix-table에 연결 자극 컨트롤러(아직 구축하지 않음)는 문서에 테이블을 삽입합니다. 이 버튼에 CSS 콘텐츠로 멋진 SVG를 제공하고 그 동안 몇 가지 테이블 스타일을 설정해 보겠습니다.
보시다시피, "file-tools" 그룹에 성공적으로 추가되었습니다:

이제 Turbo를 사용하여 테이블을 추가하고 조작하는 방법으로 돌아가겠습니다. 이를 위해서는 먼저 create이 있는 컨트롤러가 필요합니다. 행동:
이 작업은 소개에서 인용한 'On Rails' 블로그 게시물에서 어느 정도 차용할 수 있습니다. SGID 및 content를 포함하여 클라이언트 측에 첨부 파일을 삽입하는 데 필요한 JSON을 구성합니다. editor에서 렌더링됨 나중에 살펴보겠지만 부분적입니다.
관련 리소스 테이블 경로를 추가합니다. 우리 구성에:
이제 깊은 끝으로 뛰어들 순간이 왔습니다. 테이블 모델을 구축해야 합니다. 먼저 ActionText::Attachable을 포함시켜 보겠습니다. 관련 부분 경로를 정의합니다:
아직 테이블 내용이 저장되는 방법을 정의하지 않았습니다. 데이터베이스에서 JSON(B) 열로 선언했기 때문에 어떤 형식이든 자유롭게 선택할 수 있습니다. 인용된 블로그 게시물에서 조금 벗어나 2차원 배열을 사용해 보겠습니다. 따라서 content에 대해 중첩 루프를 간단히 수행할 수 있습니다. 이렇게:
위 부분은 ActionView에서 요청할 때마다 렌더링됩니다. , 예를 들어. 다음으로 editor도 고안해야 합니다. Trix에서 인라인으로 사용되는 부분:
아마 눈치채셨겠지만 유일한 차이점은 SGID를 DOM ID로 사용하여 터보 프레임에 래핑했다는 것입니다. 또한 구분 블록에 행 및 열 인덱스를 제공하고 내부 DIV contenteditable를 만들어 인라인 편집을 준비합니다. — 이에 대해서는 나중에 다루겠습니다.
이제 도구 모음의 테이블 버튼을 방금 작성한 서버 측 컨트롤러 작업에 연결하겠습니다. 이를 위해서는 먼저 Rails의 request.js 라이브러리를 프로젝트로 가져와야 합니다. 이 라이브러리는 post을 관리하는 데 도움이 됩니다. 적절한 CSRF 토큰 등을 포함한 클라이언트의 요청:
새로운 Trix 테이블 자극 컨트롤러 구축
이제 모든 것이 설정되었으므로 새 trix-table을 만들어 보겠습니다. 자극 컨트롤러. 여기서는 attachTable를 구현하겠습니다. 툴바 버튼이 참조하는 작업:
테이블의 create에 게시됩니다. 경로, JSON 응답을 Trix 첨부 파일로 삽입 . 이는 다시 OnRails 블로그 게시물에서 차용하여 더 이상 사용되지 않는 rails-ujs를 교환합니다. 최신 request.js가 필요합니다. 도서관.
이제 이 컨트롤러를 양식의 마크업에 추가하여 앱에서 실제로 활용해야 합니다.
Stimulus.js의 장점은 form에 두 개의 데이터 속성만 추가한다는 것입니다. 요소가 원하는 결과를 얻습니다. 이제 버튼을 한 번만 클릭하면 기사 내용에 표를 추가할 수 있습니다:

터보 프레임을 통한 테이블 조작
이제 테이블 첨부 파일을 만들 수 있으므로 콘텐츠 조작에 초점을 맞춰 보겠습니다. 알고 보니 터보 프레임은 거의 여기에 자연스럽게 어울립니다.
표 행과 열 추가 및 삭제
테이블 행과 열을 추가하고 삭제하기 위해 각 작업에 하나씩 4개의 버튼으로 구성된 미니 도구 모음을 만듭니다. button_to을 활용하세요 도우미를 사용하고 URL을 update로 설정하세요. 해당 테이블의 경로입니다. 추가 매개변수로 트리거하려는 해당 작업을 추가해 보겠습니다.
차례로 TablesController에 해당 컨트롤러 작업을 추가해야 합니다. . update을 확인하세요. action은 해당 작업을 모델에 위임합니다.
테이블 구조에 대한 변경 사항이 저장된 후 테이블의 편집 보기로 리디렉션됩니다. 동일한 editor를 렌더링합니다. 부분적으로는 동일한 터보 프레임을 참조하는 부작용이 있습니다. 따라서 Turbo는 일치하는 프레임을 감지하고 하나를 다른 프레임으로 대체할 수 있습니다.
이제 Table에서 누락된 명령을 구현해야 합니다. 모델.
특히 2차원 배열의 단순한 데이터 구조로 인해 add/remove<sub>column</sub>/row 메서드는 열과 행 수를 수정하는 단순한 프록시입니다. 일단 배치되면 버튼 클릭으로 테이블 구조를 변경할 수 있습니다:

표 셀 내용 편집
열과 행의 수를 변경하는 것 외에도 셀의 내용도 편집하고 싶습니다. 이를 달성하기 위해 우리는 다시 인용된 블로그 게시물에 크게 의존하여 Stimulus 테이블 편집기 컨트롤러를 만들 것입니다.
updateCell 메소드는 셀이 편집될 때마다 행 및 열 인덱스를 매개변수로 전달하여 PATCH 요청을 발행합니다. 이제 우리가 해야 할 일은 DOM에 연결하는 것뿐입니다:
서버 측 TablesController 물론 이제 이 작업을 처리할 방법이 필요합니다. 운 좋게도 이는 조건에 다른 분기를 추가하여 단순화된 개념 증명으로 쉽게 수행됩니다. 또한 update이 있는지 확인합니다. 이제 작업은 단지 빈 개체를 반환하는 경우에도 JSON 유형 요청을 처리할 수 있습니다.
프로덕션 앱에서는 작업을 삭제하기 위해 if/elsif/else보다 다른 전략을 선택하는 것이 좋습니다. 조건. 이 경우 아마도 중재자나 대리인을 찾을 것입니다.
Ruby에서 Trix의 한계
지금까지 나는 이 설명이 완벽하게 이해되었다고 가정했지만 중요한 세부 사항을 생략했습니다. 기본 데이터베이스 모델을 잘 유지하는 동안 이를 Trix의 내부 섀도우 표현과 동기화하지 않습니다. 이것이 바로 우리가 초점을 맞추면 테이블이 이전에 저장된 표현으로 돌아가는 이유입니다:

지금 페이지를 새로 고치면 Trix의 문서가 새로 초기화되었기 때문에 추가된 내용이 나타납니다.
선택 항목이 변경될 때 Trix가 내부 문서를 동기화하는 위치에 이 문제를 고정했습니다. 여기 그림자 요소에서 펼쳐집니다.
turbo:submit에 연결해 보았습니다. 이벤트를 실행하고 테이블을 흐리게 할 때 동기화를 방지하지만 제가 생각해낸 솔루션은 모두 매우 복잡해 보이고 내부 API에 크게 의존합니다.
이 문제를 처리하는 가장 터보적인 방법은 전체 양식을 열심히 로드되는 터보 프레임으로 감싸고 Trix의 콘텐츠가 변경될 때마다 다시 로드하도록 지시하는 것입니다.
다음과 같은 것이 도움이 될 것입니다:
src에서 로드하는 터보 프레임에 양식을 포함하는 경우 :
하지만 이 접근 방식은 이미 지속된 기본 레코드에만 작동합니다.
트릭스에 대한 마지막 경고
우리가 구축한 개념 증명은 서버 렌더링 HTML을 사용하여 테이블을 JSON으로 직렬화하고 JavaScript 이벤트를 수신하는 추가 복잡성을 없애줍니다. ActionText 설치에 이식 가능하며 gem으로 쉽게 추출할 수 있습니다.
하지만 몇 가지 단점이 있는데, 가장 분명한 것은 Trix의 문서 모델과 필요한 재동기화입니다. 제안된 해결 방법이 실행 가능한 상황과 실행 불가능한 상황이 있을 수 있습니다. Trix가 Turbo 호환 인터페이스를 확보할 때까지 이를 피할 방법은 없습니다.
두 번째 문제는 Trix의 undo을 사용하지 않는다는 것입니다. 기능을 제공합니다(그러나 이는 모든 Trix 첨부 파일에 해당됩니다). 마찬가지로 내부 API를 조정하는 대신 업스트림 변경을 기다리는 것이 현명할 것입니다.
마무리
이 게시물에서는 ActionText 첨부 파일의 기본 사항을 간략하게 살펴보는 것부터 시작했습니다. 그런 다음 Turbo Frames를 사용하여 조정하기 전에 ActionText 모델에 테이블을 추가했습니다. 마지막으로 Trix 사용 시 몇 가지 제한 사항을 다루었습니다.
CoffeeScript에서 일반 현대 JavaScript로의 변환 기능을 제공하는 Trix v2가 진행 중이라는 점을 고려하면 이제 Turbo 호환성을 해결할 좋은 시기가 될 것입니다. 현재 이러한 래퍼의 범위는 내 능력 밖이지만 확실히 기회의 창처럼 보입니다.
즐거운 코딩 되세요!
추신 Ruby Magic 게시물이 보도되는 즉시 읽으려면 Ruby Magic 뉴스레터를 구독하고 단 하나의 게시물도 놓치지 마세요!