【问题标题】:Can I render an image with json?我可以用 json 渲染图像吗?
【发布时间】:2015-03-30 04:15:33
【问题描述】:

我正在使用 Typeahead 在下拉列表中呈现我的“用户”模型的实例:

控制器:

def typeahead
  render json: User.where(name: params[:query])
end

查看:

<input type="text" id="typeahead">
<script type="text/javascript">
  var bloodhound = new Bloodhound({
    datumTokenizer: function (d) {
      return Bloodhound.tokenizers.whitespace(d.value);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,

    remote: '/typeahead/%QUERY', 
    limit: 50
  });
  bloodhound.initialize();

  $('#typeahead').typeahead(null, {
    displayKey: 'name',
    source: bloodhound.ttAdapter()
  });

  $('#typeahead').bind('typeahead:selected', function(event, datum, name) {
    doSomething(datum.id);
  });
</script>

此代码会在我键入时导致User.names 列表下拉。

我可以渲染图像吗,在这种情况下是User.avatar.url(:thumb)?当我将 displayKey: 'name', 更改为 displayKey: 'avatar.url(:thumb)', 时,下拉列表只是为每个用户显示“未定义”。

[我确保User.avatar.url(:thumb) 在其他地方成功显示]

【问题讨论】:

  • 您的 javascript 没有解释 ruby​​。它正在访问返回的 json 上的 name 键。如果您希望能够使用avatar,您将看到它是如何包含在 json 中的。假设paperclip,您将有一个avatar_file_name 键,但我对typeahead 不够熟悉,无法告诉您如何将该文件名转换为图像以显示在您的javascript 中。
  • @ptd 你认为至少有可能吗?

标签: javascript jquery ruby-on-rails json render


【解决方案1】:

displayKey 属性告诉 Typeahead 要显示 JSON 响应 的哪个(字符串)字段,因此它只能指向现有的 JSON 属性,例如name.

我建议不要渲染图像,而是提供它的 URL 作为响应的一部分,然后在浏览器中渲染它。

例如,您可以向 User 模型添加新方法:

def thumb_url
  avatar.url(:thumb)
end

将该方法的结果添加到控制器的响应中:

def typeahead
  render json: User.where(name: params[:query]), methods: :thumb_url
end

然后在Typeahead template 中使用响应而不是displayKey,例如

$('#typeahead').typeahead(null, {
  source: bloodhound.ttAdapter()
  templates: {
    suggestion: Handlebars.compile('<p><img src="{{thumb_url}}">{{name}}</p>')
  }
});

(请注意,您必须添加 Handlebars 才能使其正常工作。)

【讨论】:

    【解决方案2】:

    您需要在服务器上将图像编码为 base64,然后在 json 响应中返回结果字符串,最后在客户端使用此 base64 字符串填充您的图像

    1-服务器端:将图片编码为base64

    def typeahead
      users = User.where(name: params[:query])
    
      json = users.collect do |user|
        path = user.avatar.url(:thumb)
        image = open(path) { |io| io.read }
        base64 = ActiveSupport::Base64.encode64(image)
    
        {id: user.id, name: user.name, base64: base64}
      end
    
      render json: json
    end
    

    2-客户端:使用模板填充用户名和图片

    $('#typeahead').typeahead(null, {
      displayKey: 'name',
      source: bloodhound.ttAdapter()
      templates: {
        suggestion: Handlebars.compile('<p><img src="data:image/png;base64,{{base64}}">{{name}}</p>')
      }
    });
    

    注意1:未经测试,您可能需要做一些调整

    注意2:当您有一个大用户表和大量并发连接时,这将需要您的服务器提供大量电力,因为服务器必须为每个查询打开和编码许多图像文件。

    【讨论】:

      猜你喜欢
      • 2019-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-26
      • 1970-01-01
      • 2015-09-21
      相关资源
      最近更新 更多