DB: Integridade referencial

master
Alinson S. Xavier 18 years ago
parent e5bc6024ba
commit c58684c31c

@ -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",
:dependent => :destroy
has_many :shoutbox_messages, has_many :events,
:class_name => 'CourseShoutboxMessage', :order => "time asc",
:foreign_key => "receiver_id", :dependent => :destroy
:order => 'id desc'
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 :log_entries,
:order => "created_at desc",
:dependent => :destroy
has_many :events, :order => "time asc" has_many :wiki_pages,
:order => "position",
:dependent => :destroy
has_many :log_entries, :order => "created_at desc" # 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&nbsp;de&nbsp;%B") = n.timestamp.strftime("%d&nbsp;de&nbsp;%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)

@ -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

@ -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

@ -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|

@ -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