$ 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: [ ... ]
}
答案 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_post
和posts_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