Rails 3 앱에서 페이지 특정 JavaScript를 추가하는 가장 좋은 방법은?


159

Rails 3에는 눈에 잘 띄지 않는 JavaScript가 있습니다.

그러나 특정 페이지에 추가 JavaScript를 포함시키는 가장 좋은 방법이 무엇인지 궁금했습니다.

예를 들어, 이전에 수행 한 위치는 다음과 같습니다.

<%= f.radio_button :rating, 'positive', :onclick => "$('some_div').show();" %>

우리는 이제 다음과 같이 방해하지 않게 만들 수 있습니다

<%= f.radio_button :rating, 'positive' %>

# then in some other file
$('user_rating_positive').click(function() {
  $('some_div').show();
}

그래서 내 질문은 JavaScript를 어디에 / 어떻게 포함시켜야하는지 생각합니다. application.js이 JavaScript는이 하나의보기에만 적용되므로 파일 을 채우고 싶지 않습니다 . 어떻게 든 각 페이지에 대한 사용자 정의 JavaScript 파일을 포함시켜야합니까, 아니면 헤더가 찾는 인스턴스 변수에 고정해야합니까?



이것이 어떻게 작동하고 무엇이 최선인지에 대한 완전한 이해를 원하는 사람들을 위해 railsapps.github.io/rails-javascript-include-external.html을 읽으 십시오 . 이것은 지금까지이 주제에서 본 최고의 문서입니다. Rails뿐만 아니라 웹 개발자를 다루는 모든 사람에게 큰 도움이됩니다. 이것이 레일 방식으로 일을하는 것이 가장 좋은 이유입니다. 앞으로의 질문에 Unholy Rails를 사용할 것입니다. 와.
— DutGRIFF

2
@KateGregory는 새로운 것입니다.
— Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

답변:


153

내가하고 싶은 것은 content_for :head블록 당 뷰당 Javascript를 포함하고 yield응용 프로그램 레이아웃에서 해당 블록을 포함하는 것입니다. 예를 들어

꽤 짧은 경우 :

<% content_for :head do %>
  <script type="text/javascript">
    $(function() {
      $('user_rating_positve').click(function() {
        $('some_div').show();
      }
    });
  </script>
<% end %>

또는 더 긴 경우 :

<% content_for :head do %>
  <script type="text/javascript">
    <%= render :partial => "my_view_javascript"
  </script>
<% end %>

그런 다음 레이아웃 파일에서

<head>
  ...
  <%= yield :head %>
</head>

40
왜 사용하지 <%= javascript_include_tag "my_javascipt_file" %> 않습니까?
— AJP

5
@AJP 나는 그것이 자산 파이프 라인의 목적을 무너 뜨린다 고 생각한다
— lulalala

2
@lulalala 그러나 대답의 코드는 어쨌든 지저분한 방식으로 수행합니까?
— AJP

8
@ AJP 더 지저분하지만 대답보다 http 요청이 적습니다.
— lulalala


103

한 페이지에만 자바 스크립트를 포함하려면 페이지 인라인에 자바 스크립트를 포함시킬 수 있지만 자바 스크립트를 그룹화하고 자산 파이프 라인, 축소 된 js 등을 활용하려는 경우 추가 할 수 있으며 추가 할 수 있습니다 js 자산을 사이트의 특정 컨트롤러 /보기 / 섹션에만 적용되는 그룹으로 분할하여 특정 페이지에만 결합되고로드되는 js 자산.

자산의 js를 각각 별도의 매니페스트 파일과 함께 폴더로 이동하므로 백엔드에서만 사용되는 admin js 라이브러리가있는 경우 다음을 수행 할 수 있습니다.

  • 자산
    • 자바 스크립트
      • 관리자
        • ... js
      • admin.js (관리자 그룹의 매니페스트)
      • application.js (앱 글로벌 그룹을위한 매니페스트)
      • 글로벌
        • ... js

기존 application.js에서

//= require jquery
//= require jquery_ujs
//= require_tree ./global // requires all js files in global folder

새로운 admin.js 매니페스트 파일

//= require_tree ./admin // requires all js files in admin folder

config / production.rb를 편집하여이 새로운 js manifest를로드하십시오.

config.assets.precompile += %w( admin.js )

그런 다음 페이지 레이아웃에 추가 j를 포함시킬 수 있도록 페이지 레이아웃을 조정하십시오.

<%= content_for :header %>   

그런 다음이 특정 js 그룹 (및 일반 응용 프로그램 그룹) 및 / 또는 페이지 특정 js, css 등을 포함하려는보기에서 :

<% content_for :header do %>
  <%= javascript_include_tag 'admin' %>  
<% end %>

물론 CSS로 동일한 작업을 수행하고 사이트의 특정 영역에만 적용하기 위해 비슷한 방식으로 그룹화 할 수 있습니다.


모든 매니페스트를 동일한 위치에 유지하면 레일에 해당 폴더의 모든 것을 미리 컴파일하도록 지시 할 수 있습니다. 그런 식으로 production.rb를 한 번만 편집하면 추가 한 내용을 추적하지 않아도됩니다.
— 방해받지 않음

그렇게 할 수 있다는 것을 몰랐습니다. 따라서 개별 js 그룹뿐만 아니라 매니페스트가 포함 된 'manifests'폴더를 가질 수 있습니까? 나는 이것을 시도 할 수 있습니다. 모든 js를 모든 곳에서 가져온 하나의 큰 파일로 가져 오는 것으로 가정하기 때문에 기본적으로 약간 더 깔끔한 설정을 원합니다.
— Kenny Grant

이상하게도를 사용하면 Sprockets :: FileNotFound 오류가 발생 //= require_tree ./global하지만 //= require_directory ./globalRails 3.2.12를 사용하면 사용 하지 않습니다 .
— qix

2
많은 스크립트 태그가 생길 것 같습니다. 자산 파이프 라인의 목표는 하나의 스크립트 태그를 갖는 것이라고 생각 했습니까? 페이지에 맞게 자바 스크립트를 작성합니다.
— Ziggy

1
이해가가는 것 같네요. 추가 스크립트 태그를 피하는 것은 페이지로드 시간에 매우 중요합니다.
— Ziggy

12

이 답변은 나에게 도움이되었습니다! 누군가가 조금 더 원한다면 ...

  1. 미리 컴파일하려면 자바 스크립트를 매니페스트에 넣어야합니다. 그러나 모든 javascript 파일이 필요한 경우 application.js.coffee다른 페이지로 이동할 때마다 모든 javacsripts가로드되고 페이지 별 javascript를 수행하는 목적이 무효화됩니다.

따라서 speciifc.js모든 페이지 별 자바 스크립트 파일이 필요한 고유 한 매니페스트 파일 (예 :)을 만들어야합니다 . 또한, 수정 require_tree에서application.js

app / assets / javascripts / application.js

//= require jquery
//= require jquery_ujs
//= require_tree ./global

app / assets / javascripts / specific.js

//= require_tree ./specific

그런 다음 environments/production.rbconfig 옵션을 사용하여이 매니페스트를 사전 컴파일 된 목록에 추가하십시오.

config.assets.precompile += %w( specific.js )

끝난! 항상로드해야하는 모든 공유 자바 스크립트는 app/assets/javascripts/global폴더에 배치되고 page-spcific 자바 스크립트는에 배치 app/assets/javascripts/specific됩니다. 뷰에서 페이지 별 자바 스크립트를 호출하면됩니다.

<%= javascript_include_tag "specific/whatever.js" %> //.js는 선택 사항입니다.

이것으로 충분하지만 나도 사용하고 싶었다 javascript_include_tag params[:controller]. 컨트롤러를 만들면 app/assets/javascripts언급 된 다른 사람들과 마찬가지로 관련 커피 스크립트 파일이 생성됩니다 . 진정 있습니다 컨트롤러 고유의 사용자가 특정 컨트롤러보기에 도달 할 경우에만로드 자바 스크립트는.

그래서 다른 매니페스트를 만들었습니다. controller-specific.js

app / assets / javascripts / controller-specific.js

//= require_directory .

여기에는 컨트롤러와 관련된 모든 자동 생성 커피 스크립트가 포함됩니다. 또한 미리 컴파일 된 목록에 추가해야합니다.

config.assets.precompile += %w( specific.js controller-specific.js )


자세한 답변을 주셔서 감사합니다. 이 줄을 어디에 두어야합니까 javascript_include_tag params[:controller]? 현재 내 application.html.erb에이 줄이 있습니다 javascript_include_tag 'application'. 이것을 다른 줄로 바꿔야합니까?
— simha

1
또한이 줄 <%= javascript_include_tag "specific/whatever.js" %>을 content_for :header블록 에 넣어야 합니까?
— simha

1
당신이 엉망이되는 것이 이상 config.assets.precompile합니다. app/assets/javascripts/*.js미리 컴파일 된 모든 것이 자동으로 컴파일 되지 않습니까?
— AlexChaffee

@AlexChaffee 자동으로 사용 가능한 파일은 application.css및 application.js입니다. 다른 파일은 다른 파일에 포함되거나을 사용하여 나열되어야합니다 config.assets.precompile. 자세한 내용은 여기
— Sung Cho

매니페스트 선언이 이동되었습니다. 레일 4.2.0을 실행하고 있습니다. 그리고 이것을 production.rb 파일에 주석 발견 #을 config.assets.precompile하고 config.assets.version이동 한을 설정 / 초기화 / assets.rb
— 커트

11

나는 다음을 선호합니다 ...

application_helper.rb 파일에서

def include_javascript (file)
    s = " <script type=\"text/javascript\">" + render(:file => file) + "</script>"
    content_for(:head, raw(s))
end

그런 다음 특정보기 (이 예에서는 app / views / books / index.html.erb)에서

<% include_javascript 'books/index.js' %>

... 나를 위해 일하는 것 같습니다.


9

필요한 파이프 라인 특정 자바 스크립트 (공감)를 얻기 위해 자산 파이프 라인이나 복잡한 해결 방법 을 사용하지 않으려는 경우 가장 단순하고 가장 강력한 방법으로 위의 답변과 동일하지만 코드는 적습니다. 사용하다:

<%= javascript_include_tag "my_javascipt_file" %>

참고 : 이것은 사용하는 답변보다 include 태그 당 하나 이상의 http 요청이 필요합니다. content_for :head


javascript_include_tag내가 찾던 정확히 무엇 환호는 AJP
— 톰 맥켄지

"my_javascipt_file"을 어디에 넣습니까? 자산 / 자바 스크립트에서? 그러나 그렇다면 //= require .application.js에서 자동으로 선택되지 않습니까?
— qix

@Linus yep, //= require .해당 스크립트를 사이트의 모든 페이지로 가져 오면 Kenny Grant (use //= require_tree ./global) 또는 bjg 제안 과 같은 작업을 수행해야합니다 .
— AJP

1
이것은 내가 변경, 나를 위해 가장 쉬운 방법으로했습니다 //= require_tree .에 //= require_directory .application.js에서 다음 자산 \ 자바 스크립트의 하위 디렉토리를 만들었습니다. 행을 추가하여 js를 사전 컴파일하려면 config \ initializers \ assets.rb에 새 디렉토리를 포함시켜야합니다.Rails.application.config.assets.precompile += %w( new_dir/js_file.js )
— Jonesy


3

자산 파이프 라인은 모든 js를 하나의 (최소화 된) 파일로 묶어서 페이지로드 시간을 줄이는 것을 의미합니다. 이것은 표면 상으로 모호한 것처럼 보일 수 있지만 실제로는 C 및 Ruby와 같은 인기있는 언어로 이미 존재하는 기능입니다. "include"태그와 같은 것은 파일의 다중 포함을 방지하고 프로그래머가 코드를 구성하는 데 도움을주기위한 것입니다. C로 프로그램을 작성하고 컴파일 할 때 해당 코드가 모두 실행중인 프로그램의 모든 부분에 존재하지만 해당 코드가 사용될 때 메소드는 메모리에만로드됩니다. 어떤 의미에서, 컴파일 된 프로그램에는 코드가 잘 모듈화되도록 보장하는 것이 포함되지 않습니다. 우리는 그런 식으로 프로그램을 작성하여 코드를 모듈화하고 운영 체제는 주어진 지역에 필요한 객체와 메소드 만 메모리에로드합니다. "방법 별 포함"과 같은 것이 있습니까? Rails 앱이 편안하다면 이것은 본질적으로 당신이 요구하는 것입니다.

페이지에서 HTML 요소의 동작을 향상시키기 위해 자바 스크립트를 작성하는 경우 해당 기능은 설계 상 '페이지 별'입니다. 문맥에 관계없이 실행되는 방식으로 작성한 복잡한 코드가있는 경우 어쨌든 해당 코드를 html 요소에 바인딩하는 것을 고려하십시오 ( Garber-Irish 메소드에 설명 된대로 body 태그를 사용할 수 있음 ). 함수가 조건부로 실행되면 성능이 모든 추가 스크립트 태그보다 작을 수 있습니다.

rails apps project에 설명 된대로 paloma gem 을 사용할 생각입니다 . 그런 다음 paloma 콜백에 페이지 별 함수를 포함시켜 자바 스크립트를 페이지별로 만들 수 있습니다.

Paloma.callbacks['users']['new'] = function(params){
    // This will only run after executing users/new action
    alert('Hello New Sexy User');
}; 

당신은 레일을 사용하므로 보석을 좋아한다는 것을 알고 있습니다 :)


3

Rails를 훌륭하게 만드는 중요한 기능을 잃어 버리기 때문에 자산 파이프 라인 외부에서 JS 또는 CSS 파일을로드해서는 안됩니다. 그리고 당신은 다른 보석이 필요하지 않습니다. 나는 가능한 한 적은 보석을 사용한다고 생각하며 여기서 보석을 사용할 필요는 없습니다.

원하는 것은 "컨트롤러 특정 Javascript"( "활동 특정 Javascript가 맨 아래에 포함되어 있습니다.)입니다.이를 통해 특정 컨트롤러에 대한 특정 JavaScript 파일을로드 할 수 있습니다. Javascript를보기에 연결하려고하는 것은 일종의 .. 뒤로하고 MVC 디자인 패턴을 따르지 않는 경우 컨트롤러와 컨트롤러 또는 컨트롤러 내부의 작업과 연결하려고합니다.

불행하게도, 어떤 이유로 든 Rails devs는 기본적으로 모든 페이지가 자산 디렉토리에있는 모든 JS 파일을로드 할 것이라고 결정했습니다. 기본적으로 "Controller Specific Javascript"를 활성화하는 대신이 작업을 수행하기로 결정한 이유는 알 수 없습니다. 이 작업은 application.js 파일을 통해 수행되며 기본적으로 다음 코드 줄이 포함됩니다.

//= require_tree .

이것을 지시문이라고 합니다. 이것이 스프라켓이 자산 / javascripts 디렉토리의 모든 JS 파일을로드하기 위해 사용하는 것입니다. 기본적으로 스프로킷은 application.js 및 application.css를 자동으로로드하며 require_tree 지시문은 모든 JS 및 Coffee 파일을 해당 디렉토리에로드합니다.

참고 : 비계를 사용하는 경우 (비계가 아닌 경우 이제 시작하기에 좋은시기입니다) Rails 는 해당 비계의 컨트롤러에 대해 자동으로 커피 파일을 생성합니다 . 커피 파일 대신 표준 JS 파일 을 생성 하려면 Gemfile 에서 기본적으로 활성화 된 커피 보석 을 제거하면 스캐 폴드가 대신 JS 파일을 생성합니다.

"Controller Specific Javascript"를 활성화 하는 첫 번째 단계 는 application.js 파일에서 require_tree 코드를 제거하거나 여전히 전역 JS 파일이 필요한 경우 asset / javascripts 디렉토리 내의 폴더로 변경하는 것입니다. IE :

//= require_tree ./global

2 단계 : config / initializers / assets.rb 파일로 이동하여 다음을 추가하십시오.

%w( controllerone controllertwo controllerthree ).each do |controller|
  Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
end

원하는 컨트롤러 이름을 삽입하십시오.

3 단계 : application.html.erb 파일에서 javascript_include_tag를 다음과 같이 바꿉니다 (params [: controller] 부분 참고 :

<%= javascript_include_tag 'application', params[:controller], 'data-turbolinks-track': 'reload' %>

서버와 비올라를 다시 시작하십시오! 스캐 폴드로 생성 된 JS 파일은 이제 해당 컨트롤러가 호출 될 때만로드됩니다.

컨트롤러의 특정 ACTION에 특정 JS 파일을로드해야 합니까? IE / articles / new ? 대신이 작업을 수행하십시오.

application.html.erb :

<%= javascript_include_tag "#{controller_name}/#{action_name}" if AppName::Application.assets.find_asset("#{controller_name}/#{action_name}") %>

config / initializers / assets.rb :

config.assets.precompile += %w(*/*)

그런 다음 자산 / 자바 스크립트 폴더에서 컨트롤러와 동일한 이름의 새 폴더를 추가하고 내부에 작업과 동일한 이름의 js 파일을 넣으십시오. 그런 다음 해당 특정 작업에로드합니다.


1

좋아, 아마도 이것은 최악의 작업과 같지만 .js 파일을 렌더링 한 컨트롤러 메소드를 만듭니다.

제어 장치

def get_script
   render :file => 'app/assessts/javascripts/' + params[:name] + '.js'
end
def get_page
   @script = '/' + params[:script_name] + '.js?body=1'
   render page
end

전망

%script{:src => @script, :type => "text/javascript"}

어떤 이유로 든 우리가 이것을하고 싶지 않다면 알려주십시오.


1

JS를 추가하는 기본 방법은 바닥 글에 있으므로 다음과 같이 할 수 있습니다.

show.html.erb :

<% content_for :footer_js do %>
   This content will show up in the footer section
<% end %>

layouts / application.html.erb

<%= yield :footer_js %>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.