Rails - 如何获取关联 table 的第一条记录?
Rails - How get first record of associated table?
我正在尝试为我的移动应用创建一个 api。
我有 posts
和 images
table。对于我的 api,我可以发送所有 posts
:
@posts = Post.all
render json: @posts
Output: [{"id":20,"title":"Title 1", "body":" first post ", "user_id":1 }]
但它根本不包含图像。为了在我的应用程序主页中显示展示图片,我只需要关联图片的第一张图片。
我需要的输出是(showcase_image
属性的名称无关紧要):
Output: [{"id":20, "title":"Title 1", "body":" first post ", "showcase_image": 'first_image.jpg' , "user_id":1 }]
我需要将关联图片 table 中的第一张图片添加到我的 json 回复中..
提前致谢!
我建议使用序列化程序。 Active Model Serializer is pretty standard and easy to use, but is not receiving any updates and has a bad performance. You can choose any other serializer (I recommend Blueprinter) 或使用 AMS。
通过 AMS,您可以定义要序列化的关系,它将构建您期望的 json
class PostSerializer < ActiveModel::Serializer
attributes :id, :title, :body, :showcase_image, :user_id
def showcase_image
object.images.first.name # don't know what is the attribute you're looking for
end
end
在你的控制器上:
@posts = Post.includes(:images).all # Use includes to avoid N+1 problems
render json: @posts, serialize_collection: PostSerializer
您可以在调用 as_json
时包含与 :include
选项的关联。
render json: @posts.as_json(include: :images)
您可以通过向 Post
添加新关联来将其限制为一张图像。
class Post < ApplicationRecord
has_many :images
has_one :showcase_image, class_name: 'Image'
end
这将允许您改用 :showcase_image
。
render json: @posts.as_json(include: :showcase_image)
您也可以使用 Jbuilder 来解决手头的问题,而无需添加额外的关联。
# app/views/posts/index.json.jbuilder
# Get images that belong to posts, group them by post_id and
# return the minimum image id for each post_id.
images = Images.where(post_id: @posts.select(:id)).group(:post_id).minimum(:id)
# Request the full image data for all image ids returned above.
images = images.keys.zip(Image.find(images.values)).to_h
json.array! @posts do |post|
json.extract! post, :id, :title, :body, :...
json.showcase_image do
image = images[post.id]
if image
json.extract! image, :id, :name, :location, :...
else
json.null!
end
end
end
不调用特定的渲染,Rails 将默认为 app/views/posts/index
文件,select 匹配请求的文件。 (如果你请求 HTML 它会寻找一个 HTML 文件,如果你请求 JSON 它会寻找 JSON,等等)
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
@posts = Post.all
end
end
现在,当您使用 header Accept: application/json
请求 /posts.json
或 /posts
时,您的应用程序应该 return Jbuilder 构建的 JSON 响应.
我正在尝试为我的移动应用创建一个 api。
我有 posts
和 images
table。对于我的 api,我可以发送所有 posts
:
@posts = Post.all
render json: @posts
Output: [{"id":20,"title":"Title 1", "body":" first post ", "user_id":1 }]
但它根本不包含图像。为了在我的应用程序主页中显示展示图片,我只需要关联图片的第一张图片。
我需要的输出是(showcase_image
属性的名称无关紧要):
Output: [{"id":20, "title":"Title 1", "body":" first post ", "showcase_image": 'first_image.jpg' , "user_id":1 }]
我需要将关联图片 table 中的第一张图片添加到我的 json 回复中..
提前致谢!
我建议使用序列化程序。 Active Model Serializer is pretty standard and easy to use, but is not receiving any updates and has a bad performance. You can choose any other serializer (I recommend Blueprinter) 或使用 AMS。 通过 AMS,您可以定义要序列化的关系,它将构建您期望的 json
class PostSerializer < ActiveModel::Serializer
attributes :id, :title, :body, :showcase_image, :user_id
def showcase_image
object.images.first.name # don't know what is the attribute you're looking for
end
end
在你的控制器上:
@posts = Post.includes(:images).all # Use includes to avoid N+1 problems
render json: @posts, serialize_collection: PostSerializer
您可以在调用 as_json
时包含与 :include
选项的关联。
render json: @posts.as_json(include: :images)
您可以通过向 Post
添加新关联来将其限制为一张图像。
class Post < ApplicationRecord
has_many :images
has_one :showcase_image, class_name: 'Image'
end
这将允许您改用 :showcase_image
。
render json: @posts.as_json(include: :showcase_image)
您也可以使用 Jbuilder 来解决手头的问题,而无需添加额外的关联。
# app/views/posts/index.json.jbuilder
# Get images that belong to posts, group them by post_id and
# return the minimum image id for each post_id.
images = Images.where(post_id: @posts.select(:id)).group(:post_id).minimum(:id)
# Request the full image data for all image ids returned above.
images = images.keys.zip(Image.find(images.values)).to_h
json.array! @posts do |post|
json.extract! post, :id, :title, :body, :...
json.showcase_image do
image = images[post.id]
if image
json.extract! image, :id, :name, :location, :...
else
json.null!
end
end
end
不调用特定的渲染,Rails 将默认为 app/views/posts/index
文件,select 匹配请求的文件。 (如果你请求 HTML 它会寻找一个 HTML 文件,如果你请求 JSON 它会寻找 JSON,等等)
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
@posts = Post.all
end
end
现在,当您使用 header Accept: application/json
请求 /posts.json
或 /posts
时,您的应用程序应该 return Jbuilder 构建的 JSON 响应.