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.cssapplication.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.