【问题标题】:Rails - Serialize related dataRails - 序列化相关数据
【发布时间】:2016-04-13 12:36:55
【问题描述】:

我有两个模型:

class Continent < ActiveRecord::Base
  has_many :countries
end

class Country < ActiveRecord::Base
  belongs_to :continent
end

我创建了这样的控制器:

class ContinentsController < ApplicationController
  def index
    @continents = Continent.all
    render json: @continents
  end
end

和序列化器:

class ContitnentSerializer < ActiveModel::Serializer
  attributes :name, :countries
end

我的问题从这里开始。我只想序列化具有给定条件的国家,其中值来自 HTTP GET 参数。例如,仅当人口大于 params[:population] 时,才应显示序列化程序中的国家/地区。问题出在序列化程序内部,我们无法访问参数来检查它。

[
 {
  name: 'Europe'
  countries: [ 
    {
      name: 'Italy',
      population: 1000000 
    }
  ]
 },
 {
  name: 'Africa'
  countries: [ 

  ]
 }
]

我已尝试加入有条件的表格,但似乎无法正常工作。

@continents = Continent.all.joins("LEFT JOIN countries ON countries.continent_id = continents.id AND countries.population > #{params[:population]}")

【问题讨论】:

标签: sql ruby-on-rails ruby serialization


【解决方案1】:

创建一个作用域并从控制器调用具有param 值的作用域:

scope :population_more_than, ->(population) {all.joins("LEFT JOIN countries ON countries.continent_id = continents.id AND countries.population > ?", population)}

现在从控制器而不是Continent.all调用它

Continent.population_more_than(params[:population])

【讨论】:

  • 似乎返回所有国家而不是按条件减少
  • 嗯,不太确定。您可以尝试在查询中插入 population,而不将其作为最后的参数传递。您可以尝试的另一件事是将population 包装在这样的数组中:scope :population_more_than, -&gt;(population) {all.joins("LEFT JOIN countries ON countries.continent_id = continents.id AND countries.population &gt; ?", [population])}
  • 与插值无关。我只是适当地使用它,否则我会得到一些错误。我想知道那个 SQL 查询是否符合我们的预期。
【解决方案2】:

你可以试试

@continents = Continent.all
@continents.num_population = params[:population]
render json: @continents.to_json(methods: :countries_with_population_gt)

在您的 Continent 模型中

attr_accessor :num_population

def countries_with_population_gt(num_population=0)
  countries.where('population > ?', @num_population)
end

【讨论】:

    【解决方案3】:

    基本上,您只需选择符合特定规则的Continents。如果这是一个经常使用的过滤器,那么我会按照 Babar 的建议创建一个范围。

    如果这是一次性选择,那么我更喜欢直接在此处进行过滤,而不会使我的模型与不常用的范围混淆。

    Continent.joins(:countries).where("countries.population > :population", population: params[:population])
    
    # Or event shorter
    Continent.joins(:countries).where("countries.population > :population", params)
    

    【讨论】:

      猜你喜欢
      • 2021-03-23
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 2012-02-03
      • 1970-01-01
      • 1970-01-01
      • 2017-07-17
      • 2014-12-10
      相关资源
      最近更新 更多