Commit 90363ae6 by Quang Vinh Nguyen

Add paginate

parent 9095b92a
{
"editor.tabSize": 2
}
\ No newline at end of file
...@@ -6,6 +6,11 @@ ruby '2.5.1' ...@@ -6,6 +6,11 @@ ruby '2.5.1'
gem 'devise', '4.4.3' gem 'devise', '4.4.3'
gem 'redis' gem 'redis'
gem 'json' gem 'json'
gem 'bootstrap'
gem 'jquery-rails'
gem 'kaminari'
gem 'rsolr'
gem 'rsolr-ext'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.0' gem 'rails', '~> 5.2.0'
......
...@@ -48,6 +48,8 @@ GEM ...@@ -48,6 +48,8 @@ GEM
io-like (~> 0.3.0) io-like (~> 0.3.0)
arel (9.0.0) arel (9.0.0)
ast (2.4.0) ast (2.4.0)
autoprefixer-rails (8.6.2)
execjs
bcrypt (3.1.12) bcrypt (3.1.12)
bcrypt (3.1.12-java) bcrypt (3.1.12-java)
bcrypt (3.1.12-x64-mingw32) bcrypt (3.1.12-x64-mingw32)
...@@ -57,6 +59,10 @@ GEM ...@@ -57,6 +59,10 @@ GEM
msgpack (~> 1.0) msgpack (~> 1.0)
bootsnap (1.3.0-java) bootsnap (1.3.0-java)
msgpack (~> 1.0) msgpack (~> 1.0)
bootstrap (4.1.1)
autoprefixer-rails (>= 6.0.3)
popper_js (>= 1.12.9, < 2)
sass (>= 3.5.2)
builder (3.2.3) builder (3.2.3)
byebug (10.0.2) byebug (10.0.2)
capybara (3.2.1) capybara (3.2.1)
...@@ -99,6 +105,8 @@ GEM ...@@ -99,6 +105,8 @@ GEM
railties (>= 3.0.0) railties (>= 3.0.0)
faker (1.8.7) faker (1.8.7)
i18n (>= 0.7) i18n (>= 0.7)
faraday (0.15.2)
multipart-post (>= 1.2, < 3)
ffi (1.9.25) ffi (1.9.25)
ffi (1.9.25-java) ffi (1.9.25-java)
ffi (1.9.25-x64-mingw32) ffi (1.9.25-x64-mingw32)
...@@ -109,11 +117,28 @@ GEM ...@@ -109,11 +117,28 @@ GEM
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
io-like (0.3.0) io-like (0.3.0)
jaro_winkler (1.5.1) jaro_winkler (1.5.1)
jaro_winkler (1.5.1-java)
jbuilder (2.7.0) jbuilder (2.7.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
multi_json (>= 1.2) multi_json (>= 1.2)
jquery-rails (4.3.3)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.1.0) json (2.1.0)
json (2.1.0-java) json (2.1.0-java)
kaminari (1.1.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.1.1)
kaminari-activerecord (= 1.1.1)
kaminari-core (= 1.1.1)
kaminari-actionview (1.1.1)
actionview
kaminari-core (= 1.1.1)
kaminari-activerecord (1.1.1)
activerecord
kaminari-core (= 1.1.1)
kaminari-core (1.1.1)
listen (3.1.5) listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4) rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7) rb-inotify (~> 0.9, >= 0.9.7)
...@@ -135,6 +160,7 @@ GEM ...@@ -135,6 +160,7 @@ GEM
msgpack (1.2.4-x64-mingw32) msgpack (1.2.4-x64-mingw32)
msgpack (1.2.4-x86-mingw32) msgpack (1.2.4-x86-mingw32)
multi_json (1.13.1) multi_json (1.13.1)
multipart-post (2.0.0)
mysql2 (0.5.1) mysql2 (0.5.1)
mysql2 (0.5.1-x64-mingw32) mysql2 (0.5.1-x64-mingw32)
mysql2 (0.5.1-x86-mingw32) mysql2 (0.5.1-x86-mingw32)
...@@ -152,6 +178,7 @@ GEM ...@@ -152,6 +178,7 @@ GEM
parallel (1.12.1) parallel (1.12.1)
parser (2.5.1.0) parser (2.5.1.0)
ast (~> 2.4.0) ast (~> 2.4.0)
popper_js (1.12.9)
powerpack (0.1.1) powerpack (0.1.1)
pry (0.11.3) pry (0.11.3)
coderay (~> 1.1.0) coderay (~> 1.1.0)
...@@ -199,6 +226,11 @@ GEM ...@@ -199,6 +226,11 @@ GEM
responders (2.4.0) responders (2.4.0)
actionpack (>= 4.2.0, < 5.3) actionpack (>= 4.2.0, < 5.3)
railties (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3)
rsolr (2.2.1)
builder (>= 2.1.2)
faraday (>= 0.9.0)
rsolr-ext (1.0.3)
rsolr (>= 1.0.2)
rspec-core (3.7.1) rspec-core (3.7.1)
rspec-support (~> 3.7.0) rspec-support (~> 3.7.0)
rspec-expectations (3.7.0) rspec-expectations (3.7.0)
...@@ -227,7 +259,6 @@ GEM ...@@ -227,7 +259,6 @@ GEM
ruby-progressbar (1.9.0) ruby-progressbar (1.9.0)
ruby_dep (1.5.0) ruby_dep (1.5.0)
rubyzip (1.2.1) rubyzip (1.2.1)
safe_yaml (1.0.4)
sass (3.5.6) sass (3.5.6)
sass-listen (~> 4.0.0) sass-listen (~> 4.0.0)
sass-listen (4.0.0) sass-listen (4.0.0)
...@@ -296,6 +327,7 @@ PLATFORMS ...@@ -296,6 +327,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
bootsnap (>= 1.1.0) bootsnap (>= 1.1.0)
bootstrap
byebug byebug
capybara (>= 2.15, < 4.0) capybara (>= 2.15, < 4.0)
chromedriver-helper chromedriver-helper
...@@ -305,16 +337,19 @@ DEPENDENCIES ...@@ -305,16 +337,19 @@ DEPENDENCIES
factory_girl_rails (= 4.9.0) factory_girl_rails (= 4.9.0)
faker (= 1.8.7) faker (= 1.8.7)
jbuilder (~> 2.5) jbuilder (~> 2.5)
jquery-rails
json json
kaminari
listen (>= 3.0.5, < 3.2) listen (>= 3.0.5, < 3.2)
mysql2 (>= 0.4.4, < 0.6.0) mysql2 (>= 0.4.4, < 0.6.0)
pry pry
puma (~> 3.11) puma (~> 3.11)
rails (~> 5.2.0) rails (~> 5.2.0)
redis redis
rsolr
rsolr-ext
rspec-rails rspec-rails
rubocop (= 0.57.1) rubocop (= 0.57.1)
safe_yaml
sass-rails (~> 5.0) sass-rails (~> 5.0)
selenium-webdriver selenium-webdriver
shoulda-matchers (~> 3.1) shoulda-matchers (~> 3.1)
......
...@@ -14,3 +14,6 @@ ...@@ -14,3 +14,6 @@
//= require activestorage //= require activestorage
//= require turbolinks //= require turbolinks
//= require_tree . //= require_tree .
//= require jquery3
//= require popper
//= require bootstrap
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
...@@ -10,6 +10,5 @@ ...@@ -10,6 +10,5 @@
* files in this directory. Styles in this file should be added after the last require_* statement. * files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope. * It is generally better to create a new file per style scope.
* *
*= require_tree .
*= require_self
*/ */
@import "bootstrap";
// Place all the styles related to the Jobs controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
// Place all the styles related to the StaticPages controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
def index
render html: "Yep, It's working ..."
end
end end
class JobsController < ApplicationController
def index
@jobs = Job.search(params[:search]).order('created_at DESC').page(params[:page])
end
def show
@job = Job.find(params[:id])
end
def city
@cities = City.all.select { |city| city.jobs.any? }
end
def jobs_in_city
@city = City.find_by(slug: params[:slug])
@jobs = get_jobs_in_city(@city.id).page(params[:page])
end
def home
@jobs = Job.all.order(updated_at: :desc).take(5)
@cities = City.all.select{ |city| city.jobs.any? }.take(8)
end
def get_jobs_in_city(city_id)
Job.where(city_id: city_id)
end
end
class StaticPagesController < ApplicationController
def home
@jobs = Job.all.order(updated_at: :desc).take(5)
@cities = City.all.take(6)
end
end
module JobsHelper
def number_of_jobs_in_city(city_id)
jobs = Job.where(city_id: city_id)
jobs.count
end
end
module StaticPagesHelper
end
...@@ -26,4 +26,11 @@ class Job < ApplicationRecord ...@@ -26,4 +26,11 @@ class Job < ApplicationRecord
validates :welfare, presence: true, length: { maximum: 1000 } validates :welfare, presence: true, length: { maximum: 1000 }
validates :condition, presence: true, length: { maximum: 1000 } validates :condition, presence: true, length: { maximum: 1000 }
validates :link, presence: true validates :link, presence: true
paginates_per 10
def self.search(search)
# where("name LIKE ? OR ingredients LIKE ? OR cooking_instructions LIKE ?", "%#{search}%", "%#{search}%", "%#{search}%", "%#{search}%")
where("title LIKE ?", "%#{search}%")
end
end end
<li>
<div class="card" style="width: 40rem;">
<div class="card-body">
<h5 class="card-title"><%= job.title %></h5>
<p class="card-text">some job description</p>
<p>Update date: <%= time_ago_in_words(job.created_at) %> ago. </p>
<!-- <a href="#" class="card-link">Show job</a> -->
<%= link_to 'Show job', job, class: 'card-link' %>
</div>
</div>
</li>
<h3>show all <%= pluralize(@cities.count, 'city') %></h3>
<ul class='list-group'>
<% @cities.each do |city| %>
<li class = 'list-group-item'>
<%= city.name %>
<%= link_to pluralize(number_of_jobs_in_city(city.id), 'job'),
controller: 'jobs',
action: 'jobs_in_city',
slug: city.slug %>
</li>
<% end %>
</ul>
\ No newline at end of file
<div class='container'>
<div class='container'>
<nav class='navbar navbar-light bg-light'>
<%= form_tag( jobs_path,
method: 'get',
class: 'form-inline') do %>
<%= text_field_tag :search, params[:search],
placeholder: 'Search Jobs',
class: 'form-control mr-sm-2'%>
<%= submit_tag 'Search', name: nil,
class: 'btn btn-outline-success my-2 my-sm-0' %>
<% end %>
</nav>
</div>
<div class='jobs-list'>
<ul>
<%= render @jobs %>
</ul>
</div>
<h4> Cities list </h4>
<div class='cities-list'>
<ul>
<% @cities.each do |city| %>
<li>
<%= city.name %>
<%= link_to pluralize(number_of_jobs_in_city(city.id), 'job'),
controller: 'jobs',
action: 'jobs_in_city',
slug: city.slug %>
</li>
<% end %>
</ul>
</div
</div>
<h1>View jobs</h1>
<nav class='navbar navbar-light bg-light'>
<%= form_tag(jobs_path, method: 'get',
class: 'form-inline') do %>
<%= text_field_tag :search, params[:search],
placeholder: 'Search Jobs',
class: 'form-control mr-sm-2'%>
<%= submit_tag 'Search', name: nil,
class: 'btn btn-outline-success my-2 my-sm-0' %>
<% end %>
</nav>
<ul class='jobs'>
<%= paginate @jobs, outer_window: 3 %>
<%= render @jobs %>
</ul>
\ No newline at end of file
<h4><%= @city.name %> have <%= pluralize(number_of_jobs_in_city(@city.id), 'job') %></h4>
<%#= link_to 'Back', city_jobs_path %>
<div class='container'>
<div class='jobs-list'>
<ul>
<%= paginate @jobs, outer_window: 3 %>
<%= render @jobs %>
</ul>
</div>
</div>
\ No newline at end of file
<div class="row">
<aside class="col-md-16">
<section class="user_info">
<h2>Job detail</h2>
<h4>
<%= @job.title %>
</h4>
<p>
<%= @job.description %>
</p>
</section>
</aside>
</div>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<%= link_to 'Venjobs', root_path, class: 'navbar-brand' %>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<%= link_to 'Home', root_path, class: 'nav-link' %>
</li>
<li class="nav-item active">
<%= link_to 'City', city_jobs_path, class: 'nav-link' %>
</li>
</ul>
</div>
</nav>
...@@ -10,21 +10,12 @@ ...@@ -10,21 +10,12 @@
</head> </head>
<body> <body>
<%= render 'layouts/header' %>
<% if notice %> <div class="container">
<p class="alert alert-success"><%= notice %></p> <% flash.each do |message_type, message| %>
<% end %> <%= content_tag(:div, message, class: "alert alert-#{message_type}") %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %> <% end %>
<!--
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %> alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<%= value %>
</div>
<% end %>
-->
<%= yield %> <%= yield %>
</div>
</body> </body>
</html> </html>
<div class='container'>
<div class='jobs-list'>
<ul>
<% @jobs.each do |job| %>
<li>
<div class="card">
<h5 class="card-header"><%= job.title %></h5>
<div class="card-body">
<h5 class="card-title"><%= job.company.name %></h5>
<p class="card-text"><% job.description %></p>
<%= link_to 'Show job', job, class: 'card-link' %>
</div>
</div>
</li>
<% end %>
</ul>
</div>
<h4> Cities list </h4>
<div class='cities-list'>
<ul>
<% @cities.each do |city| %>
<li>
<%= city.code %> -- <%= city.name %>
<%= link_to 'Show', controller: 'jobs', action: 'jobs_in_city', slug: city.slug %>
</li>
<% end %>
</ul>
</div
</div>
# frozen_string_literal: true
Kaminari.configure do |config|
# config.default_per_page = 25
# 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.params_on_first_page = false
end
Rails.application.routes.draw do Rails.application.routes.draw do
root to: 'jobs#home'
resources :jobs do
collection do
get 'home'
get 'city'
get 'city/:slug', to: 'jobs#jobs_in_city'
get 'search'
end
end
devise_for :users devise_for :users
root to: 'application#index'
end end
# frozen_string_literal: true
namespace :importdb do namespace :importdb do
require 'pry' require 'pry'
require 'json' require 'json'
...@@ -10,8 +12,8 @@ namespace :importdb do ...@@ -10,8 +12,8 @@ namespace :importdb do
provs = Redis.new provs = Redis.new
provs_hash_arr = provs.smembers 'cities' provs_hash_arr = provs.smembers 'cities'
provs_hash = JSON.parse(provs_hash_arr[0]) provs_hash = JSON.parse(provs_hash_arr[0])
provs_hash.each do |code, prov| provs_hash.each do |_code, prov|
City.create!( name: prov['name'], City.create!(name: prov['name'],
slug: prov['slug'], slug: prov['slug'],
city_type: prov['type'], city_type: prov['type'],
name_with_type: prov['name_with_type'], name_with_type: prov['name_with_type'],
...@@ -19,7 +21,6 @@ namespace :importdb do ...@@ -19,7 +21,6 @@ namespace :importdb do
end end
end end
desc 'import data to companies table' desc 'import data to companies table'
task companies: :environment do task companies: :environment do
Company.create!( Company.create!(
...@@ -48,12 +49,12 @@ namespace :importdb do ...@@ -48,12 +49,12 @@ namespace :importdb do
jobs_redis = Redis.new jobs_redis = Redis.new
jobs_yaml_arr = jobs_redis.smembers 'crawled' jobs_yaml_arr = jobs_redis.smembers 'crawled'
jobs_yaml_arr.each do |row| jobs_yaml_arr.each do |row|
job = YAML.load(row) job = YAML.safe_load(row)
next if job[1].blank? || !!Job.find_by(title: job[1]) || !!Job.find_by(link: job[14]) next if job[1].blank? || !!Job.find_by(title: job[1]) || !!Job.find_by(link: job[14])
Job.create!( Job.create!(
title: job[1], title: job[1],
company_id: 1, company_id: 1,
city_id: 1, city_id: get_city_id(job[3]),
industry_id: 1, industry_id: 1,
position: 'NA', position: 'NA',
salary: '1_000', salary: '1_000',
...@@ -63,8 +64,20 @@ namespace :importdb do ...@@ -63,8 +64,20 @@ namespace :importdb do
published: true, published: true,
welfare: 'NA', welfare: 'NA',
condition: 'NA', condition: 'NA',
link: job[14], link: job[14]
) )
end end
end end
# Return id of city id database
def get_city_id(city_name = 'Hồ Chí Minh')
city_query = City.where(name: city_name)
if city_query.any?
city_query.each do |city|
return city['id']
end
else
return 59
end
end
end end
require 'rails_helper'
RSpec.describe JobsController, type: :controller do
describe "GET #index" do
it "returns http success" do
get :index
expect(response).to have_http_status(:success)
end
end
end
require 'rails_helper'
RSpec.describe StaticPagesController, type: :controller do
describe "GET #home" do
it "returns http success" do
get :home
expect(response).to have_http_status(:success)
end
end
end
require 'rails_helper'
# Specs in this file have access to a helper object that includes
# the JobsHelper. For example:
#
# describe JobsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe JobsHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end
require 'rails_helper'
# Specs in this file have access to a helper object that includes
# the StaticPagesHelper. For example:
#
# describe StaticPagesHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe StaticPagesHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end
require 'rails_helper'
RSpec.describe "jobs/index.html.erb", type: :view do
pending "add some examples to (or delete) #{__FILE__}"
end
require 'rails_helper'
RSpec.describe "static_pages/home.html.erb", type: :view do
pending "add some examples to (or delete) #{__FILE__}"
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment