Rails Helpers 사용 방법: 부트스트랩 캐러셀 데모

게시 됨: 2022-03-11

모든 Rails 내장 구조 중 가장 오용되고, 오해되고, 무시되는 것 중 하나는 view helper 입니다. app/helpers 디렉토리에 위치하며 모든 새로운 Rails 프로젝트와 함께 기본적으로 생성되는 헬퍼는 전체 애플리케이션의 뷰 레이어에서 사용되는 일회성 메서드의 쓰레기장이라는 나쁜 평판을 받는 경우가 많습니다. 불행히도 Rails 자체는 기본적으로 모든 도우미를 모든 보기에 포함하여 오염된 전역 네임스페이스를 생성함으로써 이러한 구조 부족과 빈약한 조직을 조장합니다.

하지만 헬퍼가 더 의미론적이고, 더 잘 조직되고, 프로젝트 전체에서 재사용할 수 있다면 어떨까요? 뷰 전체에 흩어져 있는 일회성 기능 이상일 수 있지만 조건부 논리와 코드에서 뷰를 자유롭게 유지하는 복잡한 마크업을 쉽게 생성하는 강력한 메서드가 있다면 어떨까요?

친숙한 Twitter Bootstrap 프레임워크와 좋은 구식 객체 지향 프로그래밍을 사용하여 이미지 캐러셀을 구축할 때 이 작업을 수행하는 방법을 살펴보겠습니다.

Rails 도우미를 사용해야 하는 경우

Rails의 뷰 레이어에는 프리젠터, 데코레이터, 부분, 헬퍼 등 다양한 디자인 패턴을 사용할 수 있습니다. 간단한 경험 법칙은 특정 구조, 특정 CSS 클래스, 조건부 논리 또는 여러 페이지에서 재사용이 필요한 HTML 마크업을 생성하려는 경우 도우미가 훌륭하게 작동한다는 것입니다.

Rails 도우미의 가장 좋은 예는 입력 필드, 선택 태그, 레이블 및 기타 HTML 구조를 생성하기 위한 모든 관련 메서드와 함께 FormBuilder 에서 보여줍니다. 이러한 유용한 방법은 모든 관련 속성이 올바르게 설정된 마크업을 생성합니다. 이와 같은 편리함이 우리 모두가 처음에 Rails와 사랑에 빠진 이유입니다.

잘 만들어진 도우미를 사용하면 캡슐화, 코드 반복 감소(DRY), 논리를 보기에 보이지 않는 등 잘 작성된 깨끗한 코드와 동일하게 사용할 수 있습니다.

Twitter 부트스트랩 캐러셀 분석

Twitter 부트스트랩은 모달, 탭 및 이미지 캐러셀과 같은 공통 구성 요소에 대한 지원이 내장된 널리 사용되는 프런트 엔드 프레임워크입니다. 이러한 부트스트랩 구성 요소는 마크업이 고도로 구조화되어 있고 JavaScript가 작동하려면 특정 클래스, ID 및 데이터 속성을 올바르게 설정해야 하며 이러한 속성을 설정하려면 약간의 조건부 논리가 필요하기 때문에 사용자 지정 도우미의 훌륭한 사용 사례입니다.

Bootstrap 3 캐러셀에는 다음 마크업이 있습니다.

 <div class="carousel slide" data-ride="carousel"> <!-- Indicators --> <ol class="carousel-indicators"> <li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li> <li data-target="#carousel-example-generic" data-slide-to="1"></li> <li data-target="#carousel-example-generic" data-slide-to="2"></li> </ol> <!-- Wrapper for slides --> <div class="carousel-inner"> <div class="item active"> <img src="..." alt="..."> </div> <div class="item"> <img src="..." alt="..."> </div> ... </div> <!-- Controls --> <a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"> <span class="glyphicon glyphicon-chevron-left"></span> </a> <a class="right carousel-control" href="#carousel-example-generic" data-slide="next"> <span class="glyphicon glyphicon-chevron-right"></span> </a> </div>

보시다시피, (1) 표시기 (2) 이미지 슬라이드 (3) 슬라이드 컨트롤의 세 가지 주요 구조가 있습니다.

하단(표시기) 근처에 3개의 작은 원이 있는 중앙 와이드스크린 비율 직사각형(슬라이드)을 보여주는 청사진. 양쪽에는 각각 왼쪽 및 오른쪽 화살표가 있는 두 개의 얇은 직사각형(컨트롤)이 있습니다.
부트스트랩 캐러셀의 일부입니다.

목표는 데이터, id , href 속성 및 CSS 클래스가 모두 올바르게 설정되도록 하여 이미지 컬렉션을 가져오고 이 전체 캐러셀 구성 요소를 렌더링하는 단일 도우미 메서드를 빌드할 수 있도록 하는 것입니다.

도우미

도우미의 기본 개요부터 시작하겠습니다.

 # app/helpers/carousel_helper.rb module CarouselHelper def carousel_for(images) Carousel.new(self, images).html end class Carousel def initialize(view, images) @view, @images = view, images end def html # TO FILL IN end private attr_accessor :view, :images end end

도우미 메서드 carousel_for 는 주어진 이미지 URL에 대한 완전한 캐러셀 마크업을 반환합니다. Carousel 러셀의 각 부분을 렌더링하기 위해 개별 메서드 모음을 구축하는 대신(각 메서드에 이미지 컬렉션 및 기타 상태 저장 정보를 전달해야 함) 캐러셀 데이터를 나타냅니다. 이 클래스는 완전히 렌더링된 마크업을 반환하는 html 메서드를 노출합니다. 이미지 URL images 컬렉션과 뷰 컨텍스트 view 초기화합니다.

view 매개변수는 모든 Rails 도우미가 혼합되어 있는 ActionView 의 인스턴스입니다. link_to , content_tag , image_tagsafe_join 과 같은 Rails의 내장 도우미 메서드에 액세스하기 위해 이를 객체 인스턴스에 전달합니다. 이 메서드는 클래스 내에서 마크업을 작성하는 데 사용할 것입니다. view 를 참조하지 않고 해당 메서드를 직접 호출할 수 있도록 delegate 매크로도 추가합니다.

 def html content = view.safe_join([indicators, slides, controls]) view.content_tag(:div, content, class: 'carousel slide') end private attr_accessor :view, :images delegate :link_to, :content_tag, :image_tag, :safe_join, to: :view def indicators # TO FILL IN end def slides # TO FILL IN end def controls # TO FILL IN end

캐러셀이 3개의 개별 구성요소로 구성되어 있다는 것을 알고 있으므로 결국 각각에 대한 마크업을 제공할 메서드를 제거한 다음 html 메서드가 이들을 컨테이너 div 태그에 결합하여 캐러셀 자체에 필요한 부트스트랩 클래스를 적용하도록 합시다.

safe_join 은 문자열 컬렉션을 연결하고 결과에 대해 html_safe 를 호출하는 편리한 내장 메서드입니다. 인스턴스를 생성할 때 전달한 view 매개변수를 통해 해당 메소드에 액세스할 수 있음을 기억하십시오.

먼저 지표를 구축합니다.

 def indicators items = images.count.times.map { |index| indicator_tag(index) } content_tag(:ol, safe_join(items), class: 'carousel-indicators') end def indicator_tag(index) options = { class: (index.zero? ? 'active' : ''), data: { target: uid, slide_to: index } } content_tag(:li, '', options) end

표시기는 컬렉션의 각 이미지에 대한 목록 항목 li 요소가 있는 간단한 정렬된 목록 ol 입니다. 현재 활성화된 이미지 표시기는 active CSS 클래스가 필요하므로 생성한 첫 번째 표시기에 대해 설정되어 있는지 확인합니다. 이것은 일반적으로 보기 자체에 있어야 하는 논리의 좋은 예입니다.

표시기는 포함하는 캐러셀 요소의 고유 id 를 참조해야 합니다(페이지에 캐러셀이 두 개 이상 있는 경우). 이니셜라이저에서 이 id 를 쉽게 생성하고 클래스의 나머지 부분에서 사용할 수 있습니다(특히 표시기 및 컨트롤 내에서). 도우미 메서드 내에서 프로그래밍 방식으로 이 작업을 수행하면 id 가 캐러셀 요소에서 일관되게 유지됩니다. 작은 오타나 한 곳에서 id 를 변경하고 다른 곳에서는 변경하지 않아 캐러셀이 깨지는 경우가 많습니다. 모든 요소가 자동으로 동일한 id 를 참조하기 때문에 여기서는 발생하지 않습니다.

 def initialize(view, images) # ... @uid = SecureRandom.hex(6) end attr_accessor :uid

다음은 이미지 슬라이드입니다.

 def slides items = images.map.with_index { |image, index| slide_tag(image, index.zero?) } content_tag(:div, safe_join(items), class: 'carousel-inner') end def slide_tag(image, is_active) options = { class: (is_active ? 'item active' : 'item'), } content_tag(:div, image_tag(image), options) end

Carousel 인스턴스에 전달한 각 이미지를 반복하고 item CSS 클래스와 함께 div 에 래핑된 이미지 태그인 적절한 마크업을 생성하고 active 클래스를 처음 생성하는 클래스에 다시 추가해야 합니다.

마지막으로 이전/다음 컨트롤이 필요합니다.

 def controls safe_join([control_tag('left'), control_tag('right')]) end def control_tag(direction) options = { class: "#{direction} carousel-control", data: { slide: direction == 'left' ? 'prev' : 'next' } } icon = content_tag(:i, nil, class: "glyphicon glyphicon-chevron-#{direction}") control = link_to(icon, "##{uid}", options) end

우리는 이미지 사이에서 앞뒤로 회전하는 회전 목마의 움직임을 제어하는 ​​링크를 만듭니다. uid 의 사용법에 다시 주목하십시오. 캐러셀 구조 내의 모든 다른 위치에서 올바른 ID를 사용하지 않는 것에 대해 걱정할 필요가 없으며 자동으로 일관되고 고유합니다.

완제품:

이것으로 캐러셀 도우미가 완성되었습니다. 전체 내용은 다음과 같습니다.

 # app/helpers/carousel_helper.rb module CarouselHelper def carousel_for(images) Carousel.new(self, images).html end class Carousel def initialize(view, images) @view, @images = view, images @uid = SecureRandom.hex(6) end def html content = safe_join([indicators, slides, controls]) content_tag(:div, content, id: uid, class: 'carousel slide') end private attr_accessor :view, :images, :uid delegate :link_to, :content_tag, :image_tag, :safe_join, to: :view def indicators items = images.count.times.map { |index| indicator_tag(index) } content_tag(:ol, safe_join(items), class: 'carousel-indicators') end def indicator_tag(index) options = { class: (index.zero? ? 'active' : ''), data: { target: uid, slide_to: index } } content_tag(:li, '', options) end def slides items = images.map.with_index { |image, index| slide_tag(image, index.zero?) } content_tag(:div, safe_join(items), class: 'carousel-inner') end def slide_tag(image, is_active) options = { class: (is_active ? 'item active' : 'item'), } content_tag(:div, image_tag(image), options) end def controls safe_join([control_tag('left'), control_tag('right')]) end def control_tag(direction) options = { class: "#{direction} carousel-control", data: { slide: direction == 'left' ? 'prev' : 'next' } } icon = content_tag(:i, '', class: "glyphicon glyphicon-chevron-#{direction}") control = link_to(icon, "##{uid}", options) end end end

행동하는 도우미:

마지막으로 요점을 파악하기 위해 이 도우미가 어떻게 우리의 삶을 더 쉽게 만들 수 있는지에 대한 간단한 예를 살펴보겠습니다. 아파트 임대 목록을 위한 웹사이트를 구축하고 있다고 가정해 보겠습니다. 각 Apartment 개체에는 이미지 URL 목록이 있습니다.

 class Apartment def image_urls # ... end end

carousel helper를 사용하면 carousel_for를 한 번만 호출하여 전체 Bootstrap carousel_for 을 렌더링할 수 있습니다. 보기에서 상당히 복잡한 논리를 완전히 제거합니다.

 <% apartment = Apartment.new %> # ... <%= carousel_for(apartment.image_urls) %> 

Rails 보기 도우미를 언제 사용해야 하는지 잘 모르십니까? 여기 데모가 있습니다.

트위터

결론

이 간단하면서도 강력한 기술을 사용하여 상당한 양의 마크업과 로직을 뷰 레이어에서 벗어나 carousel_for(some_images) 호출만으로 어디에서나 carousel 구성 요소를 렌더링하는 데 사용할 수 있는 도우미 함수로 옮겼습니다. . 이 일반 도우미는 Twitter Bootstrap을 사용할 때마다 모든 Rails 프로젝트에서 사용할 수 있습니다. 가장 중요한 것은 이제 프로젝트별 구성 요소에도 사용할 수 있는 새로운 도구가 툴킷에 있다는 것입니다.

따라서 다음에 같은 종류의 마크업을 입력하고 다시 입력하고 뷰에 조건부 논리를 포함하는 자신을 발견할 때 도우미 함수가 여러분의 삶을 더 쉽게 만들기 위해 작성되기를 기다리고 있는지 확인하십시오.