API: Add pagination to articles (#4483)
* Add pagination to articles * Refactoring * Update specs
This commit is contained in:
parent
f9f7e1813b
commit
4dad407289
2 changed files with 130 additions and 68 deletions
|
|
@ -1,5 +1,8 @@
|
|||
class ArticleApiIndexService
|
||||
attr_accessor :tag, :username, :page, :state, :top, :collection_id
|
||||
attr_accessor :tag, :username, :page, :state, :top, :collection_id, :per_page
|
||||
|
||||
DEFAULT_PER_PAGE = 30
|
||||
MAX_PER_PAGE = 1000
|
||||
|
||||
def initialize(params)
|
||||
@page = params[:page]
|
||||
|
|
@ -8,6 +11,7 @@ class ArticleApiIndexService
|
|||
@state = params[:state]
|
||||
@top = params[:top]
|
||||
@collection_id = params[:collection_id]
|
||||
@per_page = params[:per_page]
|
||||
end
|
||||
|
||||
def get
|
||||
|
|
@ -32,9 +36,9 @@ class ArticleApiIndexService
|
|||
|
||||
def username_articles
|
||||
num = if @state == "all"
|
||||
1000
|
||||
MAX_PER_PAGE
|
||||
else
|
||||
30
|
||||
DEFAULT_PER_PAGE
|
||||
end
|
||||
|
||||
if (user = User.find_by(username: username))
|
||||
|
|
@ -42,13 +46,13 @@ class ArticleApiIndexService
|
|||
includes(:organization).
|
||||
order("published_at DESC").
|
||||
page(page).
|
||||
per(num)
|
||||
per(per_page || num)
|
||||
elsif (organization = Organization.find_by(slug: username))
|
||||
organization.articles.published.
|
||||
includes(:user).
|
||||
order("published_at DESC").
|
||||
page(page).
|
||||
per(num)
|
||||
per(per_page || num)
|
||||
else
|
||||
Article.none
|
||||
end
|
||||
|
|
@ -66,12 +70,12 @@ class ArticleApiIndexService
|
|||
articles.order("hotness_score DESC")
|
||||
end
|
||||
|
||||
articles.page(page).per(30)
|
||||
articles.page(page).per(per_page || DEFAULT_PER_PAGE)
|
||||
end
|
||||
|
||||
def top_articles
|
||||
Article.published.order("positive_reactions_count DESC").where("published_at > ?", top.to_i.days.ago).
|
||||
page(page).per(30)
|
||||
page(page).per(per_page || DEFAULT_PER_PAGE)
|
||||
end
|
||||
|
||||
def state_articles(state)
|
||||
|
|
@ -90,7 +94,7 @@ class ArticleApiIndexService
|
|||
includes(:user, :organization).
|
||||
order("published_at").
|
||||
page(page).
|
||||
per(30)
|
||||
per(per_page || DEFAULT_PER_PAGE)
|
||||
end
|
||||
|
||||
def base_articles
|
||||
|
|
@ -99,6 +103,6 @@ class ArticleApiIndexService
|
|||
includes(:user, :organization).
|
||||
order("hotness_score DESC").
|
||||
page(page).
|
||||
per(30)
|
||||
per(per_page || DEFAULT_PER_PAGE)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,74 +9,132 @@ RSpec.describe "Api::V0::Articles", type: :request do
|
|||
end
|
||||
|
||||
describe "GET /api/articles" do
|
||||
it "returns json response" do
|
||||
get api_articles_path
|
||||
expect(response.content_type).to eq("application/json")
|
||||
context "without params" do
|
||||
it "returns json response" do
|
||||
get api_articles_path
|
||||
expect(response.content_type).to eq("application/json")
|
||||
end
|
||||
|
||||
it "returns featured articles if no param is given" do
|
||||
article.update_column(:featured, true)
|
||||
get api_articles_path
|
||||
expect(json_response.size).to eq(1)
|
||||
end
|
||||
|
||||
it "supports pagination" do
|
||||
create_list(:article, 2, featured: true)
|
||||
get api_articles_path, params: { page: 1, per_page: 2 }
|
||||
expect(json_response.length).to eq(2)
|
||||
get api_articles_path, params: { page: 2, per_page: 2 }
|
||||
expect(json_response.length).to eq(1)
|
||||
end
|
||||
|
||||
it "returns flare tag in the response" do
|
||||
get api_articles_path
|
||||
response_article = JSON.parse(response.body)[0]
|
||||
expect(response_article["flare_tag"]).to be_present
|
||||
expect(response_article["flare_tag"].keys).to eq(%w[name bg_color_hex text_color_hex])
|
||||
expect(response_article["flare_tag"]["name"]).to eq("discuss")
|
||||
end
|
||||
end
|
||||
|
||||
it "returns featured articles if no param is given" do
|
||||
article.update_column(:featured, true)
|
||||
get api_articles_path
|
||||
expect(json_response.size).to eq(1)
|
||||
context "with username param" do
|
||||
it "returns user's articles for the given username" do
|
||||
create(:article, user: article.user)
|
||||
get api_articles_path(username: article.user.username)
|
||||
expect(json_response.size).to eq(2)
|
||||
end
|
||||
|
||||
it "returns nothing if given user is not found" do
|
||||
get api_articles_path(username: "foobar")
|
||||
expect(json_response.size).to eq(0)
|
||||
end
|
||||
|
||||
it "returns org's articles if org's slug is given" do
|
||||
create(:article, user: article.user, organization: organization)
|
||||
get api_articles_path(username: organization.slug)
|
||||
expect(json_response.size).to eq(1)
|
||||
end
|
||||
|
||||
it "supports pagination" do
|
||||
create_list(:article, 2, user: article.user)
|
||||
get api_articles_path(username: article.user.username), params: { page: 1, per_page: 2 }
|
||||
expect(json_response.length).to eq(2)
|
||||
get api_articles_path(username: article.user.username), params: { page: 2, per_page: 2 }
|
||||
expect(json_response.length).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
it "returns user's articles for the given username" do
|
||||
create(:article, user: article.user)
|
||||
get api_articles_path(username: article.user.username)
|
||||
expect(json_response.size).to eq(2)
|
||||
context "with tag param" do
|
||||
it "returns tag's articles" do
|
||||
get api_articles_path(tag: article.tag_list.first)
|
||||
expect(json_response.size).to eq(1)
|
||||
end
|
||||
|
||||
it "returns top tag articles if tag and top param is present" do
|
||||
get api_articles_path(tag: article.tag_list.first, top: "7")
|
||||
expect(json_response.size).to eq(1)
|
||||
end
|
||||
|
||||
it "returns not tag articles if article and tag are not approved" do
|
||||
article.update_column(:approved, false)
|
||||
tag = Tag.find_by(name: article.tag_list.first)
|
||||
tag.update(requires_approval: true)
|
||||
|
||||
get api_articles_path(tag: tag.name)
|
||||
expect(JSON.parse(response.body).size).to eq(0)
|
||||
end
|
||||
|
||||
it "supports pagination" do
|
||||
create_list(:article, 2, tags: "discuss")
|
||||
get api_articles_path(tag: article.tag_list.first), params: { page: 1, per_page: 2 }
|
||||
expect(json_response.length).to eq(2)
|
||||
get api_articles_path(tag: article.tag_list.first), params: { page: 2, per_page: 2 }
|
||||
expect(json_response.length).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
it "returns nothing if given user is not found" do
|
||||
get api_articles_path(username: "foobar")
|
||||
expect(json_response.size).to eq(0)
|
||||
context "with top param" do
|
||||
it "only returns fresh top articles if top param is present" do
|
||||
# TODO: slight duplication, test should be removed
|
||||
old_article = create(:article)
|
||||
old_article.update_column(:published_at, 10.days.ago)
|
||||
get api_articles_path(top: "7")
|
||||
expect(json_response.size).to eq(1)
|
||||
end
|
||||
|
||||
it "supports pagination" do
|
||||
old_articles = create_list(:article, 2, featured: true)
|
||||
old_articles.each do |old_article|
|
||||
old_article.update_column(:published_at, 10.days.ago)
|
||||
end
|
||||
get api_articles_path(top: "11"), params: { page: 1, per_page: 2 }
|
||||
expect(json_response.length).to eq(2)
|
||||
get api_articles_path(top: "11"), params: { page: 2, per_page: 2 }
|
||||
expect(json_response.length).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
it "returns org's articles if org's slug is given" do
|
||||
create(:article, user: article.user, organization: organization)
|
||||
get api_articles_path(username: organization.slug)
|
||||
expect(json_response.size).to eq(1)
|
||||
end
|
||||
context "with collection_id param" do
|
||||
it "returns a collection id" do
|
||||
collection = create(:collection, user: article.user)
|
||||
article.update_columns(collection_id: collection.id)
|
||||
get api_articles_path(collection_id: collection.id)
|
||||
expect(json_response[0]["collection_id"]).to eq collection.id
|
||||
end
|
||||
|
||||
it "returns tag's articles" do
|
||||
get api_articles_path(tag: article.tag_list.first)
|
||||
expect(json_response.size).to eq(1)
|
||||
end
|
||||
|
||||
it "returns top tag articles if tag and top param is present" do
|
||||
get api_articles_path(tag: article.tag_list.first, top: "7")
|
||||
expect(json_response.size).to eq(1)
|
||||
end
|
||||
|
||||
it "only returns fresh top articles if top param is present" do
|
||||
# TODO: slight duplication, test should be removed
|
||||
old_article = create(:article)
|
||||
old_article.update_column(:published_at, 10.days.ago)
|
||||
get api_articles_path(top: "7")
|
||||
expect(json_response.size).to eq(1)
|
||||
end
|
||||
|
||||
it "returns not tag articles if article and tag are not approved" do
|
||||
article.update_column(:approved, false)
|
||||
tag = Tag.find_by(name: article.tag_list.first)
|
||||
tag.update(requires_approval: true)
|
||||
|
||||
get api_articles_path(tag: tag.name)
|
||||
expect(JSON.parse(response.body).size).to eq(0)
|
||||
end
|
||||
|
||||
it "returns flare tag in the response" do
|
||||
get api_articles_path
|
||||
response_article = JSON.parse(response.body)[0]
|
||||
expect(response_article["flare_tag"]).to be_present
|
||||
expect(response_article["flare_tag"].keys).to eq(%w[name bg_color_hex text_color_hex])
|
||||
expect(response_article["flare_tag"]["name"]).to eq("discuss")
|
||||
end
|
||||
|
||||
it "returns a collection id" do
|
||||
collection = create(:collection, user: article.user)
|
||||
article.update_columns(collection_id: collection.id)
|
||||
get api_articles_path(collection_id: collection.id)
|
||||
expect(json_response[0]["collection_id"]).to eq collection.id
|
||||
it "supports pagination" do
|
||||
collection = create(:collection, user: article.user)
|
||||
article.update_columns(collection_id: collection.id)
|
||||
collection_articles = create_list(:article, 2, featured: true)
|
||||
collection_articles.each do |collection_article|
|
||||
collection_article.update_columns(collection_id: collection.id)
|
||||
end
|
||||
get api_articles_path(collection_id: collection.id), params: { page: 1, per_page: 2 }
|
||||
expect(json_response.length).to eq(2)
|
||||
get api_articles_path(collection_id: collection.id), params: { page: 2, per_page: 2 }
|
||||
expect(json_response.length).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue