Sprockets › Как да задам обвързване за оценка/изобразяване на Erb?

Прекарах много време в изходния код на sprockets и tit, опитвайки се да разбера как да предам променливи/обвързвания към контекста за оценка на Erb. Ето какво се опитвам да направя: Трябва да обслужвам JS файл, чието съдържание се променя на базата на заявка. Частите, които се променят, зависят от данните, съхранявани в DB, ​​оттук и необходимостта от маршрутизиране на заявки през приложението Rails и необходимостта от предаване на променливи/обвързвания. Освен това JS файлът използва директивите require за вмъкване на други JS файлове, поради което е необходимо да се използват зъбни колела.

Ето кодовия фрагмент, който не работи:

Файл на контролера:

def ever_changing_js
  @foobars = Foobar.all
  MyApp::Application.assets.instance_eval do
    def foobars
      @foobars
    end
  end

  render :text => MyApp::Application.assets.find_asset('ever_changing.js').to_s, :content_type => "application/javascript"
end

ever_changing.js:

//= require file1.js
//= require file2.js

// Some code that uses @foobars

Как мога да направя това? Всяка помощ ще бъде оценена.


person Saurabh Nanda    schedule 15.09.2012    source източник


Отговори (2)


JavaScript файловете трябва да са напълно статични; Sprockets не е предназначен да прави това, което се опитвате да направите.

Всички данни, които се променят на базата на заявка, трябва да бъдат записани в етикет <script> в долната част на шаблона, който изобразявате.

app/assets/javascripts/user.js

(function(exports) {
  function User(name) {
    this.name = name;
  }

  User.prototype.speak() {
    console.log(this.name + ' says, "Hello!"');
  };

  exports.User = User;
})(this);

app/views/users/show.html.erb

...

  <%= javascript_include_tag('user') %>
  <script>
    (function() {
      var user = new User(<%= @user.name %>);

      $('#speak-button').click(function() {
        user.speak();
      });
    })();
  </script>
</html>

Ако можете да дадете повече контекст около вашия конкретен случай на употреба, мога да дам по-конкретен пример.

person Ross Allen    schedule 03.11.2012
comment
Благодаря за отговора ssorallen. За съжаление в моя случай няма асоцииран файл с шаблон. Нека обясня. Въпросният JS може да се използва от различни потребители на приложението, за да изобразят джаджа на техния уебсайт. (Помислете за джаджа за чат на живо, която хората инсталират на уебсайтовете си). Сега всеки потребител може да има различни настройки + данни, които трябва да бъдат посочени в JS файла. Искам да обвия статичната част на JS и динамичната част на JS в един файл и да го обслужвам. Това има ли смисъл? - person Saurabh Nanda; 04.11.2012
comment
API на JavaScript, като Google Maps, обслужват един и същ JS на всеки клиент и изискват от клиента да инстанцира обектите и API, които иска. - person Ross Allen; 04.11.2012
comment
Ако наистина искате динамичен JavaScript файл, наименувайте вашия шаблон като .js.erb и Rails ще върне правилния MIME тип за JavaScript за заявката. Трябва да живее в app/views вместо в app/assets. - person Ross Allen; 04.11.2012
comment
Не мога да помоля клиента да инстанцира обекти по начина, по който им харесва, защото това би станало твърде техническо. В идеалния случай клиентът би използвал уеб интерфейс, за да промени настройките и би включил само един JS файл в своя уебсайт. - person Saurabh Nanda; 04.11.2012
comment
Ако използвам .js.erb файл, мога ли да използвам //= require директиви отгоре? Имам нужда крайният JS файл да бъде свързана версия на 3-4 други JS файла + динамичните битове. - person Saurabh Nanda; 04.11.2012

Опитвам се да постигна същото, което и ти. Виждам няколко проблема с кодовия фрагмент на вашия контролер. Вместо да правите instance_eval на Sprockets::Environment, трябва да class_eval context_class, както е показано в Sprockets::Context документация.

MyApp::Application.assets.context_class.class_eval do
  def foobars
    @foobars
  end
end

Тогава foobars ще бъде достъпен за вашия ERb шаблон.

Като странична бележка можете да направите

render js: MyApp::Application.assets.find_asset('ever_changing.js').to_s

вместо сами да задавате типа съдържание.

person Adam Stegman    schedule 01.02.2013