Commit c2fd5587 by phuctmZigexn

Merge branch 'Task/10_create_job_list_page_ID4' into 'master'

Task/10 create job list page id4

See merge request !10
parents d71790ab f2e311ea
...@@ -46,6 +46,7 @@ group :development do ...@@ -46,6 +46,7 @@ group :development do
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring' gem 'spring'
gem 'rubocop-rails', '~> 2.11', '>= 2.11.3' gem 'rubocop-rails', '~> 2.11', '>= 2.11.3'
gem 'bullet', '~> 6.1', '>= 6.1.4'
end end
group :test do group :test do
...@@ -59,5 +60,6 @@ end ...@@ -59,5 +60,6 @@ end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem 'slim-rails', '~> 3.2' gem 'slim-rails', '~> 3.2'
gem 'kaminari', :git => 'https://github.com/kaminari/kaminari'
gem 'nokogiri', '~> 1.11', '>= 1.11.7' gem 'nokogiri', '~> 1.11', '>= 1.11.7'
gem 'httparty', '~> 0.18.1' gem 'httparty', '~> 0.18.1'
\ No newline at end of file
GIT
remote: https://github.com/kaminari/kaminari
revision: 45f13dbdaa98be3733ffe6b0e8e948da6919f116
specs:
kaminari (1.2.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.1)
kaminari-activerecord (= 1.2.1)
kaminari-core (= 1.2.1)
kaminari-actionview (1.2.1)
actionview
kaminari-core (= 1.2.1)
kaminari-activerecord (1.2.1)
activerecord
kaminari-core (= 1.2.1)
kaminari-core (1.2.1)
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
...@@ -67,6 +84,9 @@ GEM ...@@ -67,6 +84,9 @@ GEM
bootsnap (1.7.5) bootsnap (1.7.5)
msgpack (~> 1.0) msgpack (~> 1.0)
builder (3.2.4) builder (3.2.4)
bullet (6.1.4)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (11.1.3) byebug (11.1.3)
capybara (3.35.3) capybara (3.35.3)
addressable addressable
...@@ -219,6 +239,7 @@ GEM ...@@ -219,6 +239,7 @@ GEM
tzinfo (2.0.4) tzinfo (2.0.4)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
unicode-display_width (2.0.0) unicode-display_width (2.0.0)
uniform_notifier (1.14.2)
web-console (4.1.0) web-console (4.1.0)
actionview (>= 6.0.0) actionview (>= 6.0.0)
activemodel (>= 6.0.0) activemodel (>= 6.0.0)
...@@ -245,10 +266,12 @@ PLATFORMS ...@@ -245,10 +266,12 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
bootsnap (>= 1.4.4) bootsnap (>= 1.4.4)
bullet (~> 6.1, >= 6.1.4)
byebug byebug
capybara (>= 3.26) capybara (>= 3.26)
httparty (~> 0.18.1) httparty (~> 0.18.1)
jbuilder (~> 2.7) jbuilder (~> 2.7)
kaminari!
listen (~> 3.3) listen (~> 3.3)
mysql2 (~> 0.5) mysql2 (~> 0.5)
nokogiri (~> 1.11, >= 1.11.7) nokogiri (~> 1.11, >= 1.11.7)
......
// @import "bootstrap"; // @import "bootstrap";
$white: #fff;
$gray-100: #f8f9fa;
$gray-200: #e9ecef;
$gray-300: #dee2e6;
$gray-400: #ced4da;
$gray-500: #adb5bd;
$gray-600: #6c757d;
$gray-700: #495057;
$gray-800: #343a40;
$gray-900: #212529;
$black: #000;
// reset css // reset css
*{ *{
...@@ -34,12 +23,12 @@ header { ...@@ -34,12 +23,12 @@ header {
li { li {
margin-left: 18px; margin-left: 18px;
a { a {
color: $gray-400; color: #ced4da;
font-size: 18px; font-size: 18px;
text-decoration: none; text-decoration: none;
font-weight: 500; font-weight: 500;
&:hover{ &:hover{
color: $white; color: #fff;
} }
} }
} }
...@@ -58,9 +47,9 @@ footer { ...@@ -58,9 +47,9 @@ footer {
color: #777; color: #777;
a { a {
text-decoration:none; text-decoration:none;
color: $gray-600; color: #6c757d;
&:hover { &:hover {
color: $gray-900; color: #212529;
} }
} }
small { small {
...@@ -74,4 +63,4 @@ footer { ...@@ -74,4 +63,4 @@ footer {
margin-left: 15px; margin-left: 15px;
} }
} }
} }
\ No newline at end of file
// Place all the styles related to the Top controller here. // Top page
// They will automatically be included in application.css. // search
// You can use Sass (SCSS) here: https://sass-lang.com/ // banner
.banner {
background-image: url('banner.jpg');
min-height: 200px;
background-repeat: no-repeat;
background-size: cover;
}
// latest-job
.latest-job {
.job-item {
font-size: 14px;
.job-title {
text-decoration: none;
color: black;
font-size: 20px;
font-weight: 500;
}
.job-caption {
line-height: 18px;
.job-company {
text-decoration: none;
font-size: 14px;
color: #495057;
}
.job-salary {
color: #008563;
margin: 0;
}
.job-locations {
ul {
list-style: none;
margin: 0 0 6px 0;
padding: 0;
color: #495057;
}
}
.job-desc {
overflow: hidden;
text-overflow: ellipsis;
line-height: 18px;
-webkit-line-clamp: 2;
max-height: 36px;
display: -webkit-box;
-webkit-box-orient: vertical;
}
}
}
}
// top_cities
.top_cities {
.city-item {
margin-bottom: 12px;
a {
font-size: 18px;
text-decoration: none;
color: #287ab9;
margin: 10px 0;
}
}
.all-cities-btn {
color: #287ab9;
font-size: 20px;
text-decoration: none;
}
.all-cities-btn:hover {
text-decoration: underline;
}
}
// top_industries
.top_industries {
.industry-item {
margin-bottom: 12px;
a {
font-size: 18px;
text-decoration: none;
color: #287ab9;
margin: 10px 0;
}
}
.all-industries-btn {
color: #287ab9;
font-size: 20px;
text-decoration: none;
}
.all-industries-btn:hover {
text-decoration: underline;
}
}
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
end end
class CitiesController < ApplicationController
def index
@regions = City.regions.keys
@job_quantity_by_region = City.job_quantity_by_region
end
end
class IndustriesController < ApplicationController
def index
@job_quantity_by_industry = Industry.job_quantity_by_industry
end
end
class JobsController < ApplicationController
def index
if job_params.present?
search
else
@jobs = Job.sort_by_date(page: params[:page], per_page: Job::JOB_PER_PAGE)
end
end
def show
@job = Job.find(params[:id])
end
private
def search
if job_params.key?(:model) && job_params.key?(:slug) # search by model
model = params[:model].classify.constantize
@target = model.find_by(slug: job_params[:slug])
@jobs = @target.jobs.sort_by_date(page: params[:page], per_page: Job::JOB_PER_PAGE)
end
end
def job_params
params.permit(:model, :slug, :search)
end
end
class TopController < ApplicationController class TopController < ApplicationController
def index def index
@total_job = Job.count
@latest_jobs = Job.sort_by_date(per_page: Job::LATEST_JOBS_LIMIT)
@top_cities = City.top_jobs
@top_industries = Industry.top_jobs
end end
end end
module ApplicationHelper module ApplicationHelper
def full_title(page_title = '')
base_title = 'VenJob'
if page_title.empty?
base_title
else
"#{page_title} | #{base_title}"
end
end
def show_location(list)
list.map(&:name).join(' | ')
end
def show_breadcrumb(list, model)
a = list.map do |item|
link_to item.name, job_list_path(model: model, slug: item.slug), class: 'mx-1 text-decoration-none text-info'
end
a.join('|').html_safe
end
# breadcrumb
# def show_breadcrumb(job)
# a = link_to 'Home', root_path, class: 'text-decoration-none text-info mx-1 '
# span = tag.span '>', class: 'mx-1'
# arr = [a, show_item(job.cities, :city), show_item(job.industries, :industry), job.title]
# arr.join(span).html_safe
# end
end end
class City < ApplicationRecord class City < ApplicationRecord
has_and_belongs_to_many :jobs TOP_JOB_COUNT = 9
enum region: { vietnam: 0, international: 1 } enum region: { vietnam: 0, international: 1 }
has_and_belongs_to_many :jobs
validates :slug, presence: true, uniqueness: { case_sensitive: true }
def self.top_jobs
joins(:jobs).group(:name, :slug).order('COUNT(jobs.id) DESC').count.take(TOP_JOB_COUNT)
end
def self.job_quantity_by_region
regions.each_with_object({}) do |(name, _), hash|
hash[name.to_sym] = send(name).joins(:jobs).group(:name, :slug).count
end
end
end end
class Industry < ApplicationRecord class Industry < ApplicationRecord
TOP_JOB_COUNT = 9
has_and_belongs_to_many :jobs has_and_belongs_to_many :jobs
validates :slug, presence: true, uniqueness: { case_sensitive: true }
def self.top_jobs
joins(:jobs).group(:name, :slug).order('COUNT(jobs.id) DESC').count.take(TOP_JOB_COUNT)
end
def self.job_quantity_by_industry
joins(:jobs).group(:name, :slug).count
end
end end
class Job < ApplicationRecord class Job < ApplicationRecord
LATEST_JOBS_LIMIT = 5
JOB_PER_PAGE = 20
has_and_belongs_to_many :industries has_and_belongs_to_many :industries
has_and_belongs_to_many :cities has_and_belongs_to_many :cities
belongs_to :company belongs_to :company
has_many :apply_jobs, dependent: :destroy has_many :apply_jobs, dependent: :destroy
has_many :favorite_jobs, dependent: :destroy has_many :favorite_jobs, dependent: :destroy
has_many :history_job, dependent: :destroy has_many :history_job, dependent: :destroy
def self.sort_by_date(page: 1, per_page: limit)
includes(:cities, :cities_jobs, :company).order(created_at: :desc).page(page).per(per_page).references(:cities)
end
end end
/region
.countries-list
.container.py-5
h2.mt-0 REGION
hr.my-4
.row
- @regions.each do |region|
.col-lg-4.col-md-6.text-center
.mt-5
h3.h4.mb-2.text-white.see-more-text= link_to region.upcase, anchor: region
// cities list
.cities-list
.container
- @job_quantity_by_region.each do |region, city_job_count|
.countries-job-list id=region
.container-fullwidth.py-5
h2.mt-0
= region.upcase
hr.my-4
.row
- city_job_count.each do |city, count|
.col-lg-4.col-md-6.text-center
.mt-5
.city-item
h3.h4.mb-2.see-more-text= link_to city[0], job_list_path(model: :city, slug: city[1]) , class:'text-decoration-none fw-normal text-reset'
p.text-muted.mb-0= pluralize(count, 'job')
\ No newline at end of file
.countries-list
.container.py-5
h2.mt-0 INDUSTRIES
hr.my-4
#info-box.row
- @job_quantity_by_industry.each do |name, job_count|
.col-lg-6.col-md-6.text-center
.mt-5
h3.h4.mb-2.see-more-text= link_to name[0], job_list_path(model: :industry, slug: name[1]) , class:'text-decoration-none fw-normal text-reset'
p.text-muted.mb-0= pluralize(job_count, 'job')
hr.divider.my-4
- provide(:title, 'Job list page')
/ search box
= render 'shared/search'
.container
h1.mt-5
= @name
hr.my-4
.no-padding.d-flex.align-items-center.flex-column
.page-info.p-2
= page_entries_info @jobs
.page-info.p-2
= paginate @jobs
.container
.container
- @jobs.each do |job|
/ job
.job-item
= link_to job.title, job, class: 'job-title fs-3 text-decoration-none text-reset'
.job-caption
= link_to job.company.name, '#', class: 'job-company text-decoration-none text-secondary'
p.job-salary.text-success
| Salary: #{job.salary}
ul.list-unstyled
= show_location(job.cities)
.job-desc
= truncate(simple_format(job.description), escape: false, length: 250)
hr.my-4
.no-padding.d-flex.align-items-center.flex-column
.page-info.p-2
= page_entries_info @jobs
.page-info.p-2
= paginate @jobs
\ No newline at end of file
ruby:
city_list = @job.cities
industry_list = @job.industries
/ html
.container.my-5
/ breadcrumb
.breadcrumb
= link_to 'Home', root_path, class: 'text-decoration-none text-info'
span.mx-1 >
.text-info
= show_breadcrumb(city_list, :city)
span.mx-1 >
.text-info
= show_breadcrumb(industry_list, :industry)
span.mx-1 >
= @job.title
hr.my-4
/ job details
.job-detail.my5
.job-apply.d-flex.align-items-center.justify-content-between
h2.align-items-start
= @job.title
= link_to 'Apply for this job', '#', class: 'btn btn-primary'
p.text-secondary
= @job.company.name
.row.bg-light
.col-4
ul.list-unstyled
li
strong.d-block
| Location
p
= show_location(city_list)
li
strong
| Salary
p.text-success
= @job.salary
.col-4
ul.list-unstyled
li
strong
| Type
p
= @job.job_type
li
strong
| Position
p
= @job.position
.col-4
ul.list-unstyled
li
strong
| Experience
p
= @job.experience
li
strong
| Expiration date
p
= @job.expiration_date.strftime('%d/%m/%Y')
.job-benefits.my-4
h3
| Benefits
.row
- @job.benefit.split('---').each do |benefit|
li.list-unstyled.col-4.text-secondary
= benefit
.job-desc.my-4
h3
| Description
= @job.description.html_safe
.job-req.my-4
h3
| Requirement
= @job.requirement.html_safe
.job-info.my-4
h3
| Other info
- @job.other_info.split('---').each do |info|
li.text-secondary
= info
.job-apply.d-flex.align-items-center.justify-content-between
= link_to 'Apply for this job', '#', class: 'btn btn-primary'
= link_to 'Favorite', '#', class: 'btn btn-primary'
li.page-item
= link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, remote: remote, class: 'page-link'
li.page-item.disabled
= link_to raw(t 'views.pagination.truncate'), '#', class: 'page-link'
li.page-item
= link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, remote: remote, class: 'page-link'
li.page-item
= link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, rel: 'next', remote: remote, class: 'page-link'
- if page.current?
li.page-item.active
= content_tag :a, page, data: { remote: remote }, rel: page.rel, class: 'page-link'
- else
li.page-item
= link_to page, url, remote: remote, rel: page.rel, class: 'page-link'
= paginator.render do
nav
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?
li.page-item
= link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, rel: 'prev', remote: remote, class: 'page-link'
footer.footer footer.footer
small small
| The | The
= link_to "VenJob", root_path = link_to 'VenJob', root_path
| by Mai Hoàng Thái Hà | by Mai Hoàng Thái Hà
nav nav
ul ul
li li
= link_to "About", '#' = link_to 'About', '#'
li li
= link_to "Contact", '#' = link_to 'Contact', '#'
\ No newline at end of file \ No newline at end of file
header.navbar.navbar-fixed-top.navbar-inverse header.navbar.navbar-fixed-top.navbar-inverse
.container .container
= link_to image_tag("logo.png", alt: "Zigexn logo", width: "150"), = link_to image_tag('logo.png', alt: 'Zigexn logo', width: '150'),
- root_path - root_path
nav nav
ul.nav.navbar-nav.navbar-right ul.nav.navbar-nav.navbar-right
li li
= link_to "Log in", '#' = link_to 'Log in', '#'
li li
= link_to "Sign up", '#' = link_to 'Sign up', '#'
\ No newline at end of file \ No newline at end of file
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js"> <script src='//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js'>
</script> </script>
<![endif]--> <![endif]-->
\ No newline at end of file
...@@ -2,9 +2,8 @@ doctype html ...@@ -2,9 +2,8 @@ doctype html
html html
head head
title title
| hi = full_title(yield(:title))
- # <%= full_title(yield(:title)) meta[name='viewport' content='width=device-width,initial-scale=1' charset='utf-8']
meta[name="viewport" content="width=device-width,initial-scale=1" charset="utf-8"]
= csrf_meta_tags = csrf_meta_tags
= csp_meta_tag = csp_meta_tag
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'
...@@ -12,6 +11,6 @@ html ...@@ -12,6 +11,6 @@ html
= render 'layouts/shim' = render 'layouts/shim'
body body
= render 'layouts/header' = render 'layouts/header'
.container .container-fluid
= yield = yield
= render 'layouts/footer' = render 'layouts/footer'
\ No newline at end of file
doctype html doctype html
html html
head head
meta[http-equiv="Content-Type" content="text/html; charset=utf-8"] meta[http-equiv='Content-Type' content='text/html; charset=utf-8']
style style
| /* Email styles need to be inline */ | /* Email styles need to be inline */
body body
......
.search.text-center.my-5
.container
.row
.col-md-10.mb-md-0.no-padding
span.fa.fa-search.form-control-feedback
= search_field_tag :search, params[:search], placeholder: 'Find a job', class: 'form-control rounded-left no-border-radius bg-light h-100'
.col-md-2.mb-md-0.no-padding
= button_tag '', class: 'h-100 w-100 btn btn-block btn-lg btn-info', name: nil
| Search
\ No newline at end of file
- provide(:title, 'Home page')
/ search box
.container
.banner.d-flex.justify-content-center.align-items-center
.row
.col
h2.text-white
| Total: #{pluralize(@total_job, "job")}
= render 'shared/search'
/ latest job
.latest-job.mb-5
.container.mb-5
h2
| Latest jobs
hr.my-2
- @latest_jobs.each do |job|
.job-item.mb-4
= link_to job.title, job, class: 'job-title'
.job-caption
= link_to job.company.name, '#', class: 'job-company'
p.job-salary
| Salary:
= job.salary
.job-locations
- city_list = job.cities
= show_location(job.cities)
.job-desc
= truncate(simple_format(job.description), escape: false, length: 250)
hr.my-2
/ top cities
.top_cities.mb-5
.container
h2 Top cities
hr.my-2
.row.align-items-start.mb-3
- @top_cities.each do |city, city_jobs|
.col-4.city-item
= link_to city[0], job_list_path(model: :city, slug: city[1]), class: 'city-name'
span.job-count
| (
= pluralize(city_jobs, 'job')
|)
= link_to 'See all cities', cities_path, class:'all-cities-btn'
/ top industries
.top_industries.mb-5
.container
h2 Top industries
hr.my-2
.row.align-items-start
- @top_industries.each do |industry, industry_jobs|
.col-4.industry-item
= link_to industry[0], job_list_path(model: :industry, slug: industry[1]), class: 'industry-name'
span.job-count
| (
= pluralize(industry_jobs, 'job')
|)
= link_to 'See all industries', industries_path, class:'all-industries-btn'
\ No newline at end of file
...@@ -73,4 +73,20 @@ Rails.application.configure do ...@@ -73,4 +73,20 @@ Rails.application.configure do
# Uncomment if you wish to allow Action Cable access from any origin. # Uncomment if you wish to allow Action Cable access from any origin.
# config.action_cable.disable_request_forgery_protection = true # config.action_cable.disable_request_forgery_protection = true
# Enable bullet, tunrn on logger
# config.after_initialize do
# Bullet.enable = true
# Bullet.bullet_logger = true
# Bullet.raise = true # raise an error if n+1 query occurs
# Bullet.unused_eager_loading_enable = false
# end
config.after_initialize do
Bullet.enable = true
Bullet.alert = true
Bullet.bullet_logger = true
Bullet.console = true
Bullet.rails_logger = true
Bullet.add_footer = true
end
end end
# 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.max_pages = nil
# config.params_on_first_page = false
end
class String
def to_slug
source = %w[
à á â ã è é ê ì í ò ó ô õ ù ú ý ă đ ĩ ũ ơ ư ạ ả ấ ầ ẩ ẫ ậ ắ ằ ẳ ẵ ặ
ẹ ẻ ẽ ế ề ể ễ ệ ỉ ị ọ ỏ ố ồ ổ ỗ ộ ớ ờ ở ỡ ợ ụ ủ ứ ừ ử ữ ự ỳ ỷ ỹ ỵ
].freeze
destination = %w[
a a a a e e e i i o o o o u u y a d i u o u a a a a a a a a a a a a
e e e e e e e e i i o o o o o o o o o o o o u u u u u u u y y y y
].freeze
hash = Hash[source.zip destination]
downcase.encode('ASCII', 'UTF-8', fallback: hash).gsub(' ', '-').parameterize
end
end
Rails.application.routes.draw do Rails.application.routes.draw do
root 'top#index' root 'top#index'
resources :cities, only: %i[index]
resources :industries, only: %i[index]
get '/jobs/:model/:slug', to: 'jobs#index', as: :job_list
resources :jobs, only: %i[index show]
end end
class AddSlugToIndustries < ActiveRecord::Migration[6.1]
def change
add_column :industries, :slug, :string
add_index :industries, :slug, unique: true
end
end
class AddSlugToCities < ActiveRecord::Migration[6.1]
def change
add_column :cities, :slug, :string
add_index :cities, :slug, unique: true
end
end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2021_07_20_055614) do ActiveRecord::Schema.define(version: 2021_07_22_080023) do
create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
t.string "name", null: false t.string "name", null: false
...@@ -54,6 +54,8 @@ ActiveRecord::Schema.define(version: 2021_07_20_055614) do ...@@ -54,6 +54,8 @@ ActiveRecord::Schema.define(version: 2021_07_20_055614) do
t.integer "region" t.integer "region"
t.datetime "created_at", precision: 6, null: false t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false
t.string "slug"
t.index ["slug"], name: "index_cities_on_slug", unique: true
end end
create_table "cities_jobs", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| create_table "cities_jobs", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
...@@ -93,6 +95,8 @@ ActiveRecord::Schema.define(version: 2021_07_20_055614) do ...@@ -93,6 +95,8 @@ ActiveRecord::Schema.define(version: 2021_07_20_055614) do
t.string "name" t.string "name"
t.datetime "created_at", precision: 6, null: false t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false
t.string "slug"
t.index ["slug"], name: "index_industries_on_slug", unique: true
end end
create_table "industries_jobs", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| create_table "industries_jobs", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
......
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