【问题标题】:Filter a model's attributes before outputting as json在输出为 json 之前过滤模型的属性
【发布时间】:2010-12-29 01:50:31
【问题描述】:

我需要将我的模型输出为 json,一切正常。但是,有些属性需要通过一些辅助方法过滤来“美化”它们,例如number_to_human_size。我该怎么做呢?

换句话说,假设我有一个名为bytes 的属性,我想将它传递给number_to_human_size 并将 结果输出到json。

如果可能的话,我还想“修剪”输出为 json 的内容,因为我只需要一些属性。这可能吗?有人可以给我一个例子吗?我真的很感激。

初步搜索结果暗示了一些关于as_json 的内容,但我找不到与我的情况相关的具体示例。如果这真的是解决方案,我真的很感激一个例子。

研究:看来我可以使用to_json 的选项来明确说明我想要哪些属性,但我仍然需要弄清楚如何“美化”或“过滤”某些属性,在它们作为 json 输出之前通过帮助器传递它们。

我是否会为单个 json 模型创建一个局部,所以 _model.json.erb,然后为我正在使用的操作创建另一个,并在其中简单地用对象集合渲染局部?似乎要跳过一堆箍。我想知道是否有更直接/原始的方式来改变模型的 json 表示。

【问题讨论】:

  • 您正在显示您的 json?喜欢在视图中?如果有,怎么会?
  • 对不起,如果这是您的推断。不,我不是。我基本上是在尝试改变我的模型变成 json 对象的方式。到目前为止,我已经想出了 >a

标签: ruby-on-rails json html-helper


【解决方案1】:

您的模型可以覆盖 as_json 方法,Rails 在渲染 json 时使用该方法:

# class.rb
include ActionView::Helpers::NumberHelper
class Item < ActiveRecord::Base
  def as_json(options={})
    { :state => state, # just use the attribute when no helper is needed
      :downloaded => number_to_human_size(downloaded)
    }
  end
end

现在您可以在控制器中调用render :json

@items = Item.all
# ... etc ...
format.json { render :json => @items }

Rails 将为 @items 的每个成员调用 Item.as_json 并返回一个 JSON 编码的数组。

【讨论】:

  • 这似乎更自然,或者更确切地说,是我在回答中所做的传统方式。我会根据你的解决方案进行调整,看看效果如何。
  • 这是一个插入式修改。我只需要将我的哈希构建代码移动到 as_json ,一切都会按预期继续工作。我确实注意到 options 参数,这是否意味着我可以在给定参数的情况下呈现对象的不同“版本”?例如,如果我想要一个只有最低限度的“裸”对象,我可以渲染它,否则它会渲染完整的东西,我可以这样做吗?我只是检查该选项是否存在以及它是否设置正确,但是当我实际渲染它时如何传递该选项?
  • 我认为我只是将选项传递给对 as_json 的显式调用,对吗?所以渲染 :son => @items.as_json(:bare => true)。另外,我应该以任何方式调用 super 吗?怎么样?
  • options 在那里,因此您可以执行 .to_json(:only=&gt;:name) 等,如 API 中所述(api.rubyonrails.org - 请参阅 ActiveModel::Serializers::JSON。我没有看到为什么你需要这样做,或者需要调用super,除非你需要处理这些情况。调用 super 只是方法super,或者super(my_options),如果你需要改变选项。
【解决方案2】:

我想出了一个解决这个问题的方法,但我不知道它是否是最好的。我将不胜感激。

@items = Item.all

@response = []

@items.each do |item|
  @response << {
      :state => item.state,
      :lock_status => item.lock_status,
      :downloaded => ActionController::Base.helpers.number_to_human_size(item.downloaded),
      :uploaded => ActionController::Base.helpers.number_to_human_size(item.uploaded),
      :percent_complete => item.percent_complete,
      :down_rate => ActionController::Base.helpers.number_to_human_size(item.down_rate),
      :up_rate => ActionController::Base.helpers.number_to_human_size(item.up_rate),
      :eta => item.eta
  }
end

respond_to do |format|
  format.json { render :json => @response }
end

基本上,我使用我想要的值动态构造一个哈希,然后渲染 that。它有效,但就像我说的那样,我不确定这是否是最好的方法。

【讨论】:

    猜你喜欢
    • 2011-09-08
    • 2017-05-05
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-23
    • 2020-12-21
    相关资源
    最近更新 更多