【问题标题】:Sprockets > How to specify a binding for Erb evaluation / rendering?Sprockets > 如何为 Erb 评估/渲染指定绑定?
【发布时间】:2013-02-02 04:09:29
【问题描述】:

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

这是无效的代码 sn-p:

控制器文件:

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

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

// Some code that uses @foobars

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

【问题讨论】:

    标签: ruby-on-rails-3 sprockets tilt


    【解决方案1】:

    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>
    

    如果您可以针对您的特定用例提供更多背景信息,我可以举一个更具体的示例。

    【讨论】:

    • 感谢您的回答 ssorallen。不幸的是,就我而言,没有关联的模板文件。让我解释。有问题的 JS 可以被应用程序的各种用户用来在他们的网站上呈现一个小部件。 (想想人们在他们的网站上安装的实时聊天小部件)。现在每个用户可能有不同的设置 + 需要引用到 JS 文件中的数据。我想将 JS 的静态部分和 JS 的动态部分包装到一个文件中并提供它。这有意义吗?
    • Google Maps 等 JavaScript API 为每个客户端提供相同的 JS,并要求客户端实例化他们想要的对象和 API。
    • 如果您真的想要一个动态的 JavaScript 文件,请将您的模板命名为 .js.erb,Rails 将为请求返回正确的 JavaScript MIME 类型。它应该位于app/views 而不是app/assets
    • 我不能要求客户以他们喜欢的方式实例化对象,因为那样会变得过于技术化。理想情况下,客户会使用 web-UI 来更改设置,并且在他/她的网站中只包含一个 JS 文件。
    • 如果我使用.js.erb 文件,我可以在顶部使用//= require 指令吗?我需要最终的 JS 文件是 3-4 个其他 JS 文件 + 动态位的串联版本。
    【解决方案2】:

    我正在努力完成与您相同的事情。我发现您的控制器代码 sn-p 存在一些问题。与其在Sprockets::Environment 上执行instance_eval,不如在class_eval 上执行context_class,如Sprockets::Context documentation 所示。

    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
    

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

    【讨论】:

      猜你喜欢
      • 2016-07-23
      • 1970-01-01
      • 1970-01-01
      • 2020-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多