Skip to content
This repository has been archived by the owner on Feb 18, 2020. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #8 from Averethel/filters
+ Filters
  • Loading branch information
Averethel committed Sep 8, 2015
2 parents 8fa2531 + 38b8680 commit 87048f4
Show file tree
Hide file tree
Showing 11 changed files with 265 additions and 19 deletions.
20 changes: 15 additions & 5 deletions README.md
Expand Up @@ -70,8 +70,12 @@ Role base system with following permissions
## List all users
### GET /api/v1/users
#### parameters:
* `page[size]`: INTEGER
* `page[number]`: INTEGER
* pagination
* `page[size]`: INTEGER
* `page[number]`: INTEGER
* filtering
* `filters[username]`: STRING - wildcard match
* `filters[id]`: [INTEGER] - inclusion math

#### Example
```
Expand Down Expand Up @@ -428,9 +432,15 @@ Role base system with following permissions
## List issues
### GET /api/v1/issues
#### parameters:
* `page[size]`: INTEGER
* `page[number]`: INTEGER

* pagination
* `page[size]`: INTEGER
* `page[number]`: INTEGER
* filtering
* `filters[title]`: STRING - wildcard match
* `filters[description]`: STRING - wildcard match
* `filters[id]`: [INTEGER] - inclusion math
* `filters[priority]`: [STRING] - inclusion math
* `filters[status]`: [STRING] - inclusion math
#### Example
```
resp = conn.get("/api/v1/issues")
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/api/v1/comments_controller.rb
Expand Up @@ -80,10 +80,10 @@ class Api::V1::CommentsController < ApplicationController
# }
# }
def index
@comments = policy_scope(@issue.comments).page(params[:page][:number]).per(params[:page][:size])
@comments = policy_scope(@issue.comments).page(page_params[:number]).per(page_params[:size])

render json: @comments, meta: {
total: @issue.comments.count,
total: @comments.total_count,
current_page: @comments.current_page,
on_page: @comments.size,
total_pages: @comments.total_pages
Expand Down
27 changes: 23 additions & 4 deletions app/controllers/api/v1/issues_controller.rb
Expand Up @@ -6,8 +6,15 @@ class Api::V1::IssuesController < ApplicationController
# GET /api/v1/issues
#
# parameters:
# page[size]: INTEGER
# page[number]: INTEGER
# pagination
# page[size]: INTEGER
# page[number]: INTEGER
# filtering
# filters[title]: STRING - wildcard match
# filters[description]: STRING - wildcard match
# filters[id]: [INTEGER] - inclusion math
# filters[priority]: [STRING] - inclusion math
# filters[status]: [STRING] - inclusion math
#
# = Example
#
Expand Down Expand Up @@ -93,10 +100,13 @@ class Api::V1::IssuesController < ApplicationController
# }
# }
def index
@issues = policy_scope(Issue).page(params[:page][:number]).per(params[:page][:size])
@issues = IssueFilterService.new(filter_params)
.filter(policy_scope(Issue))
.page(page_params[:number])
.per(page_params[:size])

render json: @issues, meta: {
total: Issue.count,
total: @issues.total_count,
current_page: @issues.current_page,
on_page: @issues.size,
total_pages: @issues.total_pages
Expand Down Expand Up @@ -430,4 +440,13 @@ def destroy
def set_issue
@issue = Issue.find(params[:id])
end

def filter_params
params.permit(filters: [
:title, :description,
id: [],
priority: [],
status: []
])[:filters] || {}
end
end
22 changes: 18 additions & 4 deletions app/controllers/api/v1/users_controller.rb
Expand Up @@ -5,8 +5,12 @@ class Api::V1::UsersController < ApplicationController
#
# GET /api/v1/users
# parameters:
# page[size]: INTEGER
# page[number]: INTEGER
# pagination
# page[size]: INTEGER
# page[number]: INTEGER
# filtering
# filters[username]: STRING - wildcard match
# filters[id]: [INTEGER] - inclusion math
#
# = Example
#
Expand Down Expand Up @@ -102,10 +106,13 @@ class Api::V1::UsersController < ApplicationController
# }
# }
def index
@users = policy_scope(User).page(params[:page][:number]).per(params[:page][:size])
@users = UserFilterService.new(filter_params)
.filter(policy_scope(User))
.page(page_params[:number])
.per(page_params[:size])

render json: @users, meta: {
total: User.count,
total: @users.total_count,
current_page: @users.current_page,
on_page: @users.size,
total_pages: @users.total_pages
Expand Down Expand Up @@ -376,4 +383,11 @@ def destroy
def set_user
@user = User.find(params[:id])
end

def filter_params
params.permit(filters: [
:username,
id: []
])[:filters] || {}
end
end
5 changes: 2 additions & 3 deletions app/controllers/application_controller.rb
Expand Up @@ -3,7 +3,6 @@ class ApplicationController < ActionController::API
include Pundit

before_action :check_authentication
before_action :prepare_page_params, only: [:index]

after_action :verify_authorized, except: [:index]
after_action :verify_policy_scoped, only: [:index]
Expand All @@ -15,8 +14,8 @@ class ApplicationController < ActionController::API

private

def prepare_page_params
params[:page] ||= {}
def page_params
params.permit(page: [:size, :number])[:page] || {}
end

def not_found(error)
Expand Down
32 changes: 32 additions & 0 deletions app/services/issue_filter_service.rb
@@ -0,0 +1,32 @@
class IssueFilterService
def initialize(filters)
@filters = filters
end

def filter(issues)
issues = filter_by_title(issues) if @filters[:title]
issues = filter_by_description(issues) if @filters[:description]
issues = filter_by_priority(issues) if @filters[:priority]
issues = filter_by_status(issues) if @filters[:status]
issues.where(@filters.except(:tite, :description, :priority, :status))
end

private
def filter_by_title(issues)
issues.where('title ilike ?', "%#{@filters[:title]}%")
end

def filter_by_description(issues)
issues.where('description ilike ?', "%#{@filters[:description]}%")
end

def filter_by_priority(issues)
values = @filters[:priority].map{ |s| Issue.priorities[s] }.compact
issues.where(priority: values)
end

def filter_by_status(issues)
values = @filters[:status].map{ |s| Issue.statuses[s] }.compact
issues.where(status: values)
end
end
15 changes: 15 additions & 0 deletions app/services/user_filter_service.rb
@@ -0,0 +1,15 @@
class UserFilterService
def initialize(filters)
@filters = filters
end

def filter(users)
users = filter_by_username(users) if @filters[:username]
users.where(@filters.except(:username))
end

private
def filter_by_username(users)
users.where('username ilike ?', "%#{@filters[:username]}%")
end
end
45 changes: 44 additions & 1 deletion spec/controllers/api/v1/issues_controller_spec.rb
Expand Up @@ -2,12 +2,55 @@

RSpec.describe Api::V1::IssuesController, type: :controller do
describe 'GET #index' do
let!(:issue) { FactoryGirl.create(:issue) }
let!(:issue) { FactoryGirl.create(:issue, priority: 'major') }

it 'assigns all issues as @issues' do
get :index
expect(assigns(:issues)).to eq([issue])
end

context 'filtering' do
let!(:other_issue) { FactoryGirl.create(:issue, title: 'different', description: 'different', priority: 'minor') }

context 'by id' do
it 'includes only issues with matching id' do
get :index, filters: { id: [issue.id] }
expect(assigns(:issues)).to eq([issue])
end
end

context 'by title' do
it 'includes only issues with matching title' do
get :index, filters: { title: issue.title }
expect(assigns(:issues)).to eq([issue])
end
end

context 'by description' do
it 'includes only issues with matching description' do
get :index, filters: { description: issue.description }
expect(assigns(:issues)).to eq([issue])
end
end

context 'by priority' do
it 'includes only issues with matching priority' do
get :index, filters: { priority: [issue.priority] }
expect(assigns(:issues)).to eq([issue])
end
end

context 'by status' do
before do
issue.fixed!
end

it 'includes only issues with matching status' do
get :index, filters: { status: ['fixed'] }
expect(assigns(:issues)).to eq([issue])
end
end
end
end

describe 'GET #show' do
Expand Down
18 changes: 18 additions & 0 deletions spec/controllers/api/v1/users_controller_spec.rb
Expand Up @@ -7,6 +7,24 @@
get :index
expect(assigns(:users)).to eq([user])
end

context 'filtering' do
let!(:other_user) { FactoryGirl.create(:user, username: 'different') }

context 'by id' do
it 'includes only users with matching id' do
get :index, filters: { id: [user.id] }
expect(assigns(:users)).to eq([user])
end
end

context 'by username' do
it 'includes only users with matching id' do
get :index, filters: { username: user.username }
expect(assigns(:users)).to eq([user])
end
end
end
end

describe 'GET #show' do
Expand Down
65 changes: 65 additions & 0 deletions spec/services/issue_filter_service_spec.rb
@@ -0,0 +1,65 @@
require 'rails_helper'

RSpec.describe IssueFilterService, type: :model do
subject { described_class.new(filters).filter(Issue.all) }
let!(:issue1) { FactoryGirl.create(:issue, priority: 'major') }
let!(:issue2) { FactoryGirl.create(:issue, title: 'different', description: 'different', priority: 'minor') }

context '#filter' do
context 'by id' do
let(:filters) do
{
id: [issue1.id]
}
end

it 'includes only issues with matching id' do
expect(subject).to eq([issue1])
end
end

context 'by title' do
let(:filters) do
{ title: issue1.title }
end

it 'includes only issues with matching title' do
expect(subject).to eq([issue1])
end
end

context 'by description' do
let(:filters) do
{ description: issue1.description }
end

it 'includes only issues with matching description' do
expect(subject).to eq([issue1])
end
end

context 'by priority' do
let(:filters) do
{ priority: [issue1.priority] }
end

it 'includes only issues with matching priority' do
expect(subject).to eq([issue1])
end
end

context 'by status' do
before do
issue1.fixed!
end

let(:filters) do
{ status: ['fixed'] }
end

it 'includes only issues with matching status' do
expect(subject).to eq([issue1])
end
end
end
end
31 changes: 31 additions & 0 deletions spec/services/user_filter_service_spec.rb
@@ -0,0 +1,31 @@
require 'rails_helper'

RSpec.describe UserFilterService, type: :model do
subject { described_class.new(filters).filter(User.all) }
let!(:user1) { FactoryGirl.create(:user) }
let!(:user2) { FactoryGirl.create(:user, username: 'other') }

context '#filter' do
context 'by id' do
let(:filters) do
{
id: [user1.id]
}
end

it 'includes only issues with matching id' do
expect(subject).to eq([user1])
end
end

context 'by username' do
let(:filters) do
{ username: user1.username }
end

it 'includes only issues with matching username' do
expect(subject).to eq([user1])
end
end
end
end

0 comments on commit 87048f4

Please sign in to comment.