DB: Integridade referencial
This commit is contained in:
@@ -34,6 +34,7 @@ class EventsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
@event.time = Time.now
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
|||||||
@@ -25,14 +25,12 @@ class Attachment < ActiveRecord::Base
|
|||||||
self.size = new_file.size
|
self.size = new_file.size
|
||||||
end
|
end
|
||||||
|
|
||||||
# Limpa o nome do arquivo
|
|
||||||
protected
|
protected
|
||||||
def sanitize(filename)
|
def sanitize(filename)
|
||||||
filename = File.basename(filename)
|
filename = File.basename(filename)
|
||||||
filename.gsub(/[^\w\.\-]/, '_')
|
filename.gsub(/[^\w\.\-]/, '_')
|
||||||
end
|
end
|
||||||
|
|
||||||
# Verifica se o arquivo é válido
|
|
||||||
def validate
|
def validate
|
||||||
if @tmp_file
|
if @tmp_file
|
||||||
errors.add("file") if @tmp_file.size == 0
|
errors.add("file") if @tmp_file.size == 0
|
||||||
|
|||||||
@@ -13,23 +13,32 @@
|
|||||||
|
|
||||||
class Course < ActiveRecord::Base
|
class Course < ActiveRecord::Base
|
||||||
|
|
||||||
has_many :attachments, :order => "file_name"
|
# Associacoes
|
||||||
has_many :wiki_pages, :order => "position"
|
has_many :attachments,
|
||||||
|
:order => "file_name",
|
||||||
has_many :shoutbox_messages,
|
:dependent => :destroy
|
||||||
:class_name => 'CourseShoutboxMessage',
|
|
||||||
:foreign_key => "receiver_id",
|
has_many :events,
|
||||||
:order => 'id desc'
|
:order => "time asc",
|
||||||
|
:dependent => :destroy
|
||||||
|
|
||||||
has_many :news,
|
has_many :news,
|
||||||
:class_name => 'News',
|
|
||||||
:foreign_key => "receiver_id",
|
:foreign_key => "receiver_id",
|
||||||
:order => 'id desc'
|
:order => "id desc",
|
||||||
|
:dependent => :destroy
|
||||||
|
|
||||||
has_many :events, :order => "time asc"
|
has_many :log_entries,
|
||||||
|
:order => "created_at desc",
|
||||||
|
:dependent => :destroy
|
||||||
|
|
||||||
has_many :log_entries, :order => "created_at desc"
|
has_many :wiki_pages,
|
||||||
|
:order => "position",
|
||||||
|
:dependent => :destroy
|
||||||
|
|
||||||
|
# Plugins
|
||||||
|
acts_as_paranoid
|
||||||
|
|
||||||
|
# Validacao
|
||||||
generate_validations
|
generate_validations
|
||||||
validates_uniqueness_of :short_name
|
validates_uniqueness_of :short_name
|
||||||
validates_format_of :short_name, :with => /^[^0-9]/
|
validates_format_of :short_name, :with => /^[^0-9]/
|
||||||
@@ -41,15 +50,6 @@ class Course < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_destroy
|
|
||||||
associations = [:attachments, :wiki_pages, :shoutbox_messages, :news, :events]
|
|
||||||
associations.each do |assoc|
|
|
||||||
send("#{assoc}").each do |record|
|
|
||||||
record.destroy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_param
|
def to_param
|
||||||
self.short_name
|
self.short_name
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ class LogEntry < ActiveRecord::Base
|
|||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :course
|
belongs_to :course
|
||||||
|
|
||||||
|
acts_as_paranoid
|
||||||
|
|
||||||
def reversible?() false end
|
def reversible?() false end
|
||||||
|
|
||||||
def to_xml(options = {})
|
def to_xml(options = {})
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ class WikiDeleteLogEntry < WikiLogEntry
|
|||||||
def undo!(current_user)
|
def undo!(current_user)
|
||||||
w = WikiPage.find_with_deleted(target_id)
|
w = WikiPage.find_with_deleted(target_id)
|
||||||
w.update_attribute(:deleted_at, nil)
|
w.update_attribute(:deleted_at, nil)
|
||||||
w.position = w.course.wiki_pages.maximum(:position) + 1
|
w.position = w.course.wiki_pages.maximum(:position) + 1
|
||||||
w.save!
|
w.save!
|
||||||
WikiRestoreLogEntry.create!(:target_id => w.id, :user_id => current_user.id,
|
WikiRestoreLogEntry.create!(:target_id => w.id, :user_id => current_user.id,
|
||||||
:course => w.course)
|
:course => w.course)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -31,10 +31,7 @@ class User < ActiveRecord::Base
|
|||||||
attr_protected :id, :salt
|
attr_protected :id, :salt
|
||||||
attr_accessor :password, :password_confirmation
|
attr_accessor :password, :password_confirmation
|
||||||
|
|
||||||
has_many :shoutbox_messages,
|
acts_as_paranoid
|
||||||
:class_name => 'UserShoutboxMessage',
|
|
||||||
:foreign_key => "receiver_id",
|
|
||||||
:order => 'id desc'
|
|
||||||
|
|
||||||
def User.find_by_login_and_pass(login, pass)
|
def User.find_by_login_and_pass(login, pass)
|
||||||
user = find(:first, :conditions => [ "login = ?", login ])
|
user = find(:first, :conditions => [ "login = ?", login ])
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
%table
|
%table
|
||||||
- @course.news.each do |n|
|
- @course.news.each do |n|
|
||||||
%tr[n]
|
%tr[n]
|
||||||
%td.top.aright
|
%td.top.aright{:width => '1%'}
|
||||||
= n.timestamp.strftime("%d de %B")
|
= n.timestamp.strftime("%d de %B")
|
||||||
%td
|
%td
|
||||||
.title= link_to h(n.title), course_news_url(@course, n)
|
.title= link_to h(n.title), course_news_url(@course, n)
|
||||||
|
|||||||
32
db/migrate/031_create_fks.rb
Normal file
32
db/migrate/031_create_fks.rb
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
class CreateFks < ActiveRecord::Migration
|
||||||
|
def self.add_fk(table, fields, reference, cascade = true)
|
||||||
|
sql = "alter table #{table} add foreign key (#{fields}) references #{reference}"
|
||||||
|
sql = sql + " on update cascade on delete cascade" if cascade
|
||||||
|
execute sql
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.up
|
||||||
|
add_fk :attachments, :course_id, :courses
|
||||||
|
|
||||||
|
add_fk :courses_users, :user_id, :users
|
||||||
|
add_fk :courses_users, :course_id, :courses
|
||||||
|
|
||||||
|
add_fk :events, :created_by, :users
|
||||||
|
add_fk :events, :course_id, :courses
|
||||||
|
|
||||||
|
add_fk :log_entries, :course_id, :courses
|
||||||
|
add_fk :log_entries, :user_id, :users
|
||||||
|
|
||||||
|
add_fk :messages, :sender_id, :users
|
||||||
|
|
||||||
|
add_fk :wiki_pages, :course_id, :courses
|
||||||
|
add_fk :wiki_pages, :user_id, :users
|
||||||
|
|
||||||
|
add_fk :wiki_page_versions, :wiki_page_id, :wiki_pages
|
||||||
|
add_fk :wiki_page_versions, :course_id, :courses
|
||||||
|
add_fk :wiki_page_versions, :user_id, :users
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
end
|
||||||
|
end
|
||||||
13
db/migrate/032_more_paranoid.rb
Normal file
13
db/migrate/032_more_paranoid.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
class MoreParanoid < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
add_column :courses, :deleted_at, :datetime
|
||||||
|
add_column :log_entries, :deleted_at, :datetime
|
||||||
|
add_column :users, :deleted_at, :datetime
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
add_column :courses, :deleted_at
|
||||||
|
add_column :log_entries, :deleted_at
|
||||||
|
add_column :users, :deleted_at
|
||||||
|
end
|
||||||
|
end
|
||||||
17
db/schema.rb
17
db/schema.rb
@@ -9,7 +9,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended to check this file into your version control system.
|
# It's strongly recommended to check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(:version => 30) do
|
ActiveRecord::Schema.define(:version => 32) do
|
||||||
|
|
||||||
create_table "attachments", :force => true do |t|
|
create_table "attachments", :force => true do |t|
|
||||||
t.string "file_name", :null => false
|
t.string "file_name", :null => false
|
||||||
@@ -22,11 +22,12 @@ ActiveRecord::Schema.define(:version => 30) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
create_table "courses", :force => true do |t|
|
create_table "courses", :force => true do |t|
|
||||||
t.string "short_name", :null => false
|
t.string "short_name", :null => false
|
||||||
t.string "full_name", :null => false
|
t.string "full_name", :null => false
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.string "code", :default => "CK000", :null => false
|
t.string "code", :default => "CK000", :null => false
|
||||||
t.integer "period", :default => 1, :null => false
|
t.integer "period", :default => 1, :null => false
|
||||||
|
t.datetime "deleted_at"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "courses", ["short_name"], :name => "index_courses_on_short_name", :unique => true
|
add_index "courses", ["short_name"], :name => "index_courses_on_short_name", :unique => true
|
||||||
@@ -52,6 +53,7 @@ ActiveRecord::Schema.define(:version => 30) do
|
|||||||
t.integer "version"
|
t.integer "version"
|
||||||
t.integer "target_id"
|
t.integer "target_id"
|
||||||
t.string "type"
|
t.string "type"
|
||||||
|
t.datetime "deleted_at"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "messages", :force => true do |t|
|
create_table "messages", :force => true do |t|
|
||||||
@@ -71,8 +73,8 @@ ActiveRecord::Schema.define(:version => 30) do
|
|||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
|
|
||||||
add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
|
add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
|
||||||
|
add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
|
||||||
|
|
||||||
create_table "users", :force => true do |t|
|
create_table "users", :force => true do |t|
|
||||||
t.string "login", :null => false
|
t.string "login", :null => false
|
||||||
@@ -88,6 +90,7 @@ ActiveRecord::Schema.define(:version => 30) do
|
|||||||
t.string "login_key"
|
t.string "login_key"
|
||||||
t.boolean "admin", :default => false, :null => false
|
t.boolean "admin", :default => false, :null => false
|
||||||
t.string "secret", :null => false
|
t.string "secret", :null => false
|
||||||
|
t.datetime "deleted_at"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "wiki_page_versions", :force => true do |t|
|
create_table "wiki_page_versions", :force => true do |t|
|
||||||
|
|||||||
4
test/fixtures/users.yml
vendored
4
test/fixtures/users.yml
vendored
@@ -21,7 +21,7 @@ bob:
|
|||||||
display_name: bob
|
display_name: bob
|
||||||
last_seen: <%= Time.now %>
|
last_seen: <%= Time.now %>
|
||||||
admin: true
|
admin: true
|
||||||
|
secret: bob
|
||||||
|
|
||||||
existingbob:
|
existingbob:
|
||||||
id: 1000002
|
id: 1000002
|
||||||
@@ -33,6 +33,7 @@ existingbob:
|
|||||||
display_name: existingbob
|
display_name: existingbob
|
||||||
last_seen: <%= Time.now %>
|
last_seen: <%= Time.now %>
|
||||||
admin: false
|
admin: false
|
||||||
|
secret: existingbob
|
||||||
|
|
||||||
longbob:
|
longbob:
|
||||||
id: 1000003
|
id: 1000003
|
||||||
@@ -44,3 +45,4 @@ longbob:
|
|||||||
display_name: longbob
|
display_name: longbob
|
||||||
last_seen: <%= Time.now %>
|
last_seen: <%= Time.now %>
|
||||||
admin: false
|
admin: false
|
||||||
|
secret: longbob
|
||||||
|
|||||||
@@ -17,36 +17,8 @@ class CourseTest < Test::Unit::TestCase
|
|||||||
|
|
||||||
fixtures :courses
|
fixtures :courses
|
||||||
|
|
||||||
def test_orphaned_records
|
def test_truth
|
||||||
# Escolhe um curso qualquer
|
assert true
|
||||||
course = courses(:course_1)
|
|
||||||
|
|
||||||
# Cria alguns objetos associados ao curso
|
|
||||||
attachment = Attachment.create(:file_name => 'test', :content_type => 'text/plain',
|
|
||||||
:last_modified => Time.now, :description => 'test', :size => 1.megabyte,
|
|
||||||
:course_id => course.id)
|
|
||||||
|
|
||||||
wiki_page = WikiPage.create(:title => 'teste', :course_id => course.id)
|
|
||||||
|
|
||||||
shoutbox_message = Message.create(:title => 'test', :body => 'test body',
|
|
||||||
:timestamp => Time.now, :type => "CourseShoutboxMessage",
|
|
||||||
:sender_id => 0, :receiver_id => course.id)
|
|
||||||
|
|
||||||
news_message = Message.create(:title => 'test', :body => 'test body',
|
|
||||||
:timestamp => Time.now, :type => "News",
|
|
||||||
:sender_id => 0, :receiver_id => course.id)
|
|
||||||
|
|
||||||
event = Event.create(:title => 'test', :time => Time.now,
|
|
||||||
:created_by => 0, :course_id => course.id, :description => 'test')
|
|
||||||
|
|
||||||
# Deleta o curso
|
|
||||||
course.destroy
|
|
||||||
|
|
||||||
# Ve o que aconteceu com os objetos
|
|
||||||
assert_raises(ActiveRecord::RecordNotFound) { Attachment.find(attachment.id) }
|
|
||||||
assert_raises(ActiveRecord::RecordNotFound) { WikiPage.find(wiki_page.id) }
|
|
||||||
assert_raises(ActiveRecord::RecordNotFound) { CourseShoutboxMessage.find(shoutbox_message.id) }
|
|
||||||
assert_raises(ActiveRecord::RecordNotFound) { News.find(news_message.id) }
|
|
||||||
assert_raises(ActiveRecord::RecordNotFound) { Event.find(event.id) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user