【问题标题】:Jbuilder not wrapping single object in collectionJbuilder没有将单个对象包装在集合中
【发布时间】:2015-08-18 19:29:12
【问题描述】:

我的 Rails 应用程序中有一个索引视图,允许通过搜索参数进行过滤。当返回一个组操作文章时,它被包装在一个articles colllection 中,如{"articles":[{"article":{"id":341,"updated":"2015-08-18T13:05:08.427Z","title":"。但如果只找到一个对象,则缺少articles 级别,{"article":{"id":398,"updated":"2015-08-07T11:37:26.200Z","title":。如何修复它以使单个对象表现得像多个对象?

_articles.list.json.jbuilder

require 'uri'
require 'publish_on'
json.cache! ['v1', articles] do
  json.articles articles do |article|
    json.cache! ['v1', article] do
      json.article do
        json.id article.id
        json.updated as_ns_date(article.updated_at)
        json.title article.label
        json.numberOfViews article.view_mappings.count
        json.numberOfFavorites article.favorite_mappings.count
        json.imageURLs article.images if article.images.any?
        json.youtubeURL article.youtube unless article.youtube.blank?
        json.tags article.categories.map(&:label)
        json.isFeatured article.featured
        json.isPublished article.is_published
        json.published as_ns_date(article.publish_on)
      end
    end
  end
end

index.json.jbuilder

json.partial! 'articles/articles_list', articles: @articles

articles_controller.rb

  def index
    @articles = SearchArticlesCommand.new(params).execute
    render :index
  end

search_articles_command.rb

class SearchArticlesCommand
  def initialize(params = {})
    @since = params[:since_date]
    @keys = params[:search_query]
    @category = params[:category]
  end

  def execute
    Article.unscoped do
      query = if @since.present?
        Article.article.since_date(@since)
      else
        Article.published_article
      end
      query = query.search_by_keywords(@keys) if @keys.present?
      query = query.search_by_category(@category) if @category.present?
      query.select(:id, :updated_at, :label, :is_published, :featured, :slug, :created_at).order(created_at: :desc)
    end
  end
end

article.rb

  class Article < Comfy::Cms::Page
    include PgSearch
    include ActionView::Helpers::SanitizeHelper
    HOSTNAME = ENV['HOSTNAME'] || Socket.gethostname

    has_many :view_mappings, dependent: :destroy
    has_many :favorite_mappings, dependent: :destroy

    pg_search_scope :search_by_keywords, against: [:content_cache, :label], using: { tsearch: { any_word: true, prefix: true } }

    pg_search_scope :search_by_category, associated_against: {
        categories: [:label]
      }

  scope :since_date, -> (date) { where('created_at > ? OR updated_at > ? ', date, date) if date.present? }

  scope :folder, -> { where.not(layout_id: ENV['ARTICLE_LAYOUT_ID']) }

  scope :published_article, -> { published.article }

  scope :article, -> { where(layout_id: ENV['ARTICLE_LAYOUT_ID']) }

【问题讨论】:

  • 你能告诉我们你获取articles的方式吗?
  • @MurifoX 我已经用相关的控制器和命令更新了问题

标签: ruby-on-rails json jbuilder


【解决方案1】:

这是我怀疑的。如果您想要相同的行为,您的查询在找到一篇或多篇文章时应该返回相同类型的对象。问题是您返回 ActiveRecordRelationArticle 对象,具体取决于您的参数。

@articles = Article.all     # => ActiveRecordRelation, an array per se
@articles = Article.find(1) # => Article object

当涉及到jbuilder 来构造JSON 时,它会检查它是否是一个对象数组,然后用{ keyword =&gt; array } 包装json。当它是单个对象时,它默认为单个对象{article: {}}

解决方案很简单,您可以调整您的SearchArticlesCommand 以始终返回ActiveRecordRelation,即使它只找到一个对象。

【讨论】:

  • 我应该使用Array#wrap 是否有更惯用的rails 方式来做到这一点?
  • where 方法总是返回一个关系。尝试转储 select 的使用。返回所有值,然后在 jbuilder 上处理。
  • 我将搜索命令中的最后一行更改为query.where.not(id: nil).order(created_at: :desc),但它仍然返回相同
  • 那么问题出在since_datepublished_article 方法中,因为之前已经为它们设置了查询。
  • 这个:scope :published_article, -&gt; { published.article },我不知道你的业务规则,但我认为这总是会返回一个唯一的对象。你不能在where 查询中转这个吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-23
  • 1970-01-01
  • 1970-01-01
  • 2018-11-28
  • 2012-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多