Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ coverage
config/settings.local.yml
config/settings/*.local.yml
config/environments/*.local.yml

.idea
.byebug_history
6 changes: 6 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ gem 'activeadmin'
gem 'activeadmin_addons'
gem 'devise'

# Сериализация данных
gem 'alba'

# Пагинация
gem 'kaminari'

group :development, :test do
gem 'bundler-audit'
gem 'capybara'
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ GEM
uri (>= 0.13.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
alba (3.5.0)
ostruct (~> 0.6)
arbre (1.7.0)
activesupport (>= 3.0.0)
ruby2_keywords (>= 0.0.2)
Expand Down Expand Up @@ -448,6 +450,7 @@ DEPENDENCIES
activeadmin
activeadmin_addons
activerecord-import
alba
bundler-audit
capybara
config
Expand All @@ -460,6 +463,7 @@ DEPENDENCIES
factory_bot_rails
fasterer
ffaker
kaminari
parallel
pg
pry-byebug
Expand Down
7 changes: 7 additions & 0 deletions app/controllers/books_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class BooksController < ApplicationController
def index
@books = Book.all.page(params[:page])

render json: BookSerializer.new(@books).serialize
end
end
11 changes: 11 additions & 0 deletions app/serializers/author_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class AuthorSerializer
include Alba::Resource

attributes :id, :full_name

private

def full_name(author)
author.slice(:first_name, :middle_name, :last_name).values.join(' ')
end
end
10 changes: 10 additions & 0 deletions app/serializers/book_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class BookSerializer
include Alba::Resource

root_key :books

attributes :id, :title, :insno, :libid

many :authors
one :language
end
5 changes: 5 additions & 0 deletions app/serializers/language_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class LanguageSerializer
include Alba::Resource

attributes :id, :slug, :name
end
4 changes: 2 additions & 2 deletions config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ default: &default
postgre: &postgre
host: <%= ENV.fetch('POSTGRES_HOST', 'localhost') %>
port: <%= ENV.fetch('POSTGRES_PORT', '5432') %>
username: <%= ENV.fetch('POSTGRES_USER') { 'igorsimdyanov' } %>
password: <%= ENV.fetch('POSTGRES_PASSWORD') { '' } %>
username: <%= ENV.fetch('POSTGRES_USER') { 'postgres' } %>
password: <%= ENV.fetch('POSTGRES_PASSWORD') { 'postgres' } %>

development:
<<: *default
Expand Down
14 changes: 14 additions & 0 deletions config/initializers/kaminari_config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

Kaminari.configure do |config|
config.default_per_page = Settings.app.items_per_page
# config.max_per_page = nil
# config.window = 4
# config.outer_window = 0
# config.left = 0
# config.right = 0
# config.page_method_name = :page
# config.param_name = :page
# config.max_pages = nil
# config.params_on_first_page = false
end
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
# # end
# end

get 'books(/:page)', to: 'books#index'

# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
# Can be used by load balancers and uptime monitors to verify that the app is live.
get 'up' => 'rails/health#show', as: :rails_health_check
Expand Down
21 changes: 21 additions & 0 deletions docs/rails_layers.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@startuml

actor User

participant "Router" as Routing
participant "Controller" as Controller
participant "Model" as Model
participant "Business Logic" as BusinessLogic
participant "Serializer" as Serializer

User -> Routing: HTTP Request
Routing -> Controller: Routes to Controller
Controller -> BusinessLogic: Some Business Logic
BusinessLogic -> Model: Query
Model -> BusinessLogic: Records
BusinessLogic -> Controller: Processed Data
Controller -> Serializer: Serialize
Serializer -> Controller: Serialized Data
Controller -> User: HTTP Response

@enduml
42 changes: 42 additions & 0 deletions spec/controllers/books_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'rails_helper'

RSpec.describe BooksController, type: :controller do
describe 'GET #index' do
let(:language) { create(:language) }
let(:folder) { create(:folder) }
let!(:books) { create_list(:book, 21, folder:, language:) }

before do
get :index
end

it 'returns a successful response' do
expect(response).to have_http_status(:success)
end

it 'returns JSON with all books' do
json_response = JSON.parse(response.body)

expect(json_response.size).to eq(20)

json_response.each_with_index do |book_json, index|
expect(book_json['id']).to eq(books[index].id)
expect(book_json['title']).to eq(books[index].title)
expect(book_json['insno']).to eq(books[index].insno)
expect(book_json['libid']).to eq(books[index].libid)
end
end

context 'with pagination' do
before do
get :index, params: { page: 2 }
end

it 'returns only the first page of books' do
json_response = JSON.parse(response.body)

expect(json_response.size).to eq(books[20..].size)
end
end
end
end
1 change: 1 addition & 0 deletions spec/factories/books.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
FactoryBot.define do
factory :book do
title { FFaker::Book.title }
insno { FFaker::Book.isbn }
libid { 3064 }
size { 9836 }
filename { 3064 }
Expand Down
17 changes: 17 additions & 0 deletions spec/serializers/author_serializer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
RSpec.describe AuthorSerializer, type: :serializer do
let(:author) { create(:full_author) }

describe 'serialization' do
context 'when correct author is passed' do
subject { described_class.new(author) }

it "return correct json response" do
serialized = JSON.parse(subject.to_json)
full_name = [ author.first_name, author.middle_name, author.last_name ].join(' ')

expect(serialized['id']).to eq(author.id)
expect(serialized['full_name']).to eq(full_name)
end
end
end
end
21 changes: 21 additions & 0 deletions spec/serializers/book_serializer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
RSpec.describe BookSerializer, type: :serializer do
let(:book) { create(:book_with_authors) }

describe 'serialization' do
context 'when correct book is passed' do
subject { described_class.new(book) }

it "return correct json response" do
serialized = JSON.parse(subject.to_json)

expect(serialized.dig('books', 'id')).to eq(book.id)
expect(serialized.dig('books', 'title')).to eq(book.title)
expect(serialized.dig('books', 'insno')).to eq(book.insno)
expect(serialized.dig('books', 'libid')).to eq(book.libid)
expect(serialized.dig('books', 'authors').size).to eq(book.authors.size)
expect(serialized.dig('books', 'language', 'id')).to eq(book.language.id)
expect(serialized.dig('books', 'language', 'name')).to eq(book.language.name)
end
end
end
end
17 changes: 17 additions & 0 deletions spec/serializers/language_serializer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
RSpec.describe LanguageSerializer, type: :serializer do
let(:language) { create(:language) }

describe 'serialization' do
context 'when correct language is passed' do
subject { described_class.new(language) }

it "return correct json response" do
serialized = JSON.parse(subject.to_json)

expect(serialized['id']).to eq(language.id)
expect(serialized['slug']).to eq(language.slug)
expect(serialized['name']).to eq(language.name)
end
end
end
end