From f7adce658ef8865aa4afd48d44c690a33a4b6c1a Mon Sep 17 00:00:00 2001 From: Andrew Tomaka Date: Fri, 9 Oct 2015 16:45:53 -0400 Subject: [PATCH 1/4] Install paper_trail and track all models --- Gemfile | 1 + Gemfile.lock | 6 ++++++ app/models/awaken_type.rb | 2 ++ app/models/card.rb | 2 ++ app/models/character.rb | 2 ++ app/models/leader_skill.rb | 2 ++ app/models/link.rb | 2 ++ app/models/passive_skill.rb | 2 ++ app/models/rarity.rb | 2 ++ app/models/super_attack.rb | 2 ++ app/models/type.rb | 2 ++ app/models/user.rb | 1 + db/migrate/20151009204428_create_versions.rb | 20 ++++++++++++++++++++ db/schema.rb | 13 ++++++++++++- 14 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20151009204428_create_versions.rb diff --git a/Gemfile b/Gemfile index cc61952..280e850 100644 --- a/Gemfile +++ b/Gemfile @@ -16,6 +16,7 @@ gem 'simple_form' gem 'omniauth-reddit', :git => 'git://github.com/jackdempsey/omniauth-reddit.git' gem 'active_model_serializers' +gem 'paper_trail' # AUTHORIZATION gem 'pundit' diff --git a/Gemfile.lock b/Gemfile.lock index ef35c8a..6622a0d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -118,6 +118,10 @@ GEM omniauth-oauth2 (1.3.1) oauth2 (~> 1.0) omniauth (~> 1.2) + paper_trail (4.0.0) + activerecord (>= 3.0, < 6.0) + activesupport (>= 3.0, < 6.0) + request_store (~> 1.1) pg (0.18.3) puma (2.14.0) pundit (1.0.1) @@ -163,6 +167,7 @@ GEM thor (>= 0.18.1, < 2.0) rake (10.4.2) rdoc (4.2.0) + request_store (1.2.0) rolify (4.1.1) ruby-graphviz (1.2.2) sass (3.4.18) @@ -225,6 +230,7 @@ DEPENDENCIES jbuilder (~> 2.0) jquery-rails omniauth-reddit! + paper_trail pg puma pundit diff --git a/app/models/awaken_type.rb b/app/models/awaken_type.rb index 7862d09..3caf9cd 100644 --- a/app/models/awaken_type.rb +++ b/app/models/awaken_type.rb @@ -1,3 +1,5 @@ class AwakenType < ActiveRecord::Base + has_paper_trail + validates :name, presence: true end diff --git a/app/models/card.rb b/app/models/card.rb index 1791328..a69e539 100644 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -1,4 +1,6 @@ class Card < ActiveRecord::Base + has_paper_trail + belongs_to :character belongs_to :rarity belongs_to :type diff --git a/app/models/character.rb b/app/models/character.rb index 2f5c3d1..10142fc 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -1,4 +1,6 @@ class Character < ActiveRecord::Base + has_paper_trail + validates :name, presence: true, uniqueness: { case_sensitive: false } diff --git a/app/models/leader_skill.rb b/app/models/leader_skill.rb index 36e8a22..3a493af 100644 --- a/app/models/leader_skill.rb +++ b/app/models/leader_skill.rb @@ -1,3 +1,5 @@ class LeaderSkill < ActiveRecord::Base + has_paper_trail + validates :description, presence: true end diff --git a/app/models/link.rb b/app/models/link.rb index 78cbc00..a3b5b50 100644 --- a/app/models/link.rb +++ b/app/models/link.rb @@ -1,4 +1,6 @@ class Link < ActiveRecord::Base + has_paper_trail + has_and_belongs_to_many :cards validates :name, presence: true, diff --git a/app/models/passive_skill.rb b/app/models/passive_skill.rb index 3a73da0..6eebdbc 100644 --- a/app/models/passive_skill.rb +++ b/app/models/passive_skill.rb @@ -1,4 +1,6 @@ class PassiveSkill < ActiveRecord::Base + has_paper_trail + validates :name, presence: true validates :description, presence: true diff --git a/app/models/rarity.rb b/app/models/rarity.rb index 39e9d46..bfe10ed 100644 --- a/app/models/rarity.rb +++ b/app/models/rarity.rb @@ -1,4 +1,6 @@ class Rarity < ActiveRecord::Base + has_paper_trail + validates :name, presence: true, uniqueness: { case_sensitive: false } validates :description, presence: true diff --git a/app/models/super_attack.rb b/app/models/super_attack.rb index b8cda47..332c480 100644 --- a/app/models/super_attack.rb +++ b/app/models/super_attack.rb @@ -1,4 +1,6 @@ class SuperAttack < ActiveRecord::Base + has_paper_trail + validates :name, presence: true validates :description, presence: true diff --git a/app/models/type.rb b/app/models/type.rb index bfc271d..a88c3e6 100644 --- a/app/models/type.rb +++ b/app/models/type.rb @@ -1,4 +1,6 @@ class Type < ActiveRecord::Base + has_paper_trail + validates :name, presence: true, uniqueness: { case_sensitive: false } validates :description, presence: true diff --git a/app/models/user.rb b/app/models/user.rb index d185b02..e80109e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,5 @@ class User < ActiveRecord::Base + has_paper_trail rolify after_create :set_admin, if: :first_user? diff --git a/db/migrate/20151009204428_create_versions.rb b/db/migrate/20151009204428_create_versions.rb new file mode 100644 index 0000000..3876dfc --- /dev/null +++ b/db/migrate/20151009204428_create_versions.rb @@ -0,0 +1,20 @@ +class CreateVersions < ActiveRecord::Migration + + # The largest text column available in all supported RDBMS is + # 1024^3 - 1 bytes, roughly one gibibyte. We specify a size + # so that MySQL will use `longtext` instead of `text`. Otherwise, + # when serializing very large objects, `text` might not be big enough. + TEXT_BYTES = 1_073_741_823 + + def change + create_table :versions do |t| + t.string :item_type, :null => false + t.integer :item_id, :null => false + t.string :event, :null => false + t.string :whodunnit + t.text :object, :limit => TEXT_BYTES + t.datetime :created_at + end + add_index :versions, [:item_type, :item_id] + end +end diff --git a/db/schema.rb b/db/schema.rb index 8bd23fe..81bdf6a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20151008192100) do +ActiveRecord::Schema.define(version: 20151009204428) do create_table "awaken_types", force: :cascade do |t| t.string "name" @@ -134,4 +134,15 @@ ActiveRecord::Schema.define(version: 20151008192100) do add_index "users_roles", ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id" + create_table "versions", force: :cascade do |t| + t.string "item_type", null: false + t.integer "item_id", null: false + t.string "event", null: false + t.string "whodunnit" + t.text "object", limit: 1073741823 + t.datetime "created_at" + end + + add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id" + end From 73d5f3635763239bb2178b23a88d80a715619d26 Mon Sep 17 00:00:00 2001 From: Andrew Tomaka Date: Tue, 13 Oct 2015 16:38:33 -0400 Subject: [PATCH 2/4] Add listing and showing of old versions --- app/assets/javascripts/admin/versions.coffee | 3 ++ app/assets/stylesheets/admin/versions.scss | 3 ++ app/controllers/admin/cards_controller.rb | 2 + app/controllers/admin/versions_controller.rb | 16 ++++++++ app/helpers/admin/versions_helper.rb | 2 + app/views/admin/cards/edit.html.slim | 2 + app/views/admin/cards/show.html.slim | 42 ++++++++++++++++++++ app/views/admin/versions/_list.html.slim | 16 ++++++++ app/views/admin/versions/show.html.slim | 0 config/routes.rb | 1 + 10 files changed, 87 insertions(+) create mode 100644 app/assets/javascripts/admin/versions.coffee create mode 100644 app/assets/stylesheets/admin/versions.scss create mode 100644 app/controllers/admin/versions_controller.rb create mode 100644 app/helpers/admin/versions_helper.rb create mode 100644 app/views/admin/cards/show.html.slim create mode 100644 app/views/admin/versions/_list.html.slim create mode 100644 app/views/admin/versions/show.html.slim diff --git a/app/assets/javascripts/admin/versions.coffee b/app/assets/javascripts/admin/versions.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/admin/versions.coffee @@ -0,0 +1,3 @@ +# 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/ diff --git a/app/assets/stylesheets/admin/versions.scss b/app/assets/stylesheets/admin/versions.scss new file mode 100644 index 0000000..222d135 --- /dev/null +++ b/app/assets/stylesheets/admin/versions.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Admin::Versions controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/admin/cards_controller.rb b/app/controllers/admin/cards_controller.rb index ce1de73..eb20739 100644 --- a/app/controllers/admin/cards_controller.rb +++ b/app/controllers/admin/cards_controller.rb @@ -32,6 +32,8 @@ class Admin::CardsController < Admin::BaseController def edit authorize @card + + @versions = @card.versions end def update diff --git a/app/controllers/admin/versions_controller.rb b/app/controllers/admin/versions_controller.rb new file mode 100644 index 0000000..83ec1c9 --- /dev/null +++ b/app/controllers/admin/versions_controller.rb @@ -0,0 +1,16 @@ +class Admin::VersionsController < Admin::BaseController + before_action :set_version, only: [:show] + + def show + type = @version.class.to_s.underscore + instance_variable_set('@' + type, @version) + + render "admin/#{type.pluralize}/show" + end + + private + + def set_version + @version = PaperTrail::Version.find(params[:id]).reify + end +end diff --git a/app/helpers/admin/versions_helper.rb b/app/helpers/admin/versions_helper.rb new file mode 100644 index 0000000..40b273c --- /dev/null +++ b/app/helpers/admin/versions_helper.rb @@ -0,0 +1,2 @@ +module Admin::VersionsHelper +end diff --git a/app/views/admin/cards/edit.html.slim b/app/views/admin/cards/edit.html.slim index fbedb45..9312321 100644 --- a/app/views/admin/cards/edit.html.slim +++ b/app/views/admin/cards/edit.html.slim @@ -1 +1,3 @@ == render 'form' + +== render 'admin/versions/list', versions: @versions diff --git a/app/views/admin/cards/show.html.slim b/app/views/admin/cards/show.html.slim new file mode 100644 index 0000000..9708e90 --- /dev/null +++ b/app/views/admin/cards/show.html.slim @@ -0,0 +1,42 @@ +.row + .col-md-4 + strong Game ID Number: + = @card.gameid + .col-md-4 + strong Title: + = @card.title + .col-md-4 + strong Character: + = @card.character.name +.row + .col-md-4 + strong Rarity: + = @card.rarity.name + .col-md-4 + strong Type: + = @card.type.name + .col-md-4 + strong Awaken Type: + = @card.awaken_type.name +.row + .col-md-6 + strong Leader Skill: + = @card.leader_skill.description + .col-md-6 + strong Passive Skill: + = @card.passive_skill.name +.row + .col-md-12 + strong Super Attack: + = "#{@card.super_attack.name} - #{@card.super_attack.description}" +.row + .col-md-6 + strong Dokkan Card: + - if @card.dokkan_card + = @card.dokkan_card.full_name +.row + .col-md-12 + strong Links: + ul + - @card.links.each do |link| + li= link.name diff --git a/app/views/admin/versions/_list.html.slim b/app/views/admin/versions/_list.html.slim new file mode 100644 index 0000000..803b0cf --- /dev/null +++ b/app/views/admin/versions/_list.html.slim @@ -0,0 +1,16 @@ +.row + .col-md-12 + table.table.table-striped.table-hover + thead + tr + th ID + th Event + th Date + th Modified By + tbody + - versions.each do |version| + tr + td= link_to version.id, admin_version_path(version) + td= version.event + td= version.created_at + td= User.find(version.version_author).nickname diff --git a/app/views/admin/versions/show.html.slim b/app/views/admin/versions/show.html.slim new file mode 100644 index 0000000..e69de29 diff --git a/config/routes.rb b/config/routes.rb index be64e71..7b91c03 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -22,6 +22,7 @@ Rails.application.routes.draw do resources :super_attacks resources :types resources :users, except: [:new, :create] + resources :versions, only: [:show] end namespace :api do From dc55fc10f1961dd1cbcda328dbecac557e6f0f4d Mon Sep 17 00:00:00 2001 From: Andrew Tomaka Date: Wed, 14 Oct 2015 08:45:24 -0400 Subject: [PATCH 3/4] Support associations (no has_and_belongs_to) --- app/controllers/admin/versions_controller.rb | 2 +- ...51014121823_create_version_associations.rb | 17 +++++++++++++++ ...4_add_transaction_id_column_to_versions.rb | 11 ++++++++++ db/schema.rb | 21 ++++++++++++++----- 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20151014121823_create_version_associations.rb create mode 100644 db/migrate/20151014121824_add_transaction_id_column_to_versions.rb diff --git a/app/controllers/admin/versions_controller.rb b/app/controllers/admin/versions_controller.rb index 83ec1c9..d16a86d 100644 --- a/app/controllers/admin/versions_controller.rb +++ b/app/controllers/admin/versions_controller.rb @@ -11,6 +11,6 @@ class Admin::VersionsController < Admin::BaseController private def set_version - @version = PaperTrail::Version.find(params[:id]).reify + @version = PaperTrail::Version.find(params[:id]).reify(has_one: true) end end diff --git a/db/migrate/20151014121823_create_version_associations.rb b/db/migrate/20151014121823_create_version_associations.rb new file mode 100644 index 0000000..12c8f06 --- /dev/null +++ b/db/migrate/20151014121823_create_version_associations.rb @@ -0,0 +1,17 @@ +class CreateVersionAssociations < ActiveRecord::Migration + def self.up + create_table :version_associations do |t| + t.integer :version_id + t.string :foreign_key_name, :null => false + t.integer :foreign_key_id + end + add_index :version_associations, [:version_id] + add_index :version_associations, [:foreign_key_name, :foreign_key_id], :name => 'index_version_associations_on_foreign_key' + end + + def self.down + remove_index :version_associations, [:version_id] + remove_index :version_associations, :name => 'index_version_associations_on_foreign_key' + drop_table :version_associations + end +end \ No newline at end of file diff --git a/db/migrate/20151014121824_add_transaction_id_column_to_versions.rb b/db/migrate/20151014121824_add_transaction_id_column_to_versions.rb new file mode 100644 index 0000000..67e0e22 --- /dev/null +++ b/db/migrate/20151014121824_add_transaction_id_column_to_versions.rb @@ -0,0 +1,11 @@ +class AddTransactionIdColumnToVersions < ActiveRecord::Migration + def self.up + add_column :versions, :transaction_id, :integer + add_index :versions, [:transaction_id] + end + + def self.down + remove_index :versions, [:transaction_id] + remove_column :versions, :transaction_id + end +end diff --git a/db/schema.rb b/db/schema.rb index 81bdf6a..33c88fa 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20151009204428) do +ActiveRecord::Schema.define(version: 20151014121824) do create_table "awaken_types", force: :cascade do |t| t.string "name" @@ -134,15 +134,26 @@ ActiveRecord::Schema.define(version: 20151009204428) do add_index "users_roles", ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id" + create_table "version_associations", force: :cascade do |t| + t.integer "version_id" + t.string "foreign_key_name", null: false + t.integer "foreign_key_id" + end + + add_index "version_associations", ["foreign_key_name", "foreign_key_id"], name: "index_version_associations_on_foreign_key" + add_index "version_associations", ["version_id"], name: "index_version_associations_on_version_id" + create_table "versions", force: :cascade do |t| - t.string "item_type", null: false - t.integer "item_id", null: false - t.string "event", null: false + t.string "item_type", null: false + t.integer "item_id", null: false + t.string "event", null: false t.string "whodunnit" - t.text "object", limit: 1073741823 + t.text "object", limit: 1073741823 t.datetime "created_at" + t.integer "transaction_id" end add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id" + add_index "versions", ["transaction_id"], name: "index_versions_on_transaction_id" end From dfa4ffeaeacaf92aac42f11d4272e234036c1500 Mon Sep 17 00:00:00 2001 From: Andrew Tomaka Date: Wed, 14 Oct 2015 09:21:16 -0400 Subject: [PATCH 4/4] Implement undoing --- app/controllers/admin/base_controller.rb | 8 ++++++++ app/controllers/admin/cards_controller.rb | 9 ++++++--- app/controllers/admin/versions_controller.rb | 17 ++++++++++++++--- app/views/application/_flash_message.html.slim | 2 +- config/routes.rb | 2 ++ 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 807fd9a..67c01ad 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -1,3 +1,11 @@ class Admin::BaseController < ApplicationController layout 'admin' + + private + + def undo_link(item) + view_context.link_to('Undo this change', + admin_revert_version_path(id: item.version.last), + method: :post) + end end diff --git a/app/controllers/admin/cards_controller.rb b/app/controllers/admin/cards_controller.rb index eb20739..882a488 100644 --- a/app/controllers/admin/cards_controller.rb +++ b/app/controllers/admin/cards_controller.rb @@ -24,7 +24,8 @@ class Admin::CardsController < Admin::BaseController authorize @card if @card.save - redirect_to admin_cards_path, notice: 'Card was created' + redirect_to admin_cards_path, + notice: "Card was created. #{undo_link(@card)}" else render :new end @@ -40,7 +41,8 @@ class Admin::CardsController < Admin::BaseController authorize @card if @card.update(card_params) - redirect_to admin_cards_path, notice: 'Card was updated' + redirect_to admin_cards_path, + notice: "Card was updated. #{undo_link(@card)}" else render :edit end @@ -51,7 +53,8 @@ class Admin::CardsController < Admin::BaseController @card.destroy - redirect_to admin_cards_path, notice: 'Card was deleted' + redirect_to admin_cards_path, + notice: "Card was deleted. #{undo_link(@card)}" end private diff --git a/app/controllers/admin/versions_controller.rb b/app/controllers/admin/versions_controller.rb index d16a86d..af99796 100644 --- a/app/controllers/admin/versions_controller.rb +++ b/app/controllers/admin/versions_controller.rb @@ -1,16 +1,27 @@ class Admin::VersionsController < Admin::BaseController - before_action :set_version, only: [:show] - def show + @version = PaperTrail::Version.find(params[:id]).reify(has_one: true) + type = @version.class.to_s.underscore instance_variable_set('@' + type, @version) render "admin/#{type.pluralize}/show" end + def revert + @version = PaperTrail::Version.find(params[:id]) + + if @version.reify(has_one: true) + @version.reify(has_one: true).save! + else + @version.item.destroy + end + + redirect_to :back, notice: "Undid #{@version.event}!" + end + private def set_version - @version = PaperTrail::Version.find(params[:id]).reify(has_one: true) end end diff --git a/app/views/application/_flash_message.html.slim b/app/views/application/_flash_message.html.slim index e604085..5e45690 100644 --- a/app/views/application/_flash_message.html.slim +++ b/app/views/application/_flash_message.html.slim @@ -2,4 +2,4 @@ button.close type='button' data-dismiss='alert' span aria-hidden='true' × span.sr-only Close - = message + = raw(message) diff --git a/config/routes.rb b/config/routes.rb index 7b91c03..5151a74 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,6 +12,8 @@ Rails.application.routes.draw do get '/dashboard', to: 'dashboard#index' + post '/versions/revert', to: 'versions#revert', as: 'revert_version' + resources :awaken_types resources :cards resources :characters