Refactor courses

This commit is contained in:
2015-09-04 13:45:37 -04:00
parent 022620e4ab
commit 6f1427dc21
25 changed files with 339 additions and 361 deletions

View File

@@ -20,64 +20,70 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
class Course < ActiveRecord::Base
acts_as_paranoid
default_scope order('grade asc, full_name asc, period desc')
scope :visible, where(hidden: false)
has_many :attachments,
:order => 'path is not null, path, file_name',
:dependent => :destroy
order: 'path is not null, path, file_name',
dependent: :destroy
has_many :events,
:order => 'time asc',
:dependent => :destroy
order: 'time asc',
dependent: :destroy
has_many :news,
:foreign_key => 'receiver_id',
:order => 'id desc',
:class_name => 'News',
:dependent => :destroy
foreign_key: 'receiver_id',
order: 'id desc',
class_name: 'News',
dependent: :destroy
has_many :log_entries,
:order => 'created_at desc',
:dependent => :destroy
order: 'created_at desc',
dependent: :destroy
has_many :wiki_pages,
:order => 'position',
:dependent => :destroy
order: 'position',
dependent: :destroy
has_and_belongs_to_many :users,
:order => 'last_seen desc'
order: 'last_seen desc'
validates_presence_of :short_name
validates_presence_of :full_name
validates_presence_of :code
validates_numericality_of :grade, :only_integer => true
validates_inclusion_of :hidden, :in => [true, false], :allow_nil => false
validates_format_of :short_name, :with => /^[^0-9]/
validates_numericality_of :grade, only_integer: true
validates_inclusion_of :hidden, in: [true, false], allow_nil: false
validates_format_of :short_name, with: /^[^0-9]/
after_create :add_initial_wiki_pages
def related_courses
Course.all(:conditions => ['short_name = ?', self.short_name], :limit => 4,
:order => 'period desc')
Course.all(conditions: ['short_name = ?', short_name], limit: 4,
order: 'period desc')
end
def recent_news
self.news.all(:conditions => ['timestamp > ?', 7.days.ago])
news.all(conditions: ['timestamp > ?', 7.days.ago])
end
def add_initial_wiki_pages
App.initial_wiki_pages.each do |page_title|
wiki_page = WikiPage.new(:title => page_title, :description => 'New course',
:content => App.initial_wiki_page_content)
wiki_page = WikiPage.new(title: page_title, description: 'New course',
content: App.initial_wiki_page_content)
wiki_page.user = User.first
self.wiki_pages << wiki_page
wiki_pages << wiki_page
wiki_page.save!
end
end
def to_param
return self.short_name if self.period == App.current_period
return self.id.to_s
period == App.current_period ? short_name : id.to_s
end
def self.from_param(param)
param.is_numeric? ? Course.find(param) : Course.find_by_short_name(param)
end
end

View File

@@ -0,0 +1,5 @@
{
"result": {
"covered_percent": 3.57
}
}

View File

View File

@@ -20,21 +20,28 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
class AttachmentLogEntry < LogEntry
belongs_to :attachment,
:foreign_key => "target_id",
:with_deleted => true
belongs_to :attachment,
:foreign_key => "target_id",
:with_deleted => true
end
class AttachmentDeleteLogEntry < AttachmentLogEntry
def reversible?()
attachment.deleted?
end
def undo!(current_user)
attachment.update_attribute(:deleted_at, nil)
AttachmentRestoreLogEntry.create!(:target_id => attachment.id, :user_id => current_user.id, :course => attachment.course)
end
def reversible?()
attachment.deleted?
end
def undo!(current_user)
attachment.update_attribute(:deleted_at, nil)
AttachmentRestoreLogEntry.create!(:target_id => attachment.id,
:user_id => current_user.id, :course => attachment.course)
end
end
class AttachmentEditLogEntry < AttachmentLogEntry; end
class AttachmentCreateLogEntry < AttachmentLogEntry; end
class AttachmentRestoreLogEntry < AttachmentLogEntry; end
class AttachmentEditLogEntry < AttachmentLogEntry
end
class AttachmentCreateLogEntry < AttachmentLogEntry
end
class AttachmentRestoreLogEntry < AttachmentLogEntry
end

View File

@@ -20,21 +20,27 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
class EventLogEntry < LogEntry
belongs_to :event,
:foreign_key => "target_id",
:with_deleted => true
belongs_to :event,
:foreign_key => "target_id",
:with_deleted => true
end
class EventDeleteLogEntry < EventLogEntry
def reversible?()
event.deleted?
end
def undo!(current_user)
event.recover!
EventRestoreLogEntry.create!(:target_id => event.id, :user_id => current_user.id, :course => event.course, :version => event.version)
end
def reversible?()
event.deleted?
end
def undo!(current_user)
event.recover!
EventRestoreLogEntry.create!(:target_id => event.id, :user_id => current_user.id, :course => event.course, :version => event.version)
end
end
class EventEditLogEntry < EventLogEntry; end
class EventCreateLogEntry < EventLogEntry; end
class EventRestoreLogEntry < EventLogEntry; end
class EventEditLogEntry < EventLogEntry
end
class EventCreateLogEntry < EventLogEntry
end
class EventRestoreLogEntry < EventLogEntry
end

View File

@@ -22,100 +22,102 @@
require 'digest/sha1'
class User < ActiveRecord::Base
acts_as_paranoid
# Plugins
acts_as_paranoid
has_and_belongs_to_many :courses, order: 'full_name',
conditions: "period = #{App.current_period}"
# Associacoes
has_and_belongs_to_many :courses, :order => 'full_name', :conditions => "period = #{App.current_period}"
validates_length_of :login, within: 3..40
validates_length_of :name, within: 3..40
validates_length_of :display_name, within: 3..40
# Validacao
validates_length_of :login, :within => 3..40
validates_length_of :name, :within => 3..40
validates_length_of :display_name, :within => 3..40
validates_presence_of :login, :email, :display_name
validates_uniqueness_of :login, :email, :display_name
validates_presence_of :login, :email, :display_name
validates_uniqueness_of :login, :email, :display_name
validates_format_of :login, with: /^[^0-9]/
validates_format_of :display_name, with: /^[^0-9]/
validates_format_of :login, :with => /^[^0-9]/
validates_format_of :display_name, :with => /^[^0-9]/
validates_format_of :email,
with: /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
validates_format_of :email,
:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
attr_protected :id, :salt
attr_accessor :password, :password_confirmation
# Seguranca
attr_protected :id, :salt
attr_accessor :password, :password_confirmation
def self.find_by_login_and_pass(login, pass)
user = find(:first, conditions: ['login = ?', login])
(!user.nil? && User.encrypt(pass, user.salt) == user.hashed_password) ? user : nil
end
def User.find_by_login_and_pass(login, pass)
user = find(:first, :conditions => [ "login = ?", login ])
return (!user.nil? and User.encrypt(pass, user.salt) == user.hashed_password) ? user : nil
end
def to_xml(options = {})
options[:indent] ||= 2
xml = options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
xml.instruct! unless options[:skip_instruct]
xml.user do
xml.id id
xml.name name
xml.display_name display_name
xml.login login
xml.created_at created_at
xml.last_seen last_seen
xml.description description
end
end
def to_xml(options = {})
options[:indent] ||= 2
xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
xml.instruct! unless options[:skip_instruct]
xml.user do
xml.id self.id
xml.name self.name
xml.display_name self.display_name
xml.login self.login
xml.created_at self.created_at
xml.last_seen self.last_seen
xml.description self.description
end
end
# Gera uma nova senha, e a envia por email.
def generate_password_reset_key!
update_attribute(:password_reset_key, User.random_string(30))
save!
Notifications.deliver_forgot_password(email, password_reset_key)
end
# Gera uma nova senha, e a envia por email.
def generate_password_reset_key!
update_attribute(:password_reset_key, User.random_string(30))
save!
Notifications.deliver_forgot_password(self.email, self.password_reset_key)
end
def reset_login_key
self.login_key = Digest::SHA1.hexdigest(Time.now.to_s + password.to_s +
rand(123_456_789).to_s).to_s
end
def reset_login_key
self.login_key = Digest::SHA1.hexdigest(Time.now.to_s + password.to_s + rand(123456789).to_s).to_s
end
def reset_login_key!
reset_login_key
save!
login_key
end
def reset_login_key!
reset_login_key
save!
self.login_key
end
def to_param
login.match(/^[-_a-z0-9]*$/i).nil? ? id.to_s : login
end
def to_param
self.login.match(/^[-_a-z0-9]*$/i).nil? ? self.id.to_s : self.login
end
def courses_not_enrolled(period)
Course.all(conditions: ['period = ? and hidden = ? and id not in (?)',
period, false, courses])
end
protected
def validate
if new_record?
errors.add_on_blank :password
errors.add_on_blank :password_confirmation
end
protected
if !@password.blank?
errors.add(:password_confirmation) if @password_confirmation.blank? or @password != @password_confirmation
errors.add(:password, 'é muito curta') if !(5..40).include?(@password.length)
end
end
def validate
if new_record?
errors.add_on_blank :password
errors.add_on_blank :password_confirmation
end
def before_save
self.salt = User.random_string(10) if !self.salt?
self.secret = User.random_string(32) if !self.secret?
self.hashed_password = User.encrypt(@password, self.salt) if !@password.blank?
end
return unless @password.blank?
errors.add(:password_confirmation) if @password_confirmation.blank? ||
@password != @password_confirmation
errors.add(:password, 'é muito curta') unless @password.length >= 5
end
def self.encrypt(pass, salt)
Digest::SHA1.hexdigest(pass + salt)
end
def before_save
self.salt = User.random_string(10) unless self.salt?
self.secret = User.random_string(32) unless self.secret?
self.hashed_password = User.encrypt(@password, salt) unless @password.blank?
end
def self.random_string(len)
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
newpass = ""
1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
return newpass
end
def self.encrypt(pass, salt)
Digest::SHA1.hexdigest(pass + salt)
end
def self.random_string(len)
chars = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
newpass = ''
1.upto(len) { |_i| newpass << chars[rand(chars.size - 1)] }
newpass
end
end

View File

@@ -22,73 +22,68 @@
require 'acts_as_versioned'
require 'tempfile'
class WikiPage < ActiveRecord::Base
attr_accessible :title, :front_page, :content, :description
attr_writer :type
# Plugins
acts_as_paranoid
acts_as_list :scope => 'course_id = #{course_id}'
acts_as_versioned :if_changed => [:content, :description, :title]
self.non_versioned_columns << 'front_page'
self.non_versioned_columns << 'position'
self.non_versioned_columns << 'deleted_at'
self.non_versioned_columns << 'canonical_title'
acts_as_list scope: 'course_id = #{course_id}'
acts_as_versioned if_changed: [:content, :description, :title]
non_versioned_columns << 'front_page'
non_versioned_columns << 'position'
non_versioned_columns << 'deleted_at'
non_versioned_columns << 'canonical_title'
# Associacoes
belongs_to :course
belongs_to :user, :with_deleted => true
belongs_to :user, with_deleted: true
# Valicacao
validates_presence_of :front_page
validates_presence_of :description
validates_presence_of :title
validates_presence_of :content
validates_uniqueness_of :title, :scope => :course_id
validates_uniqueness_of :canonical_title, :scope => :course_id
validates_format_of :title, :with => /^[^0-9]/
validates_uniqueness_of :title, scope: :course_id
validates_uniqueness_of :canonical_title, scope: :course_id
validates_format_of :title, with: /^[^0-9]/
before_validation :set_canonical_title
before_save :set_position
# acts_as_paranoid_versioned
self.versioned_class.class_eval do
def self.delete_all(conditions = nil)
return
versioned_class.class_eval do
def self.delete_all(_conditions = nil)
nil
end
end
def set_canonical_title
self.canonical_title = self.title.pretty_url
canonical_title = title.pretty_url
end
def set_position
if !self.front_page
self.remove_from_list
elsif self.position.nil?
self.update_attribute(:position, (self.course.wiki_pages.maximum(:position)||0) + 1)
if !front_page
remove_from_list
elsif position.nil?
update_attribute(:position, (course.wiki_pages.maximum(:position) || 0) + 1)
end
end
def validate
begin
self.content.format_wiki
rescue
errors.add("content", "possui erro de sintaxe: " + $!.to_s.html_escape)
end
content.format_wiki
rescue
errors.add("content", "possui erro de sintaxe: " + $ERROR_INFO.to_s.html_escape)
end
def to_param
self.canonical_title
canonical_title
end
def self.find_front_page
WikiPage.all(:conditions => ["front_page = ?", true])
WikiPage.all(conditions: ["front_page = ?", true])
end
def WikiPage.diff(from, to)
def self.diff(from, to)
# Cria um arquivo com o conteudo da versao antiga
original_content_file = Tempfile.new("old")
original_content_file << from.content << "\n"
@@ -100,12 +95,12 @@ class WikiPage < ActiveRecord::Base
new_content_file.flush
# Calcula as diferencas
diff = `diff -u #{original_content_file.path()} #{new_content_file.path()}`
diff = `diff -u #{original_content_file.path} #{new_content_file.path}`
# Fecha os arquivos temporarios
new_content_file.close!
original_content_file.close!
return diff
diff
end
end