【问题标题】:Rails Image assets in AngularJS Directive and templateAngularJS 指令和模板中的 Rails 图像资产
【发布时间】:2014-05-23 16:13:09
【问题描述】:

我有使用这些 gem 的带有 AngularJS 的 Rails 4 应用程序:

  • gem 'angularjs-rails'
  • gem 'angular-rails-templates'
  • gem 'asset_sync'

这样的模板效果很好:

    <img ng-controller='LikePostController'  
       ng-dblclick='like(post);' 
       ng-src='{{post.photo.standard}}' 
       class='lazy post_photo pt_animate_heart'
       id='post_{{post.id}}_image'
     />

图像正确渲染。但是在我的其他 js 中

petto.directive('ptAnimateHeart', ['Helper', function(Helper){
    linkFunc = function(scope, element, attributes) {
      $heartIcon = $("#heart_icon");

      if($heartIcon.length == 0) {
        $heartIcon = $("<img id='heart_icon' src='/assets/feed.icon.heart.png' alt='Like' /> ");
        $(document.body).append($heartIcon);
      }

      element.on('dblclick', function(event){
        $animateObj = $(this);
        Helper.animateHeart($animateObj);
      });
    }
    return { 
      restrict: 'C',
      link: linkFunc
    }

  }])

我从浏览器控制台收到“assets/feed.icon.heart.png”未找到错误。我在 app/assets/feed.icon.heart.png 下有 feed.icon.heart.png。

ps:忘了提我使用资产同步 gem 来托管 amazon s3 中的资产。该图像在开发中运行良好,但在生产中运行不佳。

【问题讨论】:

    标签: ruby-on-rails angularjs asset-sync


    【解决方案1】:

    硬编码资产链接仅在开发中有效,因为在生产中资产会被预编译。这意味着,除其他外,文件名从以下位置更改:

    my_image.png

    变成这样的东西(它添加了唯一的 md5-hash):

    "my_image-231a680f23887d9dd70710ea5efd3c62.png"

    试试这个:

    将 javascript 文件扩展名更改为:yourjsfile.js.erb

    以及以下链接:

    $heartIcon = $("&lt;img id='heart_icon' src='&lt;%= image-url("feed.icon.heart.png") %&gt;' alt='Like' /&gt; ");

    为了更好地理解The Asset Pipeline — Ruby on Rails Guides

    【讨论】:

    • 你将如何在循环中执行此操作? image_url 在 javascript 插值中不起作用。
    • 它帮助了我。唯一要提的:我需要使用image_url 而不是imge-url,我使用的是Rails 4.2.6
    【解决方案2】:

    您可以在帮助程序的某处定义以下方法,例如在app/helpers/application_helper.rb:

    def list_image_assets(dir_name)
      path = File.expand_path("../../../app/assets/images/#{dir_name}", __FILE__)
      full_paths = Dir.glob "#{path}/**.*"
      assets_map = {}
      full_paths.each do |p|
        original_name = File.basename p
        asset_path    = asset_path p[p.index("#{dir_name}")..-1]
        assets_map[original_name] = asset_path
      end
      assets_map.to_json
    end
    

    您可以修改该方法以使用您希望使用的任何资产,而不仅仅是位于 app/assets/images 子目录中的资产,如本例所示。该方法将返回一个映射,其中所有原始资产名称作为键,它们的“编译”名称作为值。

    返回的地图可以通过ng-init 传递给任何角度控制器(一般不推荐,但在这种情况下合适):

    <div ng-controller="NoController" ng-init="assets='<%=list_image_assets "images_dir_name"%>'"></div>
    

    要使资产真正在 Angular 中可用,请在控制器中定义一个新的 $scope 变量:

    $scope.$watch('assets', function(value) {
      if (value) {
        $scope.assets = JSON.parse(value);
      }
    });
    

    $scope 中有这个,就可以像往常一样使用资产名称,例如ng-src 指令,这不会在预编译过程后刹车。

    <img ng-src={{::assets['my_image.png']}}/>
    

    【讨论】:

    • 我喜欢这个解决方案,这是唯一一个不使用.erb 并且不将图像直接放入public 目录的解决方案。但这似乎仍然太痛苦了
    • 很好的解决方案 A)它迫使您了解一些底层资产编译过程和 B)如果您只需要传入一小组资产,您可以使用它的变体。当您发现自己一直在这样做时,使用“gon”gem 可能会有意义。
    【解决方案3】:

    只需执行以下操作:

    app.run(function($rootScope,$location){
    $rootScope.auth_url = "http://localhost:3000"   
    $rootScope.image_url = $rootScope.auth_url + "/uploads/user/image/"
    });
    

    在控制器中为$rootScope注入dependency 并在视图中

    <img ng-src="{{user.image.url}}" width="100px" height="100px">
    

    注意:它在 Rails API 中运行良好,它假定您有可用的用户对象,以便它可以在 /uploads/image/ 目录中指定正确的图像

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多