如何限制在respond_to中渲染json时打印的记录关联数

时间:2014-07-31 01:52:56

标签: json ruby-on-rails-4

我很难理解这是如何运作的。我的问题是这个

填充控制器

  def refresh_stuffs
    id = params[:stuff][:id]
    last_update = params[:stuff][:last_update]

    @stuff = Stuff.find(id)
    @stuff.events.where('? < updated_at','2014-06-25 21:57:52') # The updated_at attr is 2014-06-19 22:59:15 
    respond_to do |format|
      format.json {
        render json: @stuff, status: :ok,
        include: {
          events: {except: [:created_at, :updated_at, :visible]}
        },
        except: [:created_at, :updated_at, :user_id]
      }
    end
  end

现在渲染效果很好,除了一件事,当我想渲染关联时它不会让我限制它。我看到的所有内容都谈到限制要显示的列,我想限制访问的记录数量。目前,即使我尝试使用上面的where查询去掉的记录也显示出来。在json中渲染时查询的确切关系如何?我该怎样做才能按照我想要的方式过滤它?

示例输出{"id":2, "name": "le name", "events": [{"id": 2, "etc":""}]

我应该使用上面的示例代码{"id":2, "name": "le name", "events":[]

2 个答案:

答案 0 :(得分:0)

您尝试过限制方法吗?

我测试了我的项目,它运作良好,我希望它对你有用。

我的项目有一个数据集模型有很多列。

irb(main):026:0> Dataset.first.columns.count
  [1m[36mDataset Load (5.0ms)[0m  [1mSELECT datasets.* FROM datasets FETCH FIRST 1 ROWS ONLY [0m
  [1m[35m (4.0ms)[0m  SELECT COUNT(*) FROM columns WHERE columns.dataset_id = 1
=> 9

使用限制,您可以控制列的结果。

irb(main):048:0> dataset = Dataset.first
  [1m[36mDataset Load (10.0ms)[0m  [1mSELECT datasets.* FROM datasets FETCH FIRST 1 ROWS ONLY [0m
irb(main):049:0> dataset.columns.where(nil).limit(3)
  [1m[35mColumn Load (11.0ms)[0m  SELECT columns.* FROM columns WHERE columns.dataset_id = 1 ORDER BY id
FETCH FIRST 3 ROWS ONLY

你可以看到,ActiveRecord生成的sql如果不同。

但是当渲染json时,render方法可能会调用colums方法(在您的情况下是events方法),因此active_record可以将新查询发布到db服务器。

要解决此问题,您可以在之前使用包含两个相关模型数据的位置,如下所示:

irb(main):056:0> dataset = Dataset.includes(:columns).where('columns.id = ?',30809).first
  [1m[35mSQL (7.0ms)[0m  SELECT datasets.id FROM datasets LEFT OUTER JOIN columns ON 
columns.dataset_id = datasets.id WHERE (columns.id = 30809) FETCH FIRST 1 ROWS ONLY
irb(main):058:0> dataset.columns.size
=> 1

如果您使用包含在哪里,ActiveRecored将为您生成联接语句。

在您的情况下,请尝试此版本。

def refresh_stuffs
  id = params[:stuff][:id]
  last_update = params[:stuff][:last_update]

  @stuff = Stuff.includes(:events)
    .where('stuffs.id = ? and ? < events.updated_at',id,'2014-06-25 21:57:52') # The updated_at attr is 2014-06-19 22:59:15 
  respond_to do |format|
    format.json {
      render json: @stuff, status: :ok,
      include: {
        events: {except: [:created_at, :updated_at, :visible]}
      },
      except: [:created_at, :updated_at, :user_id]
    }
  end
end

答案 1 :(得分:0)

我为你添加了一个新的答案,它在我的项目中有效。

控制器代码:

  # GET /datasets/1/test
  # GET /datasets/1/test.json
  def test
    @project_id = params[:project_id]
    @dataset = Dataset.includes(:columns).where('datasets.id = ? and columns.id < ?',params[:id],params[:max_col_id])

    respond_to do |format|
      format.html # show.html.erb
        format.json {
          render json: @dataset, status: :ok,
          include: {
            columns: {only: [:id]}

          },
          only: [:id]
        }
    end
  end

测试结果:

url1:  http://localhost:3000/datasets/9657/test.json?max_col_id=433612
return data1: [{"id":9657,"columns":[{"id":433609},{"id":433608},{"id":433610},{"id":433611}]}]

返回列模型的4个成员。

url2: http://localhost:3000/datasets/9657/test.json?max_col_id=433611
return data2: [{"id":9657,"columns":[{"id":433609},{"id":433608},{"id":433610}]}]

只返回列模型的3个成员。完成!

我没有使用time_stamp来过滤子模型,因为不同的dbms可能有不同的方式来比较time_stamp。

抱歉我的英语不好。我会尽力写清楚。任何建议,以改善我的答案将不胜感激。