2

我花了很多时间研究 sprockets 和 tit 的源代码,试图弄清楚如何将变量/绑定传递给 Erb 评估上下文。这就是我想要做的事情:我需要提供一个 JS 文件,其内容会根据每个请求而改变。更改的部分取决于存储在数据库中的数据,因此需要通过 Rails 应用程序路由请求并需要传递变量/绑定。最重要的是,JS 文件使用require指令插入其他 JS 文件,因此需要使用 sprockets。

这是不起作用的代码段:

控制器文件:

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_changed.js:

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

// Some code that uses @foobars

我怎样才能完成这项工作?任何帮助,将不胜感激。

4

2 回答 2

0

我正在努力完成与您相同的事情。我发现您的控制器代码片段存在一些问题。而不是做一个instance_evalon the Sprockets::Environment,你应该class_evalthe 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

而不是自己设置内容类型。

于 2013-02-01T20:09:29.743 回答
0

JavaScript 文件应该是完全静态的;Sprockets 并不意味着做你想做的事。

在每个请求的基础上更改的任何数据都应写入<script>您正在呈现的模板底部的标签。

应用程序/资产/javascripts/user.js

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

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

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

应用程序/视图/用户/show.html.erb

...

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

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

如果您可以围绕您的特定用例提供更多上下文,我可以举一个更具体的例子。

于 2012-11-03T18:16:21.873 回答