Skip to content

Commit

Permalink
Merge pull request #21 from drskinner/TCS-0145
Browse files Browse the repository at this point in the history
TCS-0145: Zone model, controller, and views
  • Loading branch information
drskinner committed May 26, 2019
2 parents 835d13a + da6e17e commit b5644a8
Show file tree
Hide file tree
Showing 20 changed files with 281 additions and 3 deletions.
64 changes: 64 additions & 0 deletions app/controllers/zones_controller.rb
@@ -0,0 +1,64 @@
class ZonesController < ApplicationController
load_and_authorize_resource

def index
sort = params[:sort] || :id
direction = params[:direction] || :asc

@zones = Zone.accessible_by(current_ability)
.search(params.slice(:name_contains, :by_owner_id))
.order(sort => direction)
.page(params[:page])
end

def show
@zone = Zone.find(params[:id])
end

def new
@zone = Zone.new
end

def create
@zone = Zone.new(zone_params)

if @zone.save
redirect_to @zone
else
render 'new'
end
end

def edit
@zone = Zone.find(params[:id])
end

def update
@zone = Zone.find(params[:id])

if @zone.update(zone_params)
redirect_to @zone
else
render 'edit'
end
end

def destroy
@zone = Zone.find(params[:id])
@zone.destroy

redirect_to zones_path
end

private

def zone_params
params.require(:zone).permit(:name,
:filename,
:author,
:owner_id,
:min_vnum,
:max_vnum)
end

end
3 changes: 3 additions & 0 deletions app/models/ability.rb
Expand Up @@ -13,15 +13,18 @@ def initialize(user)
can [:read, :update, :create], Social
can :read, User
can :update, User, id: user.id
can :read, Zone

when 'builder'
can :read, Social
can :read, User
can :update, User, id: user.id
can :read, Zone

when 'guest'
can :read, Social, id: 1..10
cannot :manage, User
can :read, Zone
end
end
end
5 changes: 5 additions & 0 deletions app/models/user.rb
Expand Up @@ -16,6 +16,7 @@ class User < ApplicationRecord

scope :name_contains, ->(name) { where('first_name ILIKE ?', "%#{name}%") }
scope :by_role_id, ->(role_id) { where(role_id: role_id) }
scope :internal, -> { joins(:role).where.not('roles.name': 'guest') }

PRONOUN_CLASSES = %i[female male neutral]

Expand Down Expand Up @@ -44,6 +45,10 @@ def gsa?
role.name == 'gsa'
end

def to_s
name_display
end

def name_display
last_name.blank? ? first_name : "#{first_name} #{last_name}"
end
Expand Down
14 changes: 14 additions & 0 deletions app/models/zone.rb
@@ -0,0 +1,14 @@
class Zone < ApplicationRecord
include Searchable

belongs_to :owner, class_name: "User"

validates_presence_of :name, :filename, :author, :owner_id, :min_vnum, :max_vnum

scope :name_contains, ->(name) { where('name ILIKE ?', "%#{name}%") }
scope :by_owner_id, ->(owner_id) { where(owner_id: owner_id) }

def owner_id_display
owner.name_display
end
end
4 changes: 2 additions & 2 deletions app/views/layouts/application.html.erb
Expand Up @@ -30,9 +30,9 @@
<nav id="top-nav" class="row">
<%= link_to 'Socials', socials_path, class: 'navbar-link pr-1' %>|
<% if can? :read, User %>
<%= link_to 'Users', users_path, class: 'navbar-link pl-1' if can? :read, User %>|
<%= link_to 'Users', users_path, class: 'navbar-link px-1' if can? :read, User %>|
<% end %>
Zones
<%= link_to 'Zones', zones_path, class: 'navbar-link pl-1' if can? :read, Zone %>
</nav>
<% end %>

Expand Down
26 changes: 26 additions & 0 deletions app/views/zones/_form.html.erb
@@ -0,0 +1,26 @@
<%= simple_form_for @zone, wrapper: :horizontal_form do |f| %>
<div class="row">
<div class="col-md-12">
<%= render partial: 'alerts/validation_errors', locals: { f: f } %>
</div>

<div class="col-md-12">
<fieldset>
<legend><%= I18n.t('zone.fieldset.metadata') %></legend>
<%= f.input :name, as: :string %>
<%= f.input :filename, as: :string %>
<%= f.input :author, as: :string %>
<%= f.input :owner_id,
as: :select,
collection: User.internal,
prompt: I18n.t('activerecord.attributes.zone.owner_id_prompt') %>
<%= f.input :min_vnum, as: :integer %>
<%= f.input :max_vnum, as: :integer %>
</fieldset>

<%= f.button :submit unless action_name == 'show' %>
</div>
</div>
<% end %>


26 changes: 26 additions & 0 deletions app/views/zones/_index_table.html.erb
@@ -0,0 +1,26 @@
<div id="index-table">

<table class=" table table-striped">
<tr>
<%= sortable 'name' %>
<%= sortable 'owner_id' %>
<%= sortable 'min_vnum' %>
<th colspan="3" class="actions"></th>
</tr>

<% @zones.each do |zone| %>
<tr>
<td><%= zone.name %></td>
<td><%= zone.owner_id_display %></td>
<td><%= zone.min_vnum %>&ndash;<%= zone.max_vnum %></td>
<td><%= link_to 'View', zone_path(zone) %></td>
<td><%= link_to 'Edit', edit_zone_path(zone) if can?(:edit, zone) %></td>
<td><%= link_to 'Delete', zone_path(zone), method: :delete, data: { confirm: 'Are you sure?' } if can?(:destroy, zone) %></td>
</tr>
<% end %>
</table>

<%= paginate @zones, theme: 'twitter-bootstrap-4',
pagination_class: 'pagination-md',
nav_class: 'd-inline-b' %>
</div>
24 changes: 24 additions & 0 deletions app/views/zones/_search.html.erb
@@ -0,0 +1,24 @@
<%= form_tag zones_path, method: 'get', class: 'search-form' do %>
<fieldset>
<legend>
<span><%= I18n.t('search.title') %></span>
</legend>
<div class="search-field-top">
<label><%= I18n.t('search.name_contains') %></label>
<%= text_field_tag :name_contains,
params['name_contains'],
class: 'search-text' %>
</div>
<div class="search-field">
<label><%= I18n.t('search.by_owner_id') %></label>
<%= select_tag :by_owner_id,
options_for_select(User.internal.collect { |u| [u.to_s, u.id] }, params[:by_owner_id]),
prompt: I18n.t('select.owner'),
class: 'search-select' %>
</div>
<div class="search-buttons">
<%= submit_tag I18n.t('button.search.submit'), name: nil, class: 'btn btn-default' %>
<%= link_to I18n.t('button.search.clear'), zones_path, class: 'btn btn-clear' %>
</div>
</fieldset>
<% end %>
3 changes: 3 additions & 0 deletions app/views/zones/edit.html.erb
@@ -0,0 +1,3 @@
<% content_for :title, I18n.t('page.action_title.edit', record: @zone.name) %>
<%= render 'form' %>
11 changes: 11 additions & 0 deletions app/views/zones/index.html.erb
@@ -0,0 +1,11 @@
<% content_for :title, I18n.t('page.action_title.index', model: 'Zones') %>

<div class="row">
<div class="col-lg-9">
<%= render 'index_table' %>
</div>

<div class="col-lg-3">
<%= render 'search' %>
</div>
</div>
3 changes: 3 additions & 0 deletions app/views/zones/new.html.erb
@@ -0,0 +1,3 @@
<% content_for :title, I18n.t('page.action_title.new', model: 'Zone') %>
<%= render 'form' %>
3 changes: 3 additions & 0 deletions app/views/zones/show.html.erb
@@ -0,0 +1,3 @@
<% content_for :title, I18n.t('page.action_title.show', record: @zone.name) %>
<%= render 'form' %>
40 changes: 40 additions & 0 deletions config/initializers/new_framework_defaults_5_2.rb
@@ -0,0 +1,40 @@
# Be sure to restart your server when you modify this file.
#
# This file contains migration options to ease your Rails 5.2 upgrade.
#
# Once upgraded flip defaults one by one to migrate to the new default.
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.

# Make Active Record use stable #cache_key alongside new #cache_version method.
# This is needed for recyclable cache keys.
# Rails.application.config.active_record.cache_versioning = true

# Use AES-256-GCM authenticated encryption for encrypted cookies.
# Also, embed cookie expiry in signed or encrypted cookies for increased security.
#
# This option is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 5.2.
#
# Existing cookies will be converted on read then written with the new scheme.
# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true

# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages
# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true.
# Rails.application.config.active_support.use_authenticated_message_encryption = true

# Add default protection from forgery to ActionController::Base instead of in
# ApplicationController.
# Rails.application.config.action_controller.default_protect_from_forgery = true

# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and
# 'f' after migrating old data.
# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true

# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header.
# Rails.application.config.active_support.use_sha1_digests = true

# Make `form_with` generate id attributes for any generated HTML tags.
# Rails.application.config.action_view.form_with_generates_ids = true

Rails.application.config.active_record.belongs_to_required_by_default = false
1 change: 1 addition & 0 deletions config/locales/layout.yml
Expand Up @@ -24,4 +24,5 @@ en:
show: "View %{record}"
show_command: "View command: %{record}"
select:
owner: "-- Select Owner --"
role: "-- Select Role --"
21 changes: 21 additions & 0 deletions config/locales/models/zone/en.yml
@@ -0,0 +1,21 @@
en:
activerecord:
attributes:
zone:
author: "Author"
filename: "Area Filename"
max_vnum: "Maximum VNUM"
min_vnum: "Minimum VNUM"
name: "Name"
owner: "Owner"
owner_id: "Owner"
owner_id_prompt: "-- Select Builder --"
errors:
models:
zone:
attributes:
owner_id:
required: "must be an internal user"
zone:
fieldset:
metadata: "Zone Metadata"
1 change: 1 addition & 0 deletions config/locales/search.yml
@@ -1,5 +1,6 @@
en:
search:
by_owner_id: "Owner"
by_role_id: "User Role"
name_contains: "Name Contains"
title: "Search Options"
4 changes: 4 additions & 0 deletions config/locales/sortable.yml
Expand Up @@ -8,3 +8,7 @@ en:
first_name: "Name"
role_id: "Role"
updated_at: "Last Update"
zones:
min_vnum: "VNUM Range"
name: "Name"
owner_id: "Owner"
2 changes: 2 additions & 0 deletions config/routes.rb
Expand Up @@ -12,4 +12,6 @@
end

resources :users, path: 'profiles'

resources :zones
end
14 changes: 14 additions & 0 deletions db/migrate/20190510122217_create_zones.rb
@@ -0,0 +1,14 @@
class CreateZones < ActiveRecord::Migration[5.2]
def change
create_table :zones do |t|
t.string :name, null: false
t.string :filename, null: false
t.string :author, null: false
t.references :owner, index: true, foreign_key: { to_table: :users }
t.integer :min_vnum, null: false
t.integer :max_vnum, null: false

t.timestamps
end
end
end
15 changes: 14 additions & 1 deletion db/schema.rb
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2019_03_26_235517) do
ActiveRecord::Schema.define(version: 2019_05_10_122217) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -54,4 +54,17 @@
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end

create_table "zones", force: :cascade do |t|
t.string "name", null: false
t.string "filename", null: false
t.string "author", null: false
t.bigint "owner_id"
t.integer "min_vnum", null: false
t.integer "max_vnum", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["owner_id"], name: "index_zones_on_owner_id"
end

add_foreign_key "zones", "users", column: "owner_id"
end

0 comments on commit b5644a8

Please sign in to comment.