Rails路由返回某些条件

时间:2015-05-09 05:07:40

标签: ruby-on-rails mongodb mongoid

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

我现在已经使用rails大约一个月了,我正在尝试做一个简单的json api。我的大部分都在工作,但是在根据关系返回自定义数据时遇到了麻烦。

宝石档案(供参考):

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

现在我知道我可以像这样返回所有这些:

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

这样可行,它会将帖子添加到结果集中。我不确定该怎么做,这就是问题,就是如何根据标准返回具体结果。

例如,我有一条路线,我想抓住用户,但只想抓住他们的最后一篇文章。另一条路线,我想抓住用户和他们的所有帖子,但是在过去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: [ ... ] 
}

1 个答案:

答案 0 :(得分:1)

在属于您想要抓住用户及其上一篇文章的路线的动作中,您可以这样做:

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

对于您的其他路线(您想要抓住用户以及过去24小时内所有帖子按降序排序),您可以尝试这样做:

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

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

class Post
  ...

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

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

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