diff --git a/Gemfile b/Gemfile index 91a3d70..8c466a3 100644 --- a/Gemfile +++ b/Gemfile @@ -5,7 +5,6 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby "2.7.4" -gem "jbuilder", "~> 2.7" gem "pg", "~> 1.1" gem "puma", "~> 5.0" gem "rails", "~> 6.1.4" @@ -15,11 +14,12 @@ gem "webpacker", "~> 5.0" gem "bootsnap", ">= 1.4.4", require: false gem "devise" -gem "devise-bootstrap-views" gem "devise-i18n" +gem "devise-bootstrap-views" + +gem "tailwindcss-rails" gem "administrate" gem "graphql" -gem "tailwindcss-rails" gem "httparty" gem "pundit" @@ -42,3 +42,7 @@ group :development do gem "listen", "~> 3.3" gem "spring" end + +group :test do + gem "shoulda-matchers", "~> 5.0" +end diff --git a/Gemfile.lock b/Gemfile.lock index f894b7f..abdc3b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -121,8 +121,6 @@ GEM multi_xml (>= 0.5.2) i18n (1.8.10) concurrent-ruby (~> 1.0) - jbuilder (2.11.2) - activesupport (>= 5.0.0) jquery-rails (4.4.0) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) @@ -271,6 +269,8 @@ GEM tilt selectize-rails (0.12.6) semantic_range (3.0.0) + shoulda-matchers (5.0.0) + activesupport (>= 5.2.0) spring (2.1.1) sprockets (4.0.2) concurrent-ruby (~> 1.0) @@ -323,7 +323,6 @@ DEPENDENCIES graphql graphql_playground-rails httparty - jbuilder (~> 2.7) listen (~> 3.3) pg (~> 1.1) pry-byebug @@ -335,6 +334,7 @@ DEPENDENCIES rubocop-rspec rubocop-shopify sass-rails (>= 6) + shoulda-matchers (~> 5.0) spring tailwindcss-rails turbolinks (~> 5) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb new file mode 100644 index 0000000..b8cac1c --- /dev/null +++ b/app/controllers/admin/users_controller.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true +module Admin + class UsersController < Admin::ApplicationController + def valid_action?(name, resource = resource_class) + ["new", "destroy"].exclude?(name.to_s) && super + end + end +end diff --git a/app/dashboards/user_dashboard.rb b/app/dashboards/user_dashboard.rb new file mode 100644 index 0000000..41e33f7 --- /dev/null +++ b/app/dashboards/user_dashboard.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true +require "administrate/base_dashboard" + +class UserDashboard < Administrate::BaseDashboard + # ATTRIBUTE_TYPES + # a hash that describes the type of each of the model's fields. + # + # Each different type represents an Administrate::Field object, + # which determines how the attribute is displayed + # on pages throughout the dashboard. + ATTRIBUTE_TYPES = { + id: Field::Number, + full_name: Field::String, + first_name: Field::String, + last_name: Field::String, + email: Field::String, + created_at: Field::DateTime, + updated_at: Field::DateTime, + }.freeze + + # COLLECTION_ATTRIBUTES + # an array of attributes that will be displayed on the model's index page. + # + # By default, it's limited to four items to reduce clutter on index pages. + # Feel free to add, remove, or rearrange items. + COLLECTION_ATTRIBUTES = [:full_name, :email].freeze + + # SHOW_PAGE_ATTRIBUTES + # an array of attributes that will be displayed on the model's show page. + SHOW_PAGE_ATTRIBUTES = [:id, :first_name, :last_name, :email, :created_at, :updated_at].freeze + + # FORM_ATTRIBUTES + # an array of attributes that will be displayed + # on the model's form (`new` and `edit`) pages. + FORM_ATTRIBUTES = [:first_name, :last_name].freeze + + # COLLECTION_FILTERS + # a hash that defines filters that can be used while searching via the search + # field of the dashboard. + # + # For example to add an option to search for open resources by typing "open:" + # in the search field: + # + # COLLECTION_FILTERS = { + # open: ->(resources) { resources.where(open: true) } + # }.freeze + COLLECTION_FILTERS = {}.freeze + + # Overwrite this method to customize how users are displayed + # across all pages of the admin dashboard. + # + # def display_resource(user) + # "User ##{user.id}" + # end +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000..76a2265 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: users +# +# id :bigint not null, primary key +# email :string not null +# first_name :string not null +# last_name :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_users_on_email (email) UNIQUE +# +class User < ApplicationRecord + validates :first_name, :last_name, :email, presence: true + + def full_name + "#{first_name} #{last_name}" + end +end diff --git a/config/routes.rb b/config/routes.rb index b85e8d8..60f56ab 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,9 +3,10 @@ Rails.application.routes.draw do devise_for :admin_users namespace :admin do + resources :users resources :admin_users - root to: "admin_users#index" + root to: "users#index" end root to: "home#index" diff --git a/db/migrate/20210804230323_create_users.rb b/db/migrate/20210804230323_create_users.rb new file mode 100644 index 0000000..55ca6e0 --- /dev/null +++ b/db/migrate/20210804230323_create_users.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true +class CreateUsers < ActiveRecord::Migration[6.1] + def change + create_table(:users) do |t| + t.string(:first_name, null: false) + t.string(:last_name, null: false) + t.string(:email, null: false) + + t.timestamps + end + + add_index(:users, :email, unique: true) + end +end diff --git a/db/schema.rb b/db/schema.rb index 4abad79..6577b7a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_08_03_222524) do +ActiveRecord::Schema.define(version: 2021_08_04_230323) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -27,4 +27,13 @@ ActiveRecord::Schema.define(version: 2021_08_03_222524) do t.index ["reset_password_token"], name: "index_admin_users_on_reset_password_token", unique: true end + create_table "users", force: :cascade do |t| + t.string "first_name", null: false + t.string "last_name", null: false + t.string "email", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["email"], name: "index_users_on_email", unique: true + end + end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb new file mode 100644 index 0000000..94b73f9 --- /dev/null +++ b/spec/models/user_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: users +# +# id :bigint not null, primary key +# email :string not null +# first_name :string not null +# last_name :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_users_on_email (email) UNIQUE +# +require "rails_helper" + +RSpec.describe(User, type: :model) do + describe "validations" do + it { is_expected.to(validate_presence_of(:first_name)) } + it { is_expected.to(validate_presence_of(:last_name)) } + it { is_expected.to(validate_presence_of(:email)) } + end +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 262e28b..990e786 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -67,3 +67,10 @@ RSpec.configure do |config| # arbitrary gems may also be filtered via: # config.filter_gems_from_backtrace("gem name") end + +Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework(:rspec) + with.library(:rails) + end +end