mirror of
https://github.com/openSUSE/osem.git
synced 2026-08-13 19:54:02 +00:00
Setup basic Revision History page
Sets up paper_trail tracking in important models and add conference_id to versions for storing conference_id of conference related objects as metadata.This will help in querying for versions related to conferences. Fix issues with factories & event types initialization.Import paper_trail testing helpers Fix bug: Creating an event creates a useless version with event update Add revert and view changes features to revision history
This commit is contained in:
parent
60877e9593
commit
a45e537bac
49 changed files with 760 additions and 26 deletions
|
|
@ -41,6 +41,7 @@
|
|||
//= require osem-schedule
|
||||
//= require osem-switch
|
||||
//= require osem-bootstrap
|
||||
//= require osem-revisionhistory
|
||||
//= require osem-commercials
|
||||
//= require unobtrusive_flash
|
||||
//= require unobtrusive_flash_bootstrap
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@ $(function () {
|
|||
pagingType: 'full_numbers',
|
||||
"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]]
|
||||
});
|
||||
|
||||
$('#versionstable').DataTable({
|
||||
pagingType: 'full_numbers',
|
||||
order: [[ 0, 'desc' ]]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
10
app/assets/javascripts/osem-revisionhistory.js
Normal file
10
app/assets/javascripts/osem-revisionhistory.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
$(document).ready(function() {
|
||||
$('.show-changeset').click(function(){
|
||||
if ($(this).text() == 'View Changes'){
|
||||
$(this).text('Hide Changes');
|
||||
}else {
|
||||
$(this).text('View Changes');
|
||||
}
|
||||
$('#changeset-' + this.id).toggle();
|
||||
});
|
||||
});
|
||||
|
|
@ -86,3 +86,7 @@ p.comment-body {
|
|||
#proposal-info div dt, #proposal-info div dd {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.changeset{
|
||||
display: none;
|
||||
}
|
||||
|
|
|
|||
58
app/controllers/admin/versions_controller.rb
Normal file
58
app/controllers/admin/versions_controller.rb
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
module Admin
|
||||
class VersionsController < Admin::BaseController
|
||||
skip_authorization_check
|
||||
|
||||
def index
|
||||
authorize! :index, PaperTrail::Version.new(item_type: 'User')
|
||||
conf_ids_for_organizer = current_user.is_admin? ? Conference.pluck(:id) : Conference.with_role(:organizer, current_user).pluck(:id)
|
||||
@versions = PaperTrail::Version.where(["conference_id IN (?) OR item_type = 'User'", conf_ids_for_organizer])
|
||||
end
|
||||
|
||||
def revert_attribute
|
||||
@version = PaperTrail::Version.find(params[:id])
|
||||
authorize! :revert_attribute, @version
|
||||
|
||||
if params[:attribute] && @version.changeset.reject{ |_, values| values[0].blank? && values[1].blank? }.keys.include?(params[:attribute])
|
||||
if @version.item[params[:attribute]] == @version.changeset[params[:attribute]][0]
|
||||
flash[:error] = 'The item is already in the state that you are trying to revert it back to'
|
||||
|
||||
else
|
||||
@version.item[params[:attribute]] = @version.changeset[params[:attribute]][0]
|
||||
if @version.item.save
|
||||
flash[:notice] = 'The selected change was successfully reverted'
|
||||
else
|
||||
flash[:error] = "An error prohibited this change from being reverted: #{@version.item.errors.full_messages.join('. ')}."
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
flash[:error] = 'Revert failed. Attribute missing or invalid'
|
||||
end
|
||||
|
||||
redirect_to admin_revision_history_path
|
||||
end
|
||||
|
||||
def revert_object
|
||||
@version = PaperTrail::Version.find(params[:id])
|
||||
authorize! :revert_object, @version
|
||||
|
||||
if @version.event != 'create'
|
||||
if @version.reify.save
|
||||
flash[:notice] = 'The selected change was successfully reverted'
|
||||
else
|
||||
flash[:error] = "An error prohibited this change from being reverted: #{@version.reify.errors.full_messages.join('. ')}."
|
||||
end
|
||||
|
||||
elsif @version.event == 'create' && @version.item
|
||||
# if @version represets a create event and is not currently deleted
|
||||
@version.item.destroy
|
||||
flash[:notice] = 'The selected change was successfully reverted'
|
||||
|
||||
else
|
||||
flash[:error] = 'The item is already in the state that you are trying to revert it back to'
|
||||
end
|
||||
|
||||
redirect_to admin_revision_history_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -370,4 +370,125 @@ module ApplicationHelper
|
|||
def selected_scheduled?(schedule)
|
||||
(schedule == @selected_schedule) ? 'Yes' : 'No'
|
||||
end
|
||||
|
||||
# Recieves a PaperTrail::Version object
|
||||
# Outputs the list of attributes that were changed in the version (ignoring changes from one blank value to another)
|
||||
# Eg: If version.changeset = '{"title"=>[nil, "Premium"], "description"=>[nil, "Premium = Super cool"], "conference_id"=>[nil, 3]}'
|
||||
# Output will be 'title, description and conference'
|
||||
def updated_attributes(version)
|
||||
version.changeset.
|
||||
reject{ |_, values| values[0].blank? && values[1].blank? }.
|
||||
keys.map{ |key| key.gsub('_id', '').tr('_', ' ')}.join(', ').
|
||||
reverse.sub(',', ' dna ').reverse
|
||||
end
|
||||
|
||||
def change_creator_link(user_id)
|
||||
user = User.find_by(id: user_id)
|
||||
if user
|
||||
link_to user.name, admin_user_path(id: user_id)
|
||||
else
|
||||
'Someone (probably via the console)'
|
||||
end
|
||||
end
|
||||
|
||||
# Recieves a PaperTrail::Version object
|
||||
# Returns object in its current state if its alive
|
||||
# Returns object as it was before version's change(unless its a create event's version)
|
||||
# Else Returns object as it was after version's change
|
||||
def get_version_object(version)
|
||||
version.item || version.reify || version.next.reify
|
||||
end
|
||||
|
||||
def event_change_description(version)
|
||||
case
|
||||
when version.event == 'create' then 'submitted new'
|
||||
|
||||
when version.changeset['state']
|
||||
case version.changeset['state'][1]
|
||||
when 'unconfirmed' then 'accepted'
|
||||
when 'withdrawn' then 'withdrew'
|
||||
when 'canceled', 'rejected', 'confirmed' then version.changeset['state'][1]
|
||||
when 'new' then 'resubmitted'
|
||||
end
|
||||
|
||||
when version.changeset['start_time'] && version.changeset['start_time'][0].nil?
|
||||
'scheduled'
|
||||
|
||||
when version.changeset['start_time'] && version.changeset['start_time'][1].nil?
|
||||
'unscheduled'
|
||||
|
||||
else
|
||||
"updated #{updated_attributes(version)} of"
|
||||
end
|
||||
end
|
||||
|
||||
def users_role_change_description(version)
|
||||
version.event == 'create' ? 'added' : 'removed'
|
||||
end
|
||||
|
||||
def subscription_change_description(version)
|
||||
user = get_version_object(version).user
|
||||
user_name = user.name unless user.id.to_s == version.whodunnit
|
||||
version.event == 'create' ? "subscribed #{user_name} to" : "unsubscribed #{user_name} from"
|
||||
end
|
||||
|
||||
def registration_change_description(version)
|
||||
if version.item_type == 'Registration'
|
||||
user = get_version_object(version).user
|
||||
else
|
||||
registration_id = get_version_object(version).registration_id
|
||||
registration_last_version = PaperTrail::Version.where(item_type: 'Registration', item_id: registration_id).last
|
||||
user = get_version_object(registration_last_version).user
|
||||
end
|
||||
|
||||
if user.id.to_s == version.whodunnit
|
||||
case version.event
|
||||
when 'create' then 'registered to'
|
||||
when 'update' then "updated #{updated_attributes(version)} of the registration for"
|
||||
when 'destroy' then 'unregistered from'
|
||||
end
|
||||
else
|
||||
case version.event
|
||||
when 'create' then "registered #{user.name} to"
|
||||
when 'update' then "updated #{updated_attributes(version)} of #{user.name}'s registration for"
|
||||
when 'destroy' then "unregistered #{user.name} from"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def comment_change_description(version)
|
||||
user = get_version_object(version).user
|
||||
if version.event == 'create'
|
||||
version.previous.nil? ? 'commented on' : "re-added #{user.name}'s comment on"
|
||||
else
|
||||
"deleted #{user.name}'s comment on"
|
||||
end
|
||||
end
|
||||
|
||||
def vote_change_description(version)
|
||||
user = get_version_object(version).user
|
||||
if version.event == 'create'
|
||||
version.previous.nil? ? 'voted on' : "re-added #{user.name}'s vote on"
|
||||
elsif version.event == 'update'
|
||||
"updated #{user.name}'s vote on"
|
||||
else
|
||||
"deleted #{user.name}'s vote on"
|
||||
end
|
||||
end
|
||||
|
||||
def user_change_description(version)
|
||||
if version.event == 'create'
|
||||
change_creator_link(version.item_id) + ' signed up'
|
||||
elsif version.event == 'update'
|
||||
if version.changeset.keys.include?('reset_password_sent_at')
|
||||
'Someone requested password reset of'
|
||||
elsif version.changeset.keys.include?('confirmed_at') && version.changeset['confirmed_at'][0].nil?
|
||||
(version.whodunnit.nil? ? change_creator_link(version.item_id) : change_creator_link(version.whodunnit)) + ' confirmed account of'
|
||||
elsif version.changeset.keys.include?('confirmed_at') && version.changeset['confirmed_at'][1].nil?
|
||||
change_creator_link(version.whodunnit) + ' unconfirmed account of'
|
||||
else
|
||||
change_creator_link(version.whodunnit) + " updated #{updated_attributes(version)} of"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -114,6 +114,14 @@ class Ability
|
|||
# for admins
|
||||
can :manage, :all if user.is_admin
|
||||
|
||||
cannot :revert_object, PaperTrail::Version do |version|
|
||||
(version.event == 'create' && %w(Conference User Event).include?(version.item_type))
|
||||
end
|
||||
|
||||
cannot :revert_attribute, PaperTrail::Version do |version|
|
||||
version.event != 'update' || version.item.nil?
|
||||
end
|
||||
|
||||
cannot :destroy, Program
|
||||
# Do not delete venue, when there are rooms being used
|
||||
cannot :destroy, Venue do |venue|
|
||||
|
|
@ -168,6 +176,10 @@ class Ability
|
|||
can [:edit, :update, :toggle_user], Role do |role|
|
||||
role.resource_type == 'Conference' && (conf_ids_for_organizer.include? role.resource_id)
|
||||
end
|
||||
|
||||
can [:index, :revert_object, :revert_attribute], PaperTrail::Version do |version|
|
||||
version.item_type == 'User' || (conf_ids_for_organizer.include? version.conference_id)
|
||||
end
|
||||
end
|
||||
|
||||
def signed_in_with_cfp_role(user)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ class Campaign < ActiveRecord::Base
|
|||
has_many :targets, dependent: :nullify
|
||||
belongs_to :conference
|
||||
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
##
|
||||
# Returns the utm parameters formatted as url.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# cannot delete program if there are events submitted
|
||||
|
||||
class Cfp < ActiveRecord::Base
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
belongs_to :program
|
||||
|
||||
validates :program_id, presence: true
|
||||
|
|
@ -68,4 +69,8 @@ class Cfp < ActiveRecord::Base
|
|||
errors.
|
||||
add(:start_date, "can't be after the end date") if start_date && end_date && start_date > end_date
|
||||
end
|
||||
|
||||
def conference_id
|
||||
program.conference_id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ class Comment < ActiveRecord::Base
|
|||
# NOTE: Comments belong to a user
|
||||
belongs_to :user
|
||||
|
||||
has_paper_trail on: [:create, :destroy], meta: { conference_id: :conference_id }
|
||||
|
||||
# Helper class method that allows you to build a comment
|
||||
# by passing a commentable object, a user_id, and comment text
|
||||
# example in readme
|
||||
|
|
@ -58,4 +60,8 @@ class Comment < ActiveRecord::Base
|
|||
def send_notification
|
||||
EventCommentMailJob.perform_later(self)
|
||||
end
|
||||
|
||||
def conference_id
|
||||
commentable.program.conference_id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ class Commercial < ActiveRecord::Base
|
|||
|
||||
belongs_to :commercialable, polymorphic: true
|
||||
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
validates :url, presence: true
|
||||
validates :url, format: URI::regexp(%w(http https))
|
||||
|
||||
|
|
@ -41,4 +43,12 @@ class Commercial < ActiveRecord::Base
|
|||
speakerdeck
|
||||
)
|
||||
end
|
||||
|
||||
def conference_id
|
||||
case commercialable_type
|
||||
when 'Conference' then commercialable_id
|
||||
when 'Event' then Event.find(commercialable_id).program.conference_id
|
||||
when 'Venue' then Venue.find(commercialable_id).conference_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class Conference < ActiveRecord::Base
|
|||
|
||||
default_scope { order('start_date DESC') }
|
||||
|
||||
has_paper_trail
|
||||
has_paper_trail ignore: [:updated_at, :guid, :revision, :events_per_week], meta: { conference_id: :id }
|
||||
|
||||
has_and_belongs_to_many :questions
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
class Contact < ActiveRecord::Base
|
||||
has_paper_trail on: [:update], ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
belongs_to :conference
|
||||
|
||||
validates :conference, presence: true
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ class DifficultyLevel < ActiveRecord::Base
|
|||
belongs_to :program
|
||||
has_many :events, dependent: :nullify
|
||||
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
validates :title, presence: true
|
||||
|
||||
validates :color, format: /\A#[0-9A-F]{6}\z/
|
||||
|
||||
before_validation :capitalize_color
|
||||
|
|
@ -12,4 +15,8 @@ class DifficultyLevel < ActiveRecord::Base
|
|||
def capitalize_color
|
||||
self.color = color.upcase if color.present?
|
||||
end
|
||||
|
||||
def conference_id
|
||||
program.conference_id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
class EmailSettings < ActiveRecord::Base
|
||||
belongs_to :conference
|
||||
|
||||
has_paper_trail on: [:update], ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
def get_values(conference, user, event = nil)
|
||||
h = {
|
||||
'email' => user.email,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
class Event < ActiveRecord::Base
|
||||
include ActiveRecord::Transitions
|
||||
has_paper_trail
|
||||
has_paper_trail on: [:create, :update], ignore: [:updated_at, :guid, :week], meta: { conference_id: :conference_id }
|
||||
|
||||
acts_as_commentable
|
||||
|
||||
|
|
@ -280,7 +280,9 @@ class Event < ActiveRecord::Base
|
|||
|
||||
def set_week
|
||||
self.week = created_at.strftime('%W')
|
||||
save!
|
||||
self.without_versioning do
|
||||
self.save!
|
||||
end
|
||||
end
|
||||
|
||||
def before_end_of_conference
|
||||
|
|
@ -288,4 +290,8 @@ class Event < ActiveRecord::Base
|
|||
add(:created_at, "can't be after the conference end date!") if program.conference && program.conference.end_date &&
|
||||
(Date.today > program.conference.end_date)
|
||||
end
|
||||
|
||||
def conference_id
|
||||
program.conference_id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ class EventType < ActiveRecord::Base
|
|||
belongs_to :program
|
||||
has_many :events, dependent: :restrict_with_error
|
||||
|
||||
has_paper_trail meta: { conference_id: :conference_id }
|
||||
|
||||
validates :title, presence: true
|
||||
validates :length, numericality: {greater_than: 0}
|
||||
validates :minimum_abstract_length, presence: true
|
||||
|
|
@ -28,4 +30,8 @@ class EventType < ActiveRecord::Base
|
|||
def capitalize_color
|
||||
self.color = color.upcase if color.present?
|
||||
end
|
||||
|
||||
def conference_id
|
||||
program.conference_id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,9 +4,17 @@ class EventsRegistration < ActiveRecord::Base
|
|||
|
||||
has_one :user, through: :registration
|
||||
|
||||
has_paper_trail meta: { conference_id: :conference_id }
|
||||
|
||||
delegate :name, to: :registration
|
||||
delegate :email, to: :registration
|
||||
|
||||
validates :event, :registration, presence: true
|
||||
validates :event, uniqueness: { scope: :registration }
|
||||
|
||||
private
|
||||
|
||||
def conference_id
|
||||
registration.conference_id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
class Lodging < ActiveRecord::Base
|
||||
belongs_to :conference
|
||||
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
validates :name, presence: true
|
||||
|
||||
mount_uploader :picture, PictureUploader, mount_on: :photo_file_name
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
# cannot delete program if there are events submitted
|
||||
|
||||
class Program < ActiveRecord::Base
|
||||
has_paper_trail on: [:update], ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
belongs_to :conference
|
||||
|
||||
has_one :cfp, dependent: :destroy
|
||||
|
|
@ -53,8 +55,8 @@ class Program < ActiveRecord::Base
|
|||
validate :voting_start_date_before_end_date
|
||||
validate :voting_dates_exist
|
||||
|
||||
before_create :create_event_types
|
||||
before_create :create_difficulty_levels
|
||||
after_create :create_event_types
|
||||
after_create :create_difficulty_levels
|
||||
validate :check_languages_format
|
||||
|
||||
# Returns all event_schedules for the selected schedule ordered by start_time
|
||||
|
|
@ -157,12 +159,12 @@ class Program < ActiveRecord::Base
|
|||
# Creates default EventTypes for this Conference. Used as before_create.
|
||||
#
|
||||
def create_event_types
|
||||
event_types << EventType.create(title: 'Talk', length: 30, color: '#FF0000', description: 'Presentation in lecture format',
|
||||
minimum_abstract_length: 0,
|
||||
maximum_abstract_length: 500)
|
||||
event_types << EventType.create(title: 'Workshop', length: 60, color: '#0000FF', description: 'Interactive hands-on practice',
|
||||
minimum_abstract_length: 0,
|
||||
maximum_abstract_length: 500)
|
||||
EventType.create(title: 'Talk', length: 30, color: '#FF0000', description: 'Presentation in lecture format',
|
||||
minimum_abstract_length: 0,
|
||||
maximum_abstract_length: 500, program_id: self.id)
|
||||
EventType.create(title: 'Workshop', length: 60, color: '#0000FF', description: 'Interactive hands-on practice',
|
||||
minimum_abstract_length: 0,
|
||||
maximum_abstract_length: 500, program_id: self.id)
|
||||
true
|
||||
end
|
||||
|
||||
|
|
@ -170,15 +172,15 @@ class Program < ActiveRecord::Base
|
|||
# Creates default DifficultyLevels for this Conference. Used as before_create.
|
||||
#
|
||||
def create_difficulty_levels
|
||||
difficulty_levels << DifficultyLevel.create(title: 'Easy',
|
||||
description: 'Events are understandable for everyone without knowledge of the topic.',
|
||||
color: '#70EF69')
|
||||
difficulty_levels << DifficultyLevel.create(title: 'Medium',
|
||||
description: 'Events require a basic understanding of the topic.',
|
||||
color: '#EEEF69')
|
||||
difficulty_levels << DifficultyLevel.create(title: 'Hard',
|
||||
description: 'Events require expert knowledge of the topic.',
|
||||
color: '#EF6E69')
|
||||
DifficultyLevel.create(title: 'Easy',
|
||||
description: 'Events are understandable for everyone without knowledge of the topic.',
|
||||
color: '#70EF69', program_id: self.id)
|
||||
DifficultyLevel.create(title: 'Medium',
|
||||
description: 'Events require a basic understanding of the topic.',
|
||||
color: '#EEEF69', program_id: self.id)
|
||||
DifficultyLevel.create(title: 'Hard',
|
||||
description: 'Events require expert knowledge of the topic.',
|
||||
color: '#EF6E69', program_id: self.id)
|
||||
true
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ class Registration < ActiveRecord::Base
|
|||
has_and_belongs_to_many :vchoices
|
||||
|
||||
has_many :events_registrations
|
||||
has_many :events, through: :events_registrations
|
||||
has_many :events, through: :events_registrations, dependent: :destroy
|
||||
|
||||
has_paper_trail ignore: [:updated_at, :week], meta: { conference_id: :conference_id }
|
||||
|
||||
accepts_nested_attributes_for :user
|
||||
accepts_nested_attributes_for :qanswers
|
||||
|
|
@ -75,7 +77,9 @@ class Registration < ActiveRecord::Base
|
|||
|
||||
def set_week
|
||||
self.week = created_at.strftime('%W')
|
||||
save!
|
||||
without_versioning do
|
||||
save!
|
||||
end
|
||||
end
|
||||
|
||||
def registration_limit_not_exceed
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
class RegistrationPeriod < ActiveRecord::Base
|
||||
belongs_to :conference
|
||||
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
validates :start_date, :end_date, presence: true
|
||||
validate :before_end_of_conference
|
||||
validate :start_date_before_end_date
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
class Role < ActiveRecord::Base
|
||||
belongs_to :resource, polymorphic: true
|
||||
has_and_belongs_to_many :users, join_table: :users_roles
|
||||
has_many :users_roles
|
||||
has_many :users, through: :users_roles
|
||||
|
||||
has_paper_trail on: [:update], only: [:name, :description], meta: { conference_id: :resource_id }
|
||||
|
||||
before_destroy :cancel
|
||||
scopify
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ class Room < ActiveRecord::Base
|
|||
belongs_to :venue
|
||||
has_many :event_schedules, dependent: :nullify
|
||||
|
||||
has_paper_trail ignore: [:guid], meta: { conference_id: :conference_id }
|
||||
|
||||
before_create :generate_guid
|
||||
|
||||
validates :name, :venue_id, presence: true
|
||||
|
|
@ -14,4 +16,8 @@ class Room < ActiveRecord::Base
|
|||
guid = SecureRandom.urlsafe_base64
|
||||
self.guid = guid
|
||||
end
|
||||
|
||||
def conference_id
|
||||
venue.conference_id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
class Splashpage < ActiveRecord::Base
|
||||
belongs_to :conference
|
||||
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ class Sponsor < ActiveRecord::Base
|
|||
belongs_to :sponsorship_level
|
||||
belongs_to :conference
|
||||
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
mount_uploader :picture, PictureUploader, mount_on: :logo_file_name
|
||||
|
||||
validates_presence_of :name, :website_url, :sponsorship_level
|
||||
|
|
|
|||
|
|
@ -3,4 +3,6 @@ class SponsorshipLevel < ActiveRecord::Base
|
|||
belongs_to :conference
|
||||
acts_as_list scope: :conference
|
||||
has_many :sponsors
|
||||
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,5 +3,7 @@ class Subscription < ActiveRecord::Base
|
|||
belongs_to :conference
|
||||
belongs_to :user
|
||||
|
||||
has_paper_trail on: [:create, :destroy], ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
validates_uniqueness_of :user_id, scope: :conference_id, message: 'already subscribed!'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ class Target < ActiveRecord::Base
|
|||
|
||||
default_scope { order('due_date ASC') }
|
||||
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
def self.units
|
||||
{
|
||||
registrations: 'Registration',
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ class Ticket < ActiveRecord::Base
|
|||
has_many :ticket_purchases, dependent: :destroy
|
||||
has_many :buyers, -> { distinct }, through: :ticket_purchases, source: :user
|
||||
|
||||
has_paper_trail meta: { conference_id: :conference_id }
|
||||
|
||||
monetize :price_cents, with_model_currency: :price_currency
|
||||
|
||||
# This validation is for the sake of simplicity.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ class Track < ActiveRecord::Base
|
|||
belongs_to :program
|
||||
has_many :events, dependent: :nullify
|
||||
|
||||
has_paper_trail only: [:name, :description, :color], meta: { conference_id: :conference_id }
|
||||
|
||||
before_create :generate_guid
|
||||
validates :name, presence: true
|
||||
validates :color, format: /\A#[0-9A-F]{6}\z/
|
||||
|
|
@ -21,4 +23,8 @@ class Track < ActiveRecord::Base
|
|||
def capitalize_color
|
||||
self.color = color.upcase if color.present?
|
||||
end
|
||||
|
||||
def conference_id
|
||||
program.conference_id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@ end
|
|||
|
||||
class User < ActiveRecord::Base
|
||||
rolify
|
||||
has_many :users_roles
|
||||
has_many :roles, through: :users_roles, dependent: :destroy
|
||||
|
||||
has_paper_trail on: [:create, :update], ignore: [:sign_in_count, :remember_created_at, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip, :last_sign_in_ip, :unconfirmed_email,
|
||||
:avatar_content_type, :avatar_file_size, :avatar_updated_at, :updated_at, :confirmation_sent_at, :confirmation_token, :reset_password_token]
|
||||
|
||||
include Gravtastic
|
||||
gravtastic size: 32
|
||||
|
||||
|
|
@ -72,7 +78,7 @@ class User < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def name
|
||||
self[:name] || username
|
||||
self[:name].blank? ? username : self[:name]
|
||||
end
|
||||
|
||||
##
|
||||
|
|
|
|||
12
app/models/users_role.rb
Normal file
12
app/models/users_role.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
class UsersRole < ActiveRecord::Base
|
||||
belongs_to :role
|
||||
belongs_to :user
|
||||
|
||||
has_paper_trail on: [:create, :destroy], meta: { conference_id: :conference_id }
|
||||
|
||||
private
|
||||
|
||||
def conference_id
|
||||
role.resource_id
|
||||
end
|
||||
end
|
||||
|
|
@ -4,6 +4,8 @@ class Venue < ActiveRecord::Base
|
|||
has_many :rooms, dependent: :destroy
|
||||
before_create :generate_guid
|
||||
|
||||
has_paper_trail ignore: [:updated_at, :guid], meta: { conference_id: :conference_id }
|
||||
|
||||
accepts_nested_attributes_for :commercial, allow_destroy: true
|
||||
validates :name, :street, :city, :country, presence: true
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
class Vote < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
belongs_to :event
|
||||
|
||||
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
|
||||
|
||||
delegate :name, to: :user
|
||||
|
||||
private
|
||||
|
||||
def conference_id
|
||||
event.program.conference_id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
28
app/views/admin/versions/_object_changes.html.haml
Normal file
28
app/views/admin/versions/_object_changes.html.haml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
.col-md-10.col-md-offset-1.changeset{id: "changeset-#{version.id}"}
|
||||
%br
|
||||
%br
|
||||
%table.table.table-bordered.table-hover
|
||||
%thead
|
||||
%tr
|
||||
%th Updated Attribute
|
||||
- if version.event != 'create'
|
||||
%th Previous Value
|
||||
- if version.event != 'destroy'
|
||||
%th New Value
|
||||
- if can? :revert_attribute, version
|
||||
%th Action
|
||||
%tbody
|
||||
- if version.event!= 'destroy'
|
||||
- version.changeset.reject{ |_, values| values[0].blank? && values[1].blank? }.each do |attribute, values|
|
||||
%tr
|
||||
%td= attribute
|
||||
- if version.event != 'create'
|
||||
%td= values[0].blank? ? '-' : values[0]
|
||||
%td= values[1].blank? ? '-' : values[1]
|
||||
- if can? :revert_attribute, version
|
||||
%td= link_to 'Revert', admin_revision_history_revert_attribute_path(id: version.id, attribute: attribute), class: 'btn btn-sm btn-primary', data: { confirm: "Are you sure you want to revert #{attribute}?" }
|
||||
- else
|
||||
- version.reify.attributes.each do |attribute, value|
|
||||
%tr
|
||||
%td= attribute
|
||||
%td= value.blank? ? '-' : value
|
||||
158
app/views/admin/versions/_object_desc_and_link.html.haml
Normal file
158
app/views/admin/versions/_object_desc_and_link.html.haml
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
- if version.item_type == 'UsersRole'
|
||||
- users_role = get_version_object(version)
|
||||
= 'role'
|
||||
= link_to users_role.role.name, admin_conference_role_path(conference_id: Conference.find(version.conference_id).short_title, id: users_role.role.name)
|
||||
= version.event == 'create' ? 'to' : 'from'
|
||||
= 'user'
|
||||
= link_to users_role.user.name, admin_user_path(id: users_role.user.id)
|
||||
|
||||
- elsif version.item_type == 'Subscription' || version.item_type == 'Registration'
|
||||
= 'conference'
|
||||
= link_to Conference.find(version.conference_id).title,
|
||||
admin_conference_registrations_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- elsif version.item_type == 'Commercial'
|
||||
- commercial_last_version = get_version_object(PaperTrail::Version.where(item_type: version.item_type, item_id: version.item_id).last)
|
||||
- commercialable_last_version = get_version_object(PaperTrail::Version.where(item_type: commercial_last_version.commercialable_type,
|
||||
item_id: commercial_last_version.commercialable_id).last)
|
||||
|
||||
- case commercial_last_version.commercialable_type
|
||||
- when 'Event'
|
||||
= link_to 'commercial',
|
||||
edit_admin_conference_program_event_path(conference_id: Conference.find(version.conference_id).short_title,
|
||||
id: commercialable_last_version.id, anchor: 'commercials-content')
|
||||
= "in event #{commercialable_last_version.title}"
|
||||
|
||||
- when 'Venue'
|
||||
- if Venue.find_by(id: commercialable_last_version.id)
|
||||
= link_to 'commercial',
|
||||
edit_admin_conference_program_event_path(conference_id: Conference.find(version.conference_id).short_title,
|
||||
id: commercialable_last_version.id, anchor: 'commercials-content')
|
||||
- else
|
||||
= 'commercial'
|
||||
= "in venue #{commercialable_last_version.name}"
|
||||
|
||||
- when 'Conference'
|
||||
= link_to 'commercial',
|
||||
admin_conference_commercials_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- elsif %w(EventsRegistration Comment Vote).include?(version.item_type)
|
||||
= 'event'
|
||||
- event_id = get_version_object(version).try(:event_id) || get_version_object(version).try(:commentable_id)
|
||||
= link_to Event.find(event_id).title,
|
||||
admin_conference_program_event_path(conference_id: Conference.find(version.conference_id).short_title, id: event_id)
|
||||
|
||||
- elsif version.item_type =='Target'
|
||||
= 'target'
|
||||
- if version.item
|
||||
= link_to Target.find(version.item_id).to_s,
|
||||
admin_conference_targets_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
- else
|
||||
= PaperTrail::Version.where(item_type: 'Target', item_id: version.item_id).last.reify.to_s
|
||||
|
||||
- elsif version.item
|
||||
- case version.item_type
|
||||
- when 'Conference'
|
||||
= 'conference'
|
||||
= link_to Conference.find(version.conference_id).title,
|
||||
edit_admin_conference_path(id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'RegistrationPeriod'
|
||||
= link_to 'registration period',
|
||||
admin_conference_registration_period_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'Contact'
|
||||
= link_to 'contact details',
|
||||
edit_admin_conference_contact_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'Program'
|
||||
= link_to 'program',
|
||||
admin_conference_program_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'Cfp'
|
||||
= link_to 'cfp',
|
||||
admin_conference_program_cfp_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'Track'
|
||||
= 'track'
|
||||
= link_to Track.find(version.item_id).name,
|
||||
admin_conference_program_track_path(conference_id: Conference.find(version.conference_id).short_title, id: version.item_id)
|
||||
|
||||
- when 'Event'
|
||||
= 'event'
|
||||
= link_to Event.find(version.item_id).title,
|
||||
admin_conference_program_event_path(conference_id: Conference.find(version.conference_id).short_title, id: version.item_id)
|
||||
|
||||
- when 'EventType'
|
||||
= 'event type'
|
||||
= link_to EventType.find(version.item_id).title,
|
||||
admin_conference_program_event_types_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'Role'
|
||||
= 'role'
|
||||
= link_to Role.find(version.item_id).name,
|
||||
admin_conference_role_path(conference_id: Conference.find(version.conference_id).short_title, id: version.item.name)
|
||||
|
||||
- when 'Venue'
|
||||
= 'venue'
|
||||
= link_to Venue.find(version.item_id).name,
|
||||
admin_conference_venue_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'Lodging'
|
||||
= 'lodging'
|
||||
= link_to Lodging.find(version.item_id).name,
|
||||
admin_conference_lodgings_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'Room'
|
||||
= 'room'
|
||||
= link_to Room.find(version.item_id).name,
|
||||
admin_conference_venue_rooms_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'Sponsor'
|
||||
= 'sponsor'
|
||||
= link_to Sponsor.find(version.item_id).name,
|
||||
admin_conference_sponsors_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'SponsorshipLevel'
|
||||
= 'sponsorship level'
|
||||
= link_to SponsorshipLevel.find(version.item_id).title,
|
||||
admin_conference_sponsorship_levels_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'Ticket'
|
||||
= 'ticket'
|
||||
= link_to Ticket.find(version.item_id).title,
|
||||
admin_conference_ticket_path(conference_id: Conference.find(version.conference_id).short_title, id: version.item_id)
|
||||
|
||||
- when 'Campaign'
|
||||
= 'campaign'
|
||||
= link_to Campaign.find(version.item_id).name,
|
||||
admin_conference_campaigns_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'DifficultyLevel'
|
||||
= 'difficulty level'
|
||||
= link_to DifficultyLevel.find(version.item_id).title,
|
||||
admin_conference_program_difficulty_level_path(conference_id: Conference.find(version.conference_id).short_title, id: version.item_id)
|
||||
|
||||
- when 'Splashpage'
|
||||
= link_to 'splashpage',
|
||||
admin_conference_splashpage_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'EmailSettings'
|
||||
= link_to 'email settings',
|
||||
admin_conference_emails_path(conference_id: Conference.find(version.conference_id).short_title)
|
||||
|
||||
- when 'User'
|
||||
- if version.event == 'update'
|
||||
= 'user'
|
||||
= link_to User.find(version.item_id).name, admin_user_path(id: version.item_id)
|
||||
|
||||
- else
|
||||
= version.item_type.underscore.tr('_', ' ')
|
||||
/ The last deleted version's name/title is used to describe all the changes in object
|
||||
- last_deleted_version = PaperTrail::Version.where(item_type: version.item_type, item_id: version.item_id).last.reify
|
||||
= last_deleted_version.try(:title) || last_deleted_version.try(:name)
|
||||
|
||||
- unless %w(Conference Subscription Registration User).include?(version.item_type)
|
||||
= "in conference"
|
||||
= link_to Conference.find(version.conference_id).short_title,
|
||||
edit_admin_conference_path(id: Conference.find(version.conference_id).short_title)
|
||||
77
app/views/admin/versions/index.html.haml
Normal file
77
app/views/admin/versions/index.html.haml
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
.row
|
||||
.col-md-12
|
||||
.page-header
|
||||
%h1 Revision History
|
||||
%p.text-muted
|
||||
Log of changes made to conferences and associated resources
|
||||
|
||||
%table.table.table-striped.table-bordered.table-hover#versionstable
|
||||
%thead
|
||||
%td ID
|
||||
%td Description
|
||||
%td Actions
|
||||
%tbody
|
||||
- @versions.each do |version|
|
||||
%tr
|
||||
%td.col-md-1
|
||||
= version.id
|
||||
%td.col-md-9
|
||||
%p
|
||||
= change_creator_link(version.whodunnit) unless version.item_type == 'User'
|
||||
|
||||
- case version.item_type
|
||||
- when 'Event'
|
||||
= event_change_description(version)
|
||||
|
||||
-when 'UsersRole'
|
||||
= users_role_change_description(version)
|
||||
|
||||
- when 'Subscription'
|
||||
= subscription_change_description(version)
|
||||
|
||||
- when 'Registration', 'EventsRegistration'
|
||||
= registration_change_description(version)
|
||||
|
||||
- when 'Comment'
|
||||
= comment_change_description(version)
|
||||
|
||||
- when 'Vote'
|
||||
= vote_change_description(version)
|
||||
|
||||
- when 'User'
|
||||
= user_change_description(version)
|
||||
|
||||
- else
|
||||
- if version.event == 'create'
|
||||
= 'created new'
|
||||
- elsif version.event == 'update'
|
||||
= "updated #{updated_attributes(version)} of"
|
||||
- else
|
||||
= 'deleted'
|
||||
|
||||
= render partial: 'object_desc_and_link', locals: { version: version }
|
||||
|
||||
%small.text-muted
|
||||
= distance_of_time_in_words(Time.now,version.created_at) + ' ago'
|
||||
%br
|
||||
= "(#{version.created_at.strftime('%B %-d, %Y %H:%M')})"
|
||||
|
||||
%br
|
||||
= render partial: 'object_changes', locals: { version: version }
|
||||
|
||||
%td.col-md-2
|
||||
.btn-group{role: 'group'}
|
||||
%a.btn.btn-success.btn-sm.show-changeset{id: version.id} View Changes
|
||||
- if can? :revert_object, version
|
||||
%button.btn.btn-default.dropdown-toggle.btn-sm.btn-primary{'data-toggle' => 'dropdown', type: 'button'}
|
||||
Revert
|
||||
%span.caret
|
||||
%ul.dropdown-menu
|
||||
%li= link_to 'All Changes', admin_revision_history_revert_object_path(id: version.id), data: { confirm: 'Are you sure you want to revert this change?' }
|
||||
|
||||
- if can? :revert_attribute, version
|
||||
%li.divider{role: 'separator'}
|
||||
- version.changeset.reject{ |_, values| values[0].blank? && values[1].blank? }.each do |attribute, values|
|
||||
%li= link_to attribute, admin_revision_history_revert_attribute_path(id: version.id, attribute: attribute), data: { confirm: "Are you sure you want to revert #{attribute}?" }
|
||||
- else
|
||||
%button.btn.btn-sm.btn-primary.disabled Revert
|
||||
|
|
@ -27,3 +27,8 @@
|
|||
= link_to(admin_users_path) do
|
||||
%span.fa.fa-user
|
||||
Users
|
||||
- if can? :index, PaperTrail::Version.new(item_type: 'User')
|
||||
%li
|
||||
= link_to(admin_revision_history_path) do
|
||||
%span.fa.fa-history
|
||||
Revision History
|
||||
|
|
|
|||
|
|
@ -44,3 +44,8 @@
|
|||
= link_to(admin_users_path) do
|
||||
%span.fa.fa-user
|
||||
Users
|
||||
- if can? :index, PaperTrail::Version.new(item_type: 'User')
|
||||
%li
|
||||
= link_to(admin_revision_history_path) do
|
||||
%span.fa.fa-history
|
||||
Revision History
|
||||
|
|
|
|||
|
|
@ -91,6 +91,10 @@ Osem::Application.routes.draw do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
get '/revision_history' => 'versions#index'
|
||||
get '/revision_history/:id/revert_object' => 'versions#revert_object', as: 'revision_history_revert_object'
|
||||
get '/revision_history/:id/revert_attribute' => 'versions#revert_attribute', as: 'revision_history_revert_attribute'
|
||||
end
|
||||
|
||||
resources :conference, only: [:index, :show] do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
class AddConferenceIdToVersions < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :versions, :conference_id, :integer
|
||||
end
|
||||
end
|
||||
5
db/migrate/20160614145614_add_id_to_users_roles.rb
Normal file
5
db/migrate/20160614145614_add_id_to_users_roles.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
class AddIdToUsersRoles < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :users_roles, :id, :primary_key
|
||||
end
|
||||
end
|
||||
|
|
@ -483,7 +483,7 @@ ActiveRecord::Schema.define(version: 20160704092023) do
|
|||
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
||||
add_index "users", ["username"], name: "index_users_on_username", unique: true
|
||||
|
||||
create_table "users_roles", id: false, force: :cascade do |t|
|
||||
create_table "users_roles", force: :cascade do |t|
|
||||
t.integer "role_id"
|
||||
t.integer "user_id"
|
||||
end
|
||||
|
|
@ -529,6 +529,7 @@ ActiveRecord::Schema.define(version: 20160704092023) do
|
|||
t.text "object"
|
||||
t.text "object_changes"
|
||||
t.datetime "created_at"
|
||||
t.integer "conference_id"
|
||||
end
|
||||
|
||||
add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id"
|
||||
|
|
|
|||
101
spec/controllers/admin/versions_controller_spec.rb
Normal file
101
spec/controllers/admin/versions_controller_spec.rb
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Admin::VersionsController do
|
||||
|
||||
let!(:conference) { create(:conference, short_title: 'exampletitle', description: 'Example Description') }
|
||||
let(:admin) { create(:admin) }
|
||||
|
||||
with_versioning do
|
||||
describe 'GET #revert' do
|
||||
before :each do
|
||||
sign_in admin
|
||||
end
|
||||
|
||||
it 'reverts all changes for update actions' do
|
||||
conference.update_attributes(short_title: 'testtitle', description: 'Some random text')
|
||||
get :revert_object, id: PaperTrail::Version.last.id
|
||||
conference.reload
|
||||
expect(conference.short_title).to eq 'exampletitle'
|
||||
expect(conference.description).to eq 'Example Description'
|
||||
end
|
||||
|
||||
it 'shows correct flash on trying to revert create event of a deleted object' do
|
||||
creation_version_id = conference.program.event_types.first.versions.first.id
|
||||
conference.program.event_types.first.destroy
|
||||
get :revert_object, id: creation_version_id
|
||||
expect(flash[:error]).to match('The item is already in the state that you are trying to revert it back to')
|
||||
end
|
||||
|
||||
it 'reverting deletion of object creates it again' do
|
||||
conference.program.event_types.first.destroy
|
||||
event_types_count = conference.program.event_types.count
|
||||
get :revert_object, id: PaperTrail::Version.last.id
|
||||
conference.reload
|
||||
expect(PaperTrail::Version.last.event).to eq 'create'
|
||||
expect(conference.program.event_types.count).to eq(event_types_count + 1)
|
||||
end
|
||||
|
||||
it 'reverting creation of object deletes it ' do
|
||||
create(:lodging, conference: conference)
|
||||
get :revert_object, id: PaperTrail::Version.last.id
|
||||
expect(PaperTrail::Version.last.event).to eq 'destroy'
|
||||
expect(Lodging.count).to eq 0
|
||||
end
|
||||
|
||||
it 'reverting creation of conference is not permitted' do
|
||||
conference_count_before = Conference.count
|
||||
get :revert_object, id: conference.versions.first.id
|
||||
expect(flash[:alert]).to eq 'You are not authorized to access this page.'
|
||||
expect(Conference.count).to eq(conference_count_before)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #revert_attribute' do
|
||||
before :each do
|
||||
sign_in admin
|
||||
end
|
||||
|
||||
it 'reverts specified change for update actions' do
|
||||
conference.update_attributes(short_title: 'testtitle', description: 'Some random text')
|
||||
get :revert_attribute, id: PaperTrail::Version.last.id, attribute: 'short_title'
|
||||
conference.reload
|
||||
expect(conference.short_title).to eq 'exampletitle'
|
||||
expect(conference.description).to eq 'Some random text'
|
||||
end
|
||||
|
||||
it 'shows correct flash on trying to revert to the current state' do
|
||||
conference.update_attributes(short_title: 'testtitle', description: 'Some random text')
|
||||
conference.update_attributes(short_title: 'exampletitle')
|
||||
get :revert_attribute, id: PaperTrail::Version.all[-2].id, attribute: 'short_title'
|
||||
expect(flash[:error]).to match('The item is already in the state that you are trying to revert it back to')
|
||||
expect(conference.short_title).to eq 'exampletitle'
|
||||
end
|
||||
|
||||
it 'fails on trying to revert deleted object' do
|
||||
conference.program.event_types.first.update_attributes(title: 'New Event Title')
|
||||
conference.program.event_types.first.destroy
|
||||
get :revert_attribute, id: PaperTrail::Version.all[-2].id, attribute: 'title'
|
||||
conference.reload
|
||||
expect(flash[:alert]).to eq 'You are not authorized to access this page.'
|
||||
end
|
||||
|
||||
it 'fails on trying to revert creation event' do
|
||||
create(:lodging, conference: conference)
|
||||
get :revert_attribute, id: PaperTrail::Version.last.id, attribute: 'name'
|
||||
expect(flash[:alert]).to eq 'You are not authorized to access this page.'
|
||||
end
|
||||
|
||||
it 'revert fails when attribute is invalid' do
|
||||
conference.update_attributes(short_title: 'testtitle', description: 'Some random text')
|
||||
before_conference_title = conference.title
|
||||
# Note: even though title is a valid attribute of conference, it was not updated in the change we are trying to revert
|
||||
get :revert_attribute, id: PaperTrail::Version.last.id, attribute: 'title'
|
||||
conference.reload
|
||||
expect(conference.short_title).to eq 'testtitle'
|
||||
expect(conference.description).to eq 'Some random text'
|
||||
expect(conference.title).to eq(before_conference_title)
|
||||
expect(flash[:error]).to match('Revert failed. Attribute missing or invalid')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -17,7 +17,6 @@ FactoryGirl.define do
|
|||
|
||||
factory :event_full do
|
||||
difficulty_level
|
||||
track
|
||||
after(:build) do |event|
|
||||
event.commercials << build(:event_commercial, commercialable: event)
|
||||
event.difficulty_level = build(:difficulty_level, program: event.program)
|
||||
|
|
|
|||
|
|
@ -3,5 +3,6 @@ FactoryGirl.define do
|
|||
name { Faker::Commerce.department(2, true) }
|
||||
description { Faker::Lorem.sentence }
|
||||
color { Faker::Color.hex_color }
|
||||
program
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -102,6 +102,9 @@ feature 'Has correct abilities' do
|
|||
|
||||
visit admin_conference_commercials_path(conference1.short_title)
|
||||
expect(current_path).to eq(admin_conference_commercials_path(conference1.short_title))
|
||||
|
||||
visit admin_revision_history_path
|
||||
expect(current_path).to eq(admin_revision_history_path)
|
||||
end
|
||||
|
||||
scenario 'when user is cfp' do
|
||||
|
|
@ -176,6 +179,9 @@ feature 'Has correct abilities' do
|
|||
|
||||
visit admin_conference_commercials_path(conference2.short_title)
|
||||
expect(current_path).to eq(root_path)
|
||||
|
||||
visit admin_revision_history_path
|
||||
expect(current_path).to eq(root_path)
|
||||
end
|
||||
|
||||
scenario 'when user is info desk' do
|
||||
|
|
@ -250,5 +256,8 @@ feature 'Has correct abilities' do
|
|||
|
||||
visit admin_conference_commercials_path(conference3.short_title)
|
||||
expect(current_path).to eq(root_path)
|
||||
|
||||
visit admin_revision_history_path
|
||||
expect(current_path).to eq(root_path)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ ActiveRecord::Migration.maintain_test_schema!
|
|||
require 'capybara/poltergeist'
|
||||
require 'phantomjs'
|
||||
|
||||
# Adds rspec helper provided by paper_trail
|
||||
# makes it easier to control when PaperTrail is enabled during testing.
|
||||
require 'paper_trail/frameworks/rspec'
|
||||
|
||||
# Requires supporting ruby files with custom matchers and macros, etc, in
|
||||
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
|
||||
# run as spec files by default. This means that files in spec/support that end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue