Rails 路由到 return 某些条件

Rails Routes to return certain criteria

$ rails -v
Rails 4.2.1
$ ruby -v
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]

我已经使用 rails 大约一个月了,我正在尝试做一个简单的 json api。我的大部分工作正常,但在 return 基于关系的自定义数据方面遇到问题。

Gem 文件(供参考):

source 'https://rubygems.org'

gem 'rails', '4.2.1'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :docgi
gem 'mongoid'
gem 'rspec-its', '~> 1.2.0'
gem 'unicorn', '~> 4.9.0'
gem 'kaminari' # adds pagination to ActiveModels
gem 'devise', '~> 3.4.1'
gem 'simple_token_authentication', '~> 1.9.1'
gem 'cancancan'

group :development do
  gem 'quiet_assets', '~> 1.1.0'
end

group :development, :test do
  gem 'rspec-rails', '~> 3.2.1'
  gem 'byebug'
  gem 'web-console', '~> 2.0'
  gem 'spring'
  gem 'factory_girl_rails', '~> 4.5.0'
end
group :test do
  gem 'capybara', '~> 2.4.4'
  gem 'capybara-email', '~> 2.4.0'
  gem 'shoulda-matchers', '~> 2.8.0'
end

正如您在 gem 文件中看到的那样,我通过 mongoid 使用 mongo。然后我有我的用户模型:

class User
  include Mongoid::Document
  include Mongoid::Timestamps
  has_many :posts

  validates :email, presence: true,
            uniqueness: true,
            format: {
                with: /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9\.-]+\.[A-Za-z]+\Z/
            }
  validates :username, presence: true, uniqueness: true
  validates :telephone, presence: true
  validates :name, presence: true
  validates :gender, presence: true
  validates :dob, presence: true
  validates :photo_url, presence: true
  validates :password, presence: true
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable, :trackable, :validatable
  ## Token Authenticatable
  acts_as_token_authenticatable
  field :authentication_token

  ## Profile
  field :name,               type: String, default: ""
  field :gender,             type: Boolean, default: 0
  field :dob,                type: Date
  field :telephone,          type: String
  field :username,           type: String
  field :photo_url,          type: String
  field :last_action,        type: Time
  ## Database authenticatable
  field :email,              type: String, default: ""
  field :encrypted_password, type: String, default: ""

  ## Trackable
  field :sign_in_count,      type: Integer, default: 0
  field :current_sign_in_at, type: Time
  field :last_sign_in_at,    type: Time
  field :current_sign_in_ip, type: String
  field :last_sign_in_ip,    type: String

  ## Indexes
  index({ email: 1, username: 1 })
  index({ gender: 1, dob: 1, telephone: 1, posts: -1})

end

我们在这里关联的关系是 has_many :posts

现在我知道我可以return他们都这样了:

user = current_user
    render json: user.as_json(include: :posts), status: :created, location: @user

这有效,它会将 post 添加到结果集中。我不确定该怎么做,这就是这里的问题,是如何 return 基于标准的特定结果。

例如,我有一条路线,我想抓住用户,但只想抓住他们的最后一个post。还有另一条路线,我想抓住用户和他们所有的 posts,但是 posts 在过去 24 小时内按最新到最旧的顺序排序,我不太确定如何正确地做到这一点。

我希望实现的示例结果集:

{
_id: "5548245663686f2a58030000",
authentication_token: "KG6qksJaUzKwU7aZxt94",
created_at: "2015-05-05T02:00:54.467Z",
dob: null,
email: "sjors1@purpledunes.com",
gender: false,
last_action: null,
name: "",
photo_url: null,
telephone: null,
updated_at: "2015-05-05T02:00:54.467Z",
username: null,
posts: [ ... ] 
}

在属于你想要抓取用户和他们最后的路由的动作中post,你可以这样做:

last_post = current_user.posts.last
render json: last_post.to_json

对于你的其他路线(你想抓取用户和他们在过去 24 小时内的所有 posts 降序排列)你可以试试这个:

posts = current_user.posts.where('created_at >= ?', 1.day.ago).order created_at: :desc
render json: posts.to_json

更新

您可以看看 ActiveModal::Serializer 以尝试优雅地解决您的问题。例如,您可以创建一个如下所示的 UserSerializer

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name, :last_post, :posts_from_last_day # and whatever else you want to be included

  has_many :posts

  def last_post
    object.posts.last
  end

  def posts_from_last_day
    object.posts.where('created_at >= ?', 1.day.ago).order created_at: :desc
  end
end

在你的控制器中你会拥有类似的东西:

render json: current_user, serializer: UserSerializer

另外,您甚至可以在 Post 模型中创建一个 scope 或方法,从序列化程序中删除条件:

class Post
  ...

  def from_last_day
    where('created_at >= ?', 1.day.ago).order created_at: :desc
  end
end

您可以将 UserSerializer 中的 posts_from_last_day 方法更改为:

def posts_from_last_day
  object.posts.from_last_day
end

更新,第二部分

如果您不想在同一个请求中使用 last_postposts_from_last_day,您可以创建两个单独的序列化程序:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name, :last_post # and whatever else you want to be included

  has_many :posts

  def last_post
    object.posts.last
  end
end

在您要检索上述数据的操作中:

render json: current_user, serializer: UserSerializer

对于其他操作,您可以创建以下序列化程序:

class UserLastDaySerializer < ActiveModel::Serializer
  attributes :id, :name, :posts_from_last_day # and whatever else you want to be included

  has_many :posts


  def posts_from_last_day
    object.posts.from_last_day
  end
end

可以这样称呼:

render json: current_user, serializer: UserLastDaySerializer