API: Endpoint to get an organization's articles (#12237)
* update route * add controller action * add article jbuilder/update shared files * add tests * update api docs * add published to query * render articles index/delete articles jbuilder * call articles index attributes const * put back article/flare partials * bug fix for readinglist index * bug fix for render partial in jbuilder
This commit is contained in:
parent
4329ea94a0
commit
27648a938b
5 changed files with 115 additions and 4 deletions
|
|
@ -1,7 +1,7 @@
|
|||
module Api
|
||||
module V0
|
||||
class OrganizationsController < ApiController
|
||||
before_action :find_organization, only: %i[users listings]
|
||||
before_action :find_organization, only: %i[users listings articles]
|
||||
|
||||
SHOW_ATTRIBUTES_FOR_SERIALIZATION = %i[
|
||||
id username name summary twitter_username github_username url
|
||||
|
|
@ -21,6 +21,8 @@ module Api
|
|||
].freeze
|
||||
private_constant :LISTINGS_FOR_SERIALIZATION
|
||||
|
||||
ARTICLES_FOR_SERIALIZATION = Api::V0::ArticlesController::INDEX_ATTRIBUTES_FOR_SERIALIZATION
|
||||
|
||||
def show
|
||||
@organization = Organization.select(SHOW_ATTRIBUTES_FOR_SERIALIZATION)
|
||||
.find_by!(username: params[:username])
|
||||
|
|
@ -47,6 +49,22 @@ module Api
|
|||
@listings = @listings.in_category(params[:category]) if params[:category].present?
|
||||
end
|
||||
|
||||
def articles
|
||||
per_page = (params[:per_page] || 30).to_i
|
||||
num = [per_page, 1000].min
|
||||
page = params[:page] || 1
|
||||
|
||||
@articles = @organization.articles.published
|
||||
.select(ARTICLES_FOR_SERIALIZATION)
|
||||
.includes(:user)
|
||||
.order(published_at: :desc)
|
||||
.page(page)
|
||||
.per(num)
|
||||
.decorate
|
||||
|
||||
render "api/v0/articles/index.json.jbuilder"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_organization
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
json.array! @articles do |article|
|
||||
json.partial! "article", article: article
|
||||
json.partial! "api/v0/articles/article", article: article
|
||||
|
||||
# /api/articles and /api/articles/:id have opposite representations
|
||||
# of `tag_list` and `tags and we can't align them without breaking the API,
|
||||
|
|
@ -16,6 +16,6 @@ json.array! @articles do |article|
|
|||
|
||||
flare_tag = FlareTag.new(article).tag
|
||||
if flare_tag
|
||||
json.partial! "flare_tag", flare_tag: flare_tag
|
||||
json.partial! "api/v0/articles/flare_tag", flare_tag: flare_tag
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ Rails.application.routes.draw do
|
|||
resources :organizations, only: [:show], param: :username do
|
||||
resources :users, only: [:index], to: "organizations#users"
|
||||
resources :listings, only: [:index], to: "organizations#listings"
|
||||
resources :articles, only: [:index], to: "organizations#articles"
|
||||
end
|
||||
|
||||
namespace :admin do
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ info:
|
|||
Dates and date times, unless otherwise specified, must be in
|
||||
the [RFC 3339](https://tools.ietf.org/html/rfc3339) format.
|
||||
|
||||
version: "0.9.4"
|
||||
version: "0.9.5"
|
||||
termsOfService: https://dev.to/terms
|
||||
contact:
|
||||
name: DEV Team
|
||||
|
|
@ -3274,6 +3274,53 @@ paths:
|
|||
source: |
|
||||
curl https://dev.to/api/organizations/ecorp/listings
|
||||
|
||||
/organizations/{username}/articles:
|
||||
get:
|
||||
operationId: getOrgArticles
|
||||
summary: Organization's Articles
|
||||
description: |
|
||||
This endpoint allows the client to retrieve a list of Articles belonging to the organization
|
||||
|
||||
It supports pagination, each page will contain `30` listing by default.
|
||||
tags:
|
||||
- organizations
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
required: true
|
||||
description: |
|
||||
Username of the organization
|
||||
schema:
|
||||
type: string
|
||||
example: "ecorp"
|
||||
- $ref: '#/components/parameters/pageParam'
|
||||
- $ref: '#/components/parameters/perPageParam30to1000'
|
||||
responses:
|
||||
"200":
|
||||
description: A list of users belonging to the organization
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/ArticleIndex"
|
||||
examples:
|
||||
article-success:
|
||||
$ref: "#/components/examples/ArticlesIndex"
|
||||
"404":
|
||||
description: Resource not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/APIError"
|
||||
examples:
|
||||
user-not-found:
|
||||
$ref: "#/components/examples/ErrorNotFound"
|
||||
x-code-samples:
|
||||
- lang: Shell
|
||||
label: curl
|
||||
source: |
|
||||
curl https://dev.to/api/organizations/ecorp/listings
|
||||
|
||||
/podcast_episodes:
|
||||
get:
|
||||
|
|
|
|||
|
|
@ -113,4 +113,49 @@ RSpec.describe "Api::V0::Organizations", type: :request do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/organizations/:username/articles" do
|
||||
let(:org_user) { create(:user, :org_member) }
|
||||
let(:organization) { org_user.organizations.first }
|
||||
let!(:article) { create(:article, user: org_user, organization: organization) }
|
||||
|
||||
it "returns 404 if the organizations articles is not found" do
|
||||
get "/api/organizations/invalid-username/articles"
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
|
||||
it "supports pagination" do
|
||||
create(:article, organization: organization)
|
||||
|
||||
get api_organization_articles_path(organization.username), params: { page: 1, per_page: 1 }
|
||||
expect(response.parsed_body.length).to eq(1)
|
||||
|
||||
get api_organization_articles_path(organization.username), params: { page: 2, per_page: 1 }
|
||||
expect(response.parsed_body.length).to eq(1)
|
||||
|
||||
get api_organization_articles_path(organization.username), params: { page: 3, per_page: 1 }
|
||||
expect(response.parsed_body.length).to eq(0)
|
||||
end
|
||||
|
||||
it "returns the correct json representation of the organizations articles", :aggregate_failures do
|
||||
get api_organization_articles_path(organization.username)
|
||||
response_article = response.parsed_body.first
|
||||
expect(response_article["type_of"]).to eq("article")
|
||||
|
||||
%w[id title slug description path public_reactions_count
|
||||
positive_reactions_count comments_count published_timestamp].each do |attr|
|
||||
expect(response_article[attr]).to eq(article.public_send(attr))
|
||||
end
|
||||
|
||||
expect(response_article["tag_list"]).to match_array(article.tag_list)
|
||||
|
||||
%w[name username twitter_username github_username website_url].each do |attr|
|
||||
expect(response_article["user"][attr]).to eq(org_user.public_send(attr))
|
||||
end
|
||||
|
||||
%w[name username slug].each do |attr|
|
||||
expect(response_article["organization"][attr]).to eq(organization.public_send(attr))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue