Skip to content

base fixes: create person and query performances #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
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
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ gem "jbuilder"
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]
gem 'slim-rails'
gem "jsbundling-rails"
gem 'kaminari'
gem 'active_model_serializers'

group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[ mri mingw x64_mingw ]
gem "rspec-rails"
gem "pry-rails"
gem "factory_bot_rails"
end

group :development do
Expand All @@ -37,6 +40,7 @@ group :test do
gem "rspec-its"
gem "shoulda"
gem "simplecov", require: false
gem "rails-controller-testing"
end

# Use Redis for Action Cable
Expand Down
45 changes: 45 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ GEM
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
active_model_serializers (0.10.15)
actionpack (>= 4.1)
activemodel (>= 4.1)
case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
activejob (7.0.8.6)
activesupport (= 7.0.8.6)
globalid (>= 0.3.6)
Expand All @@ -68,6 +73,9 @@ GEM
tzinfo (~> 2.0)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
airborne (0.0.18)
rest-client (~> 1.7, >= 1.7.2)
rspec (~> 3.1, >= 3.1.0)
annotate (3.2.0)
activerecord (>= 3.2, < 8.0)
rake (>= 10.4, < 14.0)
Expand All @@ -83,6 +91,8 @@ GEM
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
case_transform (0.2)
activesupport
coderay (1.1.3)
concurrent-ruby (1.3.4)
crass (1.0.6)
Expand All @@ -94,6 +104,7 @@ GEM
reline (>= 0.3.8)
diff-lcs (1.5.1)
docile (1.4.1)
domain_name (0.6.20240107)
erubi (1.13.0)
factory_bot (6.5.0)
activesupport (>= 5.0.0)
Expand All @@ -104,6 +115,8 @@ GEM
i18n (>= 1.8.11, < 2)
globalid (1.2.1)
activesupport (>= 6.1)
http-cookie (1.0.8)
domain_name (~> 0.5)
i18n (1.14.6)
concurrent-ruby (~> 1.0)
io-console (0.7.2)
Expand All @@ -115,6 +128,19 @@ GEM
activesupport (>= 5.0.0)
jsbundling-rails (1.3.1)
railties (>= 6.0.0)
jsonapi-renderer (0.2.2)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
kaminari-activerecord (= 1.2.2)
kaminari-core (= 1.2.2)
kaminari-actionview (1.2.2)
actionview
kaminari-core (= 1.2.2)
kaminari-activerecord (1.2.2)
activerecord
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
logger (1.6.1)
loofah (2.23.1)
crass (~> 1.0.2)
Expand All @@ -127,6 +153,7 @@ GEM
marcel (1.0.4)
matrix (0.4.2)
method_source (1.1.0)
mime-types (2.99.3)
mini_mime (1.1.5)
minitest (5.25.2)
net-imap (0.5.1)
Expand All @@ -138,6 +165,7 @@ GEM
timeout
net-smtp (0.5.0)
net-protocol
netrc (0.11.0)
nio4r (2.7.4)
nokogiri (1.16.7-arm64-darwin)
racc (~> 1.4)
Expand Down Expand Up @@ -171,6 +199,10 @@ GEM
activesupport (= 7.0.8.6)
bundler (>= 1.15.0)
railties (= 7.0.8.6)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
Expand All @@ -192,7 +224,15 @@ GEM
regexp_parser (2.9.2)
reline (0.5.11)
io-console (~> 0.5)
rest-client (1.8.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 3.0)
netrc (~> 0.7)
rexml (3.3.9)
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.2)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.3)
Expand Down Expand Up @@ -279,9 +319,12 @@ GEM

PLATFORMS
arm64-darwin-23
arm64-darwin-24
x86_64-linux

DEPENDENCIES
active_model_serializers
airborne
annotate
capybara
cssbundling-rails
Expand All @@ -290,9 +333,11 @@ DEPENDENCIES
faker
jbuilder
jsbundling-rails
kaminari
pry-rails
puma (~> 5.0)
rails (~> 7.0.1)
rails-controller-testing
redis (~> 4.0)
rspec-its
rspec-rails
Expand Down
23 changes: 23 additions & 0 deletions app/controllers/api/companies_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Api::CompaniesController < ActionController::API
def index
if params[:name].present?
companies = Company.where('LOWER(name) LIKE ?', "%#{params[:name]&.downcase}%").page(params[:page] || 1).per(params[:per_page] || 10)
else
companies = Company.all.page(params[:page] || 1).per(10)
end

render json: { meta: pagination_meta(companies), data: companies }, status: 200
end

private

def pagination_meta(scope)
{
current_page: scope.current_page,
next_page: scope.next_page,
prev_page: scope.prev_page,
total_pages: scope.total_pages,
total_count: scope.total_count
}
end
end
23 changes: 23 additions & 0 deletions app/controllers/api/people_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Api::PeopleController < ActionController::API
def index
if params[:email].present?
people = Person.where(email: params[:email]).page(params[:page] || 1).per(params[:per_page] || 10)
else
people = Person.includes(:company).page(params[:page] || 1).per(10)
end

render json: { meta: pagination_meta(people), data: people }, status: 200
end

private

def pagination_meta(scope)
{
current_page: scope.current_page,
next_page: scope.next_page,
prev_page: scope.prev_page,
total_pages: scope.total_pages,
total_count: scope.total_count
}
end
end
40 changes: 40 additions & 0 deletions app/controllers/companies_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class CompaniesController < ApplicationController
before_action :load_company, only: [:edit, :update]

def index
@companies = Company.all.page(params[:page] || 1).per(10)
end

def new
@company = Company.new
end

def edit; end

def create
if Company.create(company_attributes)
redirect_to companies_path, notice: 'Successfully created entry'
else
render :create, alert: 'Unsuccessfully created entry'
end
end

def update
if @company.update(company_attributes)
redirect_to companies_path, notice: 'Successfully updated entry'
else
render :edit, alert: 'Unsuccessfully created entry'
end
end

private

def company_attributes
params.require(:company).permit(:name)
end

def load_company
@company = Company.find(params[:id])
end
end

15 changes: 9 additions & 6 deletions app/controllers/people_controller.rb
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
class PeopleController < ApplicationController

def index
@people = Person.all
@people = Person.includes(:company).page(params[:page] || 1).per(10)
end

def new
@person = Person.new
@companies = Company.all.order(:name)
end

def create
if Person.create(person_attributes)
redirect_to people_path, notice: 'Successfully created entry'
@person = Person.new(person_attributes)

if @person.save
redirect_to people_path, notice: 'Person successfully created'
else
render :create, alert: 'Unsuccessfully created entry'
@companies = Company.page(params[:page] || 1).per(10)
render :new
end
end

private

def person_attributes
params.require(:person).permit(:name, :email, :phone)
params.require(:person).permit(:name, :email, :phone_number, :company_id)
end

end

3 changes: 2 additions & 1 deletion app/models/person.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#

class Person < ApplicationRecord

belongs_to :company, optional: true

validates :name, :phone_number, :email, presence: true
end
8 changes: 8 additions & 0 deletions app/serializers/person_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# app/serializers/person_serializer.rb
class PersonSerializer < ActiveModel::Serializer
attributes :id, :name, :email, :phone_number, :company_name

def company_name
object.company&.name
end
end
8 changes: 8 additions & 0 deletions app/views/companies/edit.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
h2 Creating an entry

= form_for @company, class: 'row' do |f|
.col-auto
= f.label :name, class: 'form-label'
= f.text_field :name, class: 'form-control'
.col-auto.mt-4
= f.submit class: 'btn btn-primary'
25 changes: 25 additions & 0 deletions app/views/companies/index.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
h2 Viewing companies

table.table
thead
tr
th[scope="col"] ID
th[scope="col"] Name
th[scope="col"] Created At
th[scope="col"] Actions
tbody
- @companies.each do |company|
tr
th[scope="row"]= company&.id
td= company.try(:name)
td= company.try(:created_at).strftime("%m/%d/%Y")
td= link_to "Edit", edit_company_path(company), class: 'btn btn-primary'

.row.justify-content-between
.col-4
= paginate @companies, theme: 'bootstrap3'
= page_entries_info @companies
.col-4
= link_to "New Company", new_company_path, class: 'btn btn-success'


8 changes: 8 additions & 0 deletions app/views/companies/new.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
h2 Creating an entry

= form_for @company, class: 'row' do |f|
.col-auto
= f.label :name, class: 'form-label'
= f.text_field :name, class: 'form-control'
.col-auto.mt-4
= f.submit class: 'btn btn-primary'
3 changes: 3 additions & 0 deletions app/views/kaminari/bootstrap3/_first_page.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
li.page-item
= link_to_unless current_page.first?, raw(t 'views.pagination.first'),
url, remote: remote, class: "page-link"
2 changes: 2 additions & 0 deletions app/views/kaminari/bootstrap3/_gap.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
li.disabled.page-item
= link_to raw(t 'views.pagination.truncate'), '#', class: "page-link"
3 changes: 3 additions & 0 deletions app/views/kaminari/bootstrap3/_last_page.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
li.page-item
= link_to_unless current_page.last?, raw(t 'views.pagination.last'),
url, remote: remote, class: "page-link"
3 changes: 3 additions & 0 deletions app/views/kaminari/bootstrap3/_next_page.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
li.page-item
= link_to_unless current_page.last?, raw(t 'views.pagination.next'),
url, rel: 'next', remote: remote, class: "page-link"
3 changes: 3 additions & 0 deletions app/views/kaminari/bootstrap3/_page.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
li class="#{'active' if page.current?} page-item"
= link_to page, page.current? ? '#' : url,
remote: remote, rel: page.rel, class: "page-link"
13 changes: 13 additions & 0 deletions app/views/kaminari/bootstrap3/_paginator.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
= paginator.render do
ul.pagination
== first_page_tag unless current_page.first?
== prev_page_tag unless current_page.first?

- each_page do |page|
- if page.left_outer? || page.right_outer? || page.inside_window?
== page_tag page
- elsif !page.was_truncated?
== gap_tag

== next_page_tag unless current_page.last?
== last_page_tag unless current_page.last?
3 changes: 3 additions & 0 deletions app/views/kaminari/bootstrap3/_prev_page.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
li.page-item
= link_to_unless current_page.first?, raw(t 'views.pagination.previous'),
url, rel: 'prev', remote: remote, class: "page-link"
2 changes: 2 additions & 0 deletions app/views/layouts/application.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ html[lang="en"]
a.nav-link[aria-current="page" href="/"]All
li.nav-item
= link_to('Create', new_person_path, class: 'nav-link')
li.nav-item
= link_to('Companies', companies_path, class: 'nav-link')
form.d-flex
input.form-control.me-2[type="search" placeholder="Search" aria-label="Search"]
button.btn.btn-outline-success[type="submit"] Search
Expand Down
Loading