Updated haml and acts_as_paranoid. Removed sass templates.

This commit is contained in:
benni 2011-05-15 21:50:43 +02:00
parent 79f8836da0
commit a4f71bd672
27 changed files with 8 additions and 1935 deletions

View file

@ -6,10 +6,11 @@ gem "rails", '3.0.7'
gem 'mysql'
gem "fastercsv"
gem "prawn", '<=0.6.3'
gem 'haml', '>=2.0.6'
gem 'haml'
gem "will_paginate", "~> 3.0.pre2"
gem 'jquery-rails'
gem 'simple_form'
gem 'rails3_acts_as_paranoid'
group :development do
gem 'annotate'

View file

@ -35,7 +35,7 @@ GEM
abstract (>= 1.0.0)
exception_notification (2.4.0)
fastercsv (1.5.4)
haml (3.0.25)
haml (3.1.1)
hirb (0.3.4)
i18n (0.5.0)
jquery-rails (1.0.1)
@ -72,6 +72,8 @@ GEM
activesupport (= 3.0.7)
bundler (~> 1.0)
railties (= 3.0.7)
rails3_acts_as_paranoid (0.0.7)
activerecord (>= 3.0)
railties (3.0.7)
actionpack (= 3.0.7)
activesupport (= 3.0.7)
@ -92,11 +94,12 @@ DEPENDENCIES
annotate
exception_notification
fastercsv
haml (>= 2.0.6)
haml
hirb
jquery-rails
mysql
prawn (<= 0.6.3)
rails (= 3.0.7)
rails3_acts_as_paranoid
simple_form
will_paginate (~> 3.0.pre2)

View file

@ -1,9 +0,0 @@
#nav
text-align: left
ul
margin: 0
li.current
a:hover
color: #fff
ul
width: 100%

View file

@ -1,656 +0,0 @@
// colors which are used in the foodsoft
!main_red = #ED0606
!hover_yellow = #ffff72
!boxContent = #e4eed6
!lightGrey = #efefef
!darkGreen = #78b74e
!lightGreen = #e4eed6
/* General rules ...
body
:background-color #fff
:color black
:margin 0
:padding 1% 0 0 0
:min-width 990px
:font-size 62.5%
:font-family verdana, arial, sans-serif
#loader
:position fixed
:top 1px
:right 1px
:background #FFF
:padding 10px
:color black
:border
:width 2px
:style solid
:color = !main_red
a, a:visited
:text-decoration underline
:color black
a:hover
:color = !main_red
h1, h2
:color = !main_red
h1
:font-size 2.2em
:line-height 0.8em
:padding 1em 0 5px 5%
:margin 0 0 1em 0
:border-bottom
:width 1px
:style dotted
:color = !main_red
h2
:font-size 1.4em
:margin-top .5em
h3
:font-size 1em
:margin-top 1.5em
input
:color #2e2e2e
abbr, acronym
:cursor help
input, textarea, select
border: 1px solid #D7D7D7
font-family: verdana, arial, helvetica, sans-serif
font-size: 0.9em
padding-left: .2em
padding-right: .2em
input:focus, textarea:focus, select:focus
border-color: #000
input[type="button"], input[type="submit"], input[type="reset"]
background: #EEEEEE none repeat scroll 0%
border: 1px outset #CCCCCC
color: #222222
padding: 0.1em 0.5em
font-size: 1em
font-weight: bold
min-width: 34px
select
max-width: 15em
option
border-top: 1px solid #D7D7D7
margin: .2em 0
span.click-me
cursor: pointer
.left
float: left
.right
float: right
.clear
clear: both
.description
color: grey
font-size: 0.9em
.hidden
display: none
// ********************************* loginpage
#login
:margin auto
:width 27em
:font-size 1.2em
#login #meta
:margin-top 2em
:padding-top .3em
:border-top 1px dotted #ED0606
:color #2e2e2e
// ******************************** - Logo - head
#header
:margin 0
:padding 0
#logo
:background = !main_red
:height 1.1em
:width 8em
:padding 0 20px
:text-align left
:line-height 54px
:font-size 54px
:overflow hidden
:letter-spacing -3px
:margin 0
a, a:hover
:color white
:background-color = !main_red
:text-decoration none
a span
:color = !main_red
:background #FFF
:padding-right 0.1em
:font-weight bold
:border-top
:width 2px
:style dotted
:color = !main_red
#logininfo
:position absolute
:top 3px
:right 10px
:font-size 1em
ul
:list-style none
li
:margin 0 0 0 5px
:float left
a
:color #737272
:font-weight bold
a:hover
:color = !main_red
// ************************************* box structure
#main
:background #FFF
:padding 0
:margin 0 15px 0 15px
// ************************************* infobar
#infobar
:width 10%
:min-width 5em
:float right
:padding 2.6em 1em
:margin 3em 0 0 0
:border-left 1px dotted #ED0606
:font-size 1.2em
h3
:color #ED0606
ul
:list-style none
li
:margin .3em 0 0 -3em
// ************************************ embedded menu
.menu, #start_nav
:border 2px solid #e3e3e3
:background #f5f5f5
:padding 0 10px 0px 5px
:float left
ul
:list-style-type none
:margin 0 0 0.2em 0
:padding 0
li
:border-bottom 1px solid #dedede
:color #666
:margin 0.8em 0 0 0
:font-weight bold
a:link, a:visited
:display block
:padding 0.25em 1em
:text-decoration none
:width 12em
a:hover, a:focus
:background-color #e3e3e3
ul
:margin 0
:padding 0
li
:border-top 1px solid #dedede
:border-bottom none
:margin 0
:font-weight normal
a:link, a:visited
:width 11.5em
:padding 0 1em 0.1em 1.5em
:font-weight normal
:text-decoration none
.menu
:position absolute
:top 100px
:right 1px
// ************************************** content
#content
:padding .5em 0 2.5em 0
:margin 0
:background #FFF
:font-size 1.3em
:width 100%
:float left
/************************************ tables
table
:border-collapse collapse
// border2px solid #e3e3e3
:text-align left
:width 100%
:margin 0
thead th, tbody td, th, td
:padding 0.3em
thead tr
:background-color #efefef
th
:color black
tr.odd, tr.even
:border-top 1px solid #DDDDDD
tr.odd, tr.odd input
:background-color #F6F6F6
tr.even
:background-color #FBFBFB
tr.unavailable, tr.unavailable a
:color grey
tr.unavailable a:hover
:color #ED0606
tr.just_updated
:color #008000
tr.selected, tr.active
:background-color #ffffc2
tr.click-me
:cursor pointer
tr.ignored
color: grey
tr.success
color: green
tr.failed
color: red
table.list
//:border 2px solid #78b74e
tr
:border 1px solid #e3e3e3
tbody tr:hover
:background-color #EEEEDD
table tfoot tr
:background-color #fff
td
:padding-top 0.8em
tr.edit_inline
:background-color = !hover_yellow
td, span
:padding 0.5em 0.2em
div.legend, div.legend table th
:color grey
:font-size .8em
:background none
form table
:border none
table.ordered_articles
:background-color #fff
tbody tr:hover
:background-color #EEEEDD
a
:display block
tr.results:hover
:background-color none
table
tfoot
:font-weight bold
td.currency, td.actions
:text-align right
:padding-right 0.5em
td.closed
background: url(/images/arrow_right_red.png) no-repeat center left
a
display: block
text-decoration: none
padding-left: 20px
td.open
background: url(/images/arrow_down_red.png) no-repeat center left
// ************************************* for edit formulars */
div.edit_form
:border 2px solid #e3e3e3
:background #f5f5f5
:padding 0 0.8em 0.8em 0.8em
:margin 5px 0
:color black
#edit_article, #edit_box, #ajax_box
:position fixed
:top 5em
:left 10em
:width 55em
:background #FBFBFB
:padding 3em
:padding-top 1em
:border
:width 3px
:style solid
:color = !main_red
// ***************************************** other boxes */
// *********boxes in columns ****/
div.box
:border-left 2px solid #78b74e
:padding-left 5px
div.single_column
:width 100%
div.left_column
:width 40%
:float left
div.middle_column
:width 40%
:margin-left 10px
:float left
div.right_column
:margin-bottom 3em
:width 55%
:float right
// *********** content of boxes ******/
div.box_title
:background #78b74e
:padding 5px 10px
h2, h2 a
:color #FFF
:margin 0
h2
:font-size 1.3em
div.column_content
:background = !boxContent
:color black
:padding 10px
margin-bottom: 2em
h2
:color black
:font-size 1.3em
:margin 1em 0 0 0
#links
:float right
// for special pages
// index-page
// * article show
tr.current_price
:background #cdee9e
// **** maybe later for the very little spinner
li.check div.spinner
:display block
:height 5px
:width 21px
:background-image url(/images/dots-white.gif)
:line-height 16px
:float left
:margin-right 5px
:background-position center center
:background-repeat no-repeat
// ************************************* the order page */
span.used, span.unused
:font-weight bold
span.used
:color #008000
span.unused
:color #ed0606
span.total
:font-size 80%
table#order
:text-align center
input
font-size: 0.9em
font-weight: bolder
background-color: #78B74E
color: #fff
-moz-border-radius: 3px
-webkit-border-radius: 3px
padding: 0
th#col_required, th#col_tolerance
:width 140px
th#col_packages, th#col_left_units
:width 50px
td.quantity, td.tolerance
text-align: right
td#col_left_units
:color #ed0606
td
:padding 0.6em
td.name
:text-align left
:padding-left 10px
tfoot
tr
:background-color = !lightGreen
td
:padding-right 10px
#order-footer, .article-info
text-align: left
z-index: 1
position: fixed
bottom: 0
background-color: #E4EED6
border-top: 2px solid #78B74E
//opacity: 0.95
#total-sum
width: 22em
margin: .5em 2em 0 0
float: right
#order-button
margin: .5em 0
input
background-color: #78B74E
color: #fff
-moz-border-radius: 3px
-webkit-border-radius: 3px
input:disabled
background-color: red
#order-footer
width: 100%
right: 0
left: 0
.article-info
z-index: 2
width: 45em
height: 8em
border: none
left: 30px
h3
text-align: center
margin: 0
margin-bottom: 5px
width: 100%
.right
width: 35%
.left
width: 60%
tr.order-article .article-info
display: none
tr.order-article:hover .article-info
display: block
// ********* Comments
#newComment
:margin 1em
.comment
:border-bottom 1px dotted black
:padding .5em 0 1em .5em
.timestamp
:font-size 0.8em
:color grey
// *************** Clearing Order Page ..
#editOrderNav
a
:color #fff
:font-weight bold
ul
:margin 0
:padding 0
li
:display inline
:list-style none
:margin-right 1em
// *************** Tasks ...
.accepted
color: green
font-weight: bold
.done, .done a, .done .accepted
color: grey
font-weight: normal
// ************** auto_complete
ul.autocomplete
.nick, .informal
margin: auto
.nick
font-weight: bold
.informal
color: grey
margin-left: 1em
// ******* to navigate easy to the next element, e.g. next order
#element_navigation
position: relative
top: -1em
left: 5%
// group stats
.stats-bar
height: 20px
min-width: 10px
border: 1px solid #DDDDDD
background-color: #fff
text-align: center
margin: 0 10px 10px 0
// *** wiki
#wiki_content
border-style: none
color: black
line-height: 1.5em
.wiki_show, .wiki_version, .wiki_new, .wiki_edit, .wiki_all
margin-top: 30px
padding: 10px
h1
padding-left: 0
padding-top: 10px
border-bottom:
:style solid
.column_content
margin-bottom: 0
#wiki_content
min-height: 400px
span.editsection
display: none
h2, h3, h4, h5, h6
background: transparent none repeat scroll 0 0
border-bottom: 1px solid #AAAAAA
padding-bottom: 0,17em
padding-top: 0,5em
font-weight: normal
font-size: 150%
color: black
h3, h4, h5, h6
border-bottom: medium none
font-weight: bold
h3
font-size: 132%
h4
font-size: 116%
ul
line-height: 1.5em
margin: 0.3em 0 0 1.5em
padding: 0
ol
line-height: 1.5em
margin: 0.3em 0 0 3.2em
padding: 0
list-style-image: none
li margin-bottom: 0.1em
a.new_wiki_link
color: grey
#preview
border: 1px dotted grey
padding: 0 1em
#wikitoc
padding: 5px
margin-bottom: 2em
width: 25em
border: 1px solid grey
:background-color= !lightGrey
h2
font-size: 1em
color: black
span a
font-size: 0.5em
color: grey
#breadcrump
font-size: 0.5em
margin-bottom: 5px
height: 1em
color: #ED0606
a
:color = !main_red
:text-decoration = none
a:hover
:text-decoration = underline
#sidebar
float: right
width: 290px
margin-top: -60px
#sidebar-links
margin-bottom: 18px
text-align: right
#subpages
border: 1px solid #78b74e
margin-top: 10px
padding: 0 0 0 0
#versions
margin-top: 10px
border: 1px solid #78b74e
#wiki-syntax-help
float: right
table
border-color: #78b74e
.wiki_version
#sidebar
margin-top: -23px
border: 1px solid #78b74e

View file

@ -1,63 +0,0 @@
/* Navigation ....
#nav
:position relative
:height 3em
:text-align right
:margin-top 5px
ul
:padding 0 0 0 0
:margin -2.3em 0 0 0
:list-style none
li
:display inline
:list-style none
:padding 0.3em 0 0.3em 0
:margin 0 0 0 0.2em
:background none
:vertical-align middle
a
:margin 0.1em 0 0 0
:text-align center
:font-size 1.1em
:font-weight bold
:text-decoration none
:color #737272
:border none
:background #e3e3e3
:padding 0.5em 1.2em 0.6em 1.2em
:margin-top 0
a:hover
:color #ED0606
// second row of nav
ul
:display none
:position absolute
:margin 0
:left 0
:padding 0.6em
:bottom -1.4em
:right 0em
:background #ED0606
li
:border-left 0.1em dotted white
:background none
a, a:hover
:border none
:background none
:color #FFF
:font-style normal
:font-size 1em
//current list-element
li.current
a
:border none
:border-bottom none
:background #ED0606
:padding-bottom 0.6em
:color #FFF
ul
:display inline
a
:background none

View file

@ -1,6 +0,0 @@
@import main.sass
#logininfo, #header, #footer
:display none
h1, h2
:color black
:border-color black

View file

@ -1,68 +0,0 @@
/* rails messages ....
!main_red = #ED0606
h3.notice, div.notice
:color #090
h3.notice
:background #dfd url(/images/icon_message.gif) no-repeat 10px 3px
:border 1px solid #bfb
:padding 4px 40px
:margin 2em 0 1em 0
:font-size 100%
:position relative
h3.error, div.error
:color red
:font-size 100%
font-weight: bold
h3.error
:background yellow url(/images/error.png) no-repeat 10px 3px
:border 1px solid red
:padding 4px 40px
:position relative
:margin 2em 0 1em 0
font-weight: normal
.fieldWithErrors
:padding 2px
:background-color red
:display table
.fieldWithErrors input
:background-color yellow
#errorExplanation
:width 40em
:padding 7px
:padding-bottom 12px
:color = !main_red
h2
:color = !main_red
:text-align left
:font-weight bold
:margin 0
:padding 5px 5px 5px 5px
:font-size 15px
p
:margin 0
:padding 5px
ul, li
:margin 0
li
:padding 0
:font-size 12px
:list-style square
div.uploadStatus
:margin 5px
div.progressBar
:margin 5px
div.border
:background-color #fff
:border 1px solid grey
:width 100%
div.background
:background-color #333
:height 18px
:width 0%

View file

@ -1,74 +0,0 @@
* (4 Oct 2007)
Update for Edge rails: remove support for legacy #count args
* (2 Feb 2007)
Add support for custom primary keys [Jeff Dean]
* (2 July 2006)
Add paranoid delete_all implementation [Marshall Roch]
* (23 May 2006)
Allow setting of future dates for content expiration.
* (15 May 2006)
Added support for dynamic finders
* (28 Mar 2006)
Updated for Rails 1.1. I love removing code.
Refactored #find method
Nested Scopes
*0.3.1* (20 Dec 2005)
* took out deleted association code for 'chainsaw butchery of base classes' [sorry Erik Terpstra]
* verified tests pass on Rails 1.0
*0.3* (27 Nov 2005)
* Deleted models will find deleted associations by default now [Erik Terpstra]
* Added :group as valid option for find [Michael Dabney]
* Changed the module namespace to Caboose::Acts::Paranoid
*0.2.0* (6 Nov 2005)
* Upgrade to Rails 1.0 RC4. ActiveRecord::Base#constrain has been replaced with scope_with.
*0.1.7* (22 Oct 2005)
* Added :with_deleted as a valid option of ActiveRecord::Base#find
*0.1.6* (25 Sep 2005)
* Fixed bug where nested constrains would get clobbered after multiple queries
*0.1.5* (22 Sep 2005)
* Fixed bug where acts_as_paranoid would clobber other constrains
* Simplified acts_as_paranoid mixin including.
*0.1.4* (18 Sep 2005)
* First RubyForge release
*0.1.3* (18 Sep 2005)
* ignore multiple calls to acts_as_paranoid on the same model
*0.1.2* (18 Sep 2005)
* fixed a bug that kept you from selecting the first deleted record
*0.1.1* (18 Sep 2005)
* Fixed bug that kept you from selecting deleted records by ID
*0.1* (17 Sep 2005)
* Initial gem

View file

@ -1,20 +0,0 @@
Copyright (c) 2005 Rick Olson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,26 +0,0 @@
= acts_as_paranoid
Overrides some basic methods for the current model so that calling #destroy sets a 'deleted_at' field to the
current timestamp. ActiveRecord is required.
== Resources
Install
* gem install acts_as_paranoid
Rubyforge project
* http://rubyforge.org/projects/ar-paranoid
RDocs
* http://ar-paranoid.rubyforge.org
Subversion
* http://techno-weenie.net/svn/projects/acts_as_paranoid
Collaboa
* http://collaboa.techno-weenie.net/repository/browse/acts_as_paranoid

View file

@ -1,41 +0,0 @@
== Creating the test database
The default name for the test databases is "activerecord_paranoid". If you
want to use another database name then be sure to update the connection
adapter setups you want to test with in test/connections/<your database>/connection.rb.
When you have the database online, you can import the fixture tables with
the test/fixtures/db_definitions/*.sql files.
Make sure that you create database objects with the same user that you specified in i
connection.rb otherwise (on Postgres, at least) tests for default values will fail.
== Running with Rake
The easiest way to run the unit tests is through Rake. The default task runs
the entire test suite for all the adapters. You can also run the suite on just
one adapter by using the tasks test_mysql_ruby, test_ruby_mysql, test_sqlite,
or test_postresql. For more information, checkout the full array of rake tasks with "rake -T"
Rake can be found at http://rake.rubyforge.org
== Running by hand
Unit tests are located in test directory. If you only want to run a single test suite,
or don't want to bother with Rake, you can do so with something like:
cd test; ruby -I "connections/native_mysql" base_test.rb
That'll run the base suite using the MySQL-Ruby adapter. Change the adapter
and test suite name as needed.
== Faster tests
If you are using a database that supports transactions, you can set the
"AR_TX_FIXTURES" environment variable to "yes" to use transactional fixtures.
This gives a very large speed boost. With rake:
rake AR_TX_FIXTURES=yes
Or, by hand:
AR_TX_FIXTURES=yes ruby -I connections/native_sqlite3 base_test.rb

View file

@ -1,180 +0,0 @@
require 'rubygems'
Gem::manage_gems
require 'rake/rdoctask'
require 'rake/packagetask'
require 'rake/gempackagetask'
require 'rake/testtask'
require 'rake/contrib/rubyforgepublisher'
PKG_NAME = 'acts_as_paranoid'
PKG_VERSION = '0.3.1'
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
PROD_HOST = "technoweenie@bidwell.textdrive.com"
RUBY_FORGE_PROJECT = 'ar-paranoid'
RUBY_FORGE_USER = 'technoweenie'
desc 'Default: run unit tests.'
task :default => :test
desc 'Test the calculations plugin.'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end
desc 'Generate documentation for the acts_as_paranoid plugin.'
Rake::RDocTask.new do |rdoc|
rdoc.rdoc_dir = 'html'
rdoc.title = "#{PKG_NAME} -- protect your ActiveRecord objects from accidental deletion"
rdoc.options << '--line-numbers --inline-source --accessor cattr_accessor=object'
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
rdoc.rdoc_files.include('README', 'CHANGELOG', 'RUNNING_UNIT_TESTS')
rdoc.rdoc_files.include('lib/**/*.rb')
end
spec = Gem::Specification.new do |s|
s.name = PKG_NAME
s.version = PKG_VERSION
s.platform = Gem::Platform::RUBY
s.summary = "acts_as_paranoid keeps models from actually being deleted by setting a deleted_at field."
s.files = FileList["{lib,test}/**/*"].to_a + %w(README MIT-LICENSE CHANGELOG RUNNING_UNIT_TESTS)
s.files.delete "acts_as_paranoid_plugin.sqlite.db"
s.files.delete "acts_as_paranoid_plugin.sqlite3.db"
s.require_path = 'lib'
s.autorequire = 'acts_as_paranoid'
s.has_rdoc = true
s.test_files = Dir['test/**/*_test.rb']
s.author = "Rick Olson"
s.email = "technoweenie@gmail.com"
s.homepage = "http://techno-weenie.net"
end
Rake::GemPackageTask.new(spec) do |pkg|
pkg.need_tar = true
end
desc "Publish the API documentation"
task :pdoc => [:rdoc] do
Rake::RubyForgePublisher.new(RUBY_FORGE_PROJECT, RUBY_FORGE_USER).upload
end
desc 'Publish the gem and API docs'
task :publish => [:pdoc, :rubyforge_upload]
desc "Publish the release files to RubyForge."
task :rubyforge_upload => :package do
files = %w(gem tgz).map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
if RUBY_FORGE_PROJECT then
require 'net/http'
require 'open-uri'
project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
project_data = open(project_uri) { |data| data.read }
group_id = project_data[/[?&]group_id=(\d+)/, 1]
raise "Couldn't get group id" unless group_id
# This echos password to shell which is a bit sucky
if ENV["RUBY_FORGE_PASSWORD"]
password = ENV["RUBY_FORGE_PASSWORD"]
else
print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
password = STDIN.gets.chomp
end
login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
data = [
"login=1",
"form_loginname=#{RUBY_FORGE_USER}",
"form_pw=#{password}"
].join("&")
http.post("/account/login.php", data)
end
cookie = login_response["set-cookie"]
raise "Login failed" unless cookie
headers = { "Cookie" => cookie }
release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
release_data = open(release_uri, headers) { |data| data.read }
package_id = release_data[/[?&]package_id=(\d+)/, 1]
raise "Couldn't get package id" unless package_id
first_file = true
release_id = ""
files.each do |filename|
basename = File.basename(filename)
file_ext = File.extname(filename)
file_data = File.open(filename, "rb") { |file| file.read }
puts "Releasing #{basename}..."
release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
release_date = Time.now.strftime("%Y-%m-%d %H:%M")
type_map = {
".zip" => "3000",
".tgz" => "3110",
".gz" => "3110",
".gem" => "1400"
}; type_map.default = "9999"
type = type_map[file_ext]
boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
query_hash = if first_file then
{
"group_id" => group_id,
"package_id" => package_id,
"release_name" => PKG_FILE_NAME,
"release_date" => release_date,
"type_id" => type,
"processor_id" => "8000", # Any
"release_notes" => "",
"release_changes" => "",
"preformatted" => "1",
"submit" => "1"
}
else
{
"group_id" => group_id,
"release_id" => release_id,
"package_id" => package_id,
"step2" => "1",
"type_id" => type,
"processor_id" => "8000", # Any
"submit" => "Add This File"
}
end
query = "?" + query_hash.map do |(name, value)|
[name, URI.encode(value)].join("=")
end.join("&")
data = [
"--" + boundary,
"Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
"Content-Type: application/octet-stream",
"Content-Transfer-Encoding: binary",
"", file_data, ""
].join("\x0D\x0A")
release_headers = headers.merge(
"Content-Type" => "multipart/form-data; boundary=#{boundary}"
)
target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
http.post(target + query, data, release_headers)
end
if first_file then
release_id = release_response.body[/release_id=(\d+)/, 1]
raise("Couldn't get release id") unless release_id
end
first_file = false
end
end
end

View file

@ -1,34 +0,0 @@
#class << ActiveRecord::Base
# def belongs_to_with_deleted(association_id, options = {})
# with_deleted = options.delete :with_deleted
# returning belongs_to_without_deleted(association_id, options) do
# if with_deleted
# reflection = reflect_on_association(association_id)
# association_accessor_methods(reflection, Caboose::Acts::BelongsToWithDeletedAssociation)
# association_constructor_method(:build, reflection, Caboose::Acts::BelongsToWithDeletedAssociation)
# association_constructor_method(:create, reflection, Caboose::Acts::BelongsToWithDeletedAssociation)
# end
# end
# end
#
# def has_many_without_deleted(association_id, options = {}, &extension)
# with_deleted = options.delete :with_deleted
# returning has_many_with_deleted(association_id, options, &extension) do
# if options[:through] && !with_deleted
# reflection = reflect_on_association(association_id)
# collection_reader_method(reflection, Caboose::Acts::HasManyThroughWithoutDeletedAssociation)
# collection_accessor_methods(reflection, Caboose::Acts::HasManyThroughWithoutDeletedAssociation, false)
# end
# end
# end
#
# alias_method_chain :belongs_to, :deleted
# alias_method :has_many_with_deleted, :has_many
# alias_method :has_many, :has_many_without_deleted
# alias_method :exists_with_deleted?, :exists?
#end
ActiveRecord::Base.send :include, Caboose::Acts::Paranoid
#ActiveRecord::Base.send :include, Caboose::Acts::ParanoidFindWrapper
#class << ActiveRecord::Base
# alias_method_chain :acts_as_paranoid, :find_wrapper
#end

View file

@ -1,14 +0,0 @@
module Caboose # :nodoc:
module Acts # :nodoc:
class BelongsToWithDeletedAssociation < ActiveRecord::Associations::BelongsToAssociation
private
def find_target
@reflection.klass.find_with_deleted(
@owner[@reflection.primary_key_name],
:conditions => conditions,
:include => @reflection.options[:include]
)
end
end
end
end

View file

@ -1,27 +0,0 @@
module Caboose # :nodoc:
module Acts # :nodoc:
class HasManyThroughWithoutDeletedAssociation < ActiveRecord::Associations::HasManyThroughAssociation
protected
def current_time
ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now
end
def construct_conditions
return super unless @reflection.through_reflection.klass.paranoid?
table_name = @reflection.through_reflection.table_name
conditions = construct_quoted_owner_attributes(@reflection.through_reflection).map do |attr, value|
"#{table_name}.#{attr} = #{value}"
end
deleted_attribute = @reflection.through_reflection.klass.deleted_attribute
quoted_current_time = @reflection.through_reflection.klass.quote_value(
current_time,
@reflection.through_reflection.klass.columns_hash[deleted_attribute.to_s])
conditions << "#{table_name}.#{deleted_attribute} IS NULL OR #{table_name}.#{deleted_attribute} > #{quoted_current_time}"
conditions << sql_conditions if sql_conditions
"(" + conditions.join(') AND (') + ")"
end
end
end
end

View file

@ -1,197 +0,0 @@
module Caboose #:nodoc:
module Acts #:nodoc:
# Overrides some basic methods for the current model so that calling #destroy sets a 'deleted_at' field to the current timestamp.
# This assumes the table has a deleted_at date/time field. Most normal model operations will work, but there will be some oddities.
#
# class Widget < ActiveRecord::Base
# acts_as_paranoid
# end
#
# Widget.find(:all)
# # SELECT * FROM widgets WHERE widgets.deleted_at IS NULL
#
# Widget.find(:first, :conditions => ['title = ?', 'test'], :order => 'title')
# # SELECT * FROM widgets WHERE widgets.deleted_at IS NULL AND title = 'test' ORDER BY title LIMIT 1
#
# Widget.find_with_deleted(:all)
# # SELECT * FROM widgets
#
# Widget.find_only_deleted(:all)
# # SELECT * FROM widgets WHERE widgets.deleted_at IS NOT NULL
#
# Widget.find_with_deleted(1).deleted?
# # Returns true if the record was previously destroyed, false if not
#
# Widget.count
# # SELECT COUNT(*) FROM widgets WHERE widgets.deleted_at IS NULL
#
# Widget.count ['title = ?', 'test']
# # SELECT COUNT(*) FROM widgets WHERE widgets.deleted_at IS NULL AND title = 'test'
#
# Widget.count_with_deleted
# # SELECT COUNT(*) FROM widgets
#
# Widget.count_only_deleted
# # SELECT COUNT(*) FROM widgets WHERE widgets.deleted_at IS NOT NULL
#
# Widget.delete_all
# # UPDATE widgets SET deleted_at = '2005-09-17 17:46:36'
#
# Widget.delete_all!
# # DELETE FROM widgets
#
# @widget.destroy
# # UPDATE widgets SET deleted_at = '2005-09-17 17:46:36' WHERE id = 1
#
# @widget.destroy!
# # DELETE FROM widgets WHERE id = 1
#
module Paranoid
def self.included(base) # :nodoc:
base.extend ClassMethods
end
module ClassMethods
def acts_as_paranoid(options = {})
unless paranoid? # don't let AR call this twice
cattr_accessor :deleted_attribute
self.deleted_attribute = options[:with] || :deleted_at
alias_method :destroy_without_callbacks!, :destroy_without_callbacks
class << self
# alias_method :find_every_with_deleted, :find_every
# alias_method :calculate_with_deleted, :calculate
alias_method :delete_all!, :delete_all
end
send :scope, :without_deleted, :conditions => {:deleted_at => nil}
end
include InstanceMethods
end
def paranoid?
self.included_modules.include?(InstanceMethods)
end
end
module InstanceMethods #:nodoc:
def self.included(base) # :nodoc:
base.extend ClassMethods
end
module ClassMethods
# def find_with_deleted(*args)
# options = args.extract_options!
# validate_find_options(options)
# set_readonly_option!(options)
# options[:with_deleted] = true # yuck!
#
# case args.first
# when :first then find_initial(options)
# when :all then find_every(options)
# else find_from_ids(args, options)
# end
# end
#
# def find_only_deleted(*args)
# options = args.extract_options!
# validate_find_options(options)
# set_readonly_option!(options)
# options[:only_deleted] = true # yuck!
#
# case args.first
# when :first then find_initial(options)
# when :all then find_every(options)
# else find_from_ids(args, options)
# end
# end
#
# def exists?(*args)
# with_deleted_scope { exists_with_deleted?(*args) }
# end
#
# def exists_only_deleted?(*args)
# with_only_deleted_scope { exists_with_deleted?(*args) }
# end
#
# def count_with_deleted(*args)
# calculate_with_deleted(:count, *construct_count_options_from_args(*args))
# end
#
# def count_only_deleted(*args)
# with_only_deleted_scope { count_with_deleted(*args) }
# end
#
# def count(*args)
# with_deleted_scope { count_with_deleted(*args) }
# end
#
# def calculate(*args)
# with_deleted_scope { calculate_with_deleted(*args) }
# end
def delete_all(conditions = nil)
self.update_all ["#{self.deleted_attribute} = ?", current_time], conditions
end
protected
def current_time
default_timezone == :utc ? Time.now.utc : Time.now
end
# def with_deleted_scope(&block)
# with_scope({:find => { :conditions => ["#{table_name}.#{deleted_attribute} IS NULL OR #{table_name}.#{deleted_attribute} > ?", current_time] } }, :merge, &block)
# end
#
# def with_only_deleted_scope(&block)
# with_scope({:find => { :conditions => ["#{table_name}.#{deleted_attribute} IS NOT NULL AND #{table_name}.#{deleted_attribute} <= ?", current_time] } }, :merge, &block)
# end
private
# all find calls lead here
# def find_every(options)
# options.delete(:with_deleted) ?
# find_every_with_deleted(options) :
# options.delete(:only_deleted) ?
# with_only_deleted_scope { find_every_with_deleted(options) } :
# with_deleted_scope { find_every_with_deleted(options) }
# end
end
def destroy_without_callbacks
unless new_record?
self.class.update_all self.class.send(:sanitize_sql, ["#{self.class.deleted_attribute} = ?", (self.deleted_at = self.class.send(:current_time))]), ["#{self.class.primary_key} = ?", id]
end
freeze
end
def destroy_with_callbacks!
return false if callback(:before_destroy) == false
result = destroy_without_callbacks!
callback(:after_destroy)
result
end
def destroy!
transaction { destroy_with_callbacks! }
end
def deleted?
!!read_attribute(:deleted_at)
end
def recover!
self.deleted_at = nil
save!
end
# def recover_with_associations!(*associations)
# self.recover!
# associations.to_a.each do |assoc|
# self.send(assoc).find_with_deleted(:all).each do |a|
# a.recover! if a.class.paranoid?
# end
# end
# end
end
end
end
end

View file

@ -1,94 +0,0 @@
module Caboose #:nodoc:
module Acts #:nodoc:
# Adds a wrapper find method which can identify :with_deleted or :only_deleted options
# and would call the corresponding acts_as_paranoid finders find_with_deleted or
# find_only_deleted methods.
#
# With this wrapper you can easily change from using this pattern:
#
# if some_condition_enabling_access_to_deleted_records?
# @post = Post.find_with_deleted(params[:id])
# else
# @post = Post.find(params[:id])
# end
#
# to this:
#
# @post = Post.find(params[:id], :with_deleted => some_condition_enabling_access_to_deleted_records?)
#
# Examples
#
# class Widget < ActiveRecord::Base
# acts_as_paranoid
# end
#
# Widget.find(:all)
# # SELECT * FROM widgets WHERE widgets.deleted_at IS NULL
#
# Widget.find(:all, :with_deleted => false)
# # SELECT * FROM widgets WHERE widgets.deleted_at IS NULL
#
# Widget.find_with_deleted(:all)
# # SELECT * FROM widgets
#
# Widget.find(:all, :with_deleted => true)
# # SELECT * FROM widgets
#
# Widget.find_only_deleted(:all)
# # SELECT * FROM widgets WHERE widgets.deleted_at IS NOT NULL
#
# Widget.find(:all, :only_deleted => true)
# # SELECT * FROM widgets WHERE widgets.deleted_at IS NOT NULL
#
# Widget.find(:all, :only_deleted => false)
# # SELECT * FROM widgets WHERE widgets.deleted_at IS NULL
#
module ParanoidFindWrapper
def self.included(base) # :nodoc:
base.extend ClassMethods
end
module ClassMethods
def acts_as_paranoid_with_find_wrapper(options = {})
unless paranoid? # don't let AR call this twice
acts_as_paranoid_without_find_wrapper(options)
class << self
alias_method :find_without_find_wrapper, :find
alias_method :validate_find_options_without_find_wrapper, :validate_find_options
end
end
include InstanceMethods
end
end
module InstanceMethods #:nodoc:
def self.included(base) # :nodoc:
base.extend ClassMethods
end
module ClassMethods
# This is a wrapper for the regular "find" so you can pass acts_as_paranoid related
# options and determine which finder to call.
def find(*args)
options = args.extract_options!
# Determine who to call.
finder_option = VALID_PARANOID_FIND_OPTIONS.detect { |key| options.delete(key) } || :without_find_wrapper
finder_method = "find_#{finder_option}".to_sym
# Put back the options in the args now that they don't include the extended keys.
args << options
send(finder_method, *args)
end
protected
VALID_PARANOID_FIND_OPTIONS = [:with_deleted, :only_deleted]
def validate_find_options(options) #:nodoc:
cleaned_options = options.reject { |k, v| VALID_PARANOID_FIND_OPTIONS.include?(k) }
validate_find_options_without_find_wrapper(cleaned_options)
end
end
end
end
end
end

View file

@ -1,18 +0,0 @@
sqlite:
:adapter: sqlite
:dbfile: acts_as_paranoid_plugin.sqlite.db
sqlite3:
:adapter: sqlite3
:dbfile: acts_as_paranoid_plugin.sqlite3.db
postgresql:
:adapter: postgresql
:username: postgres
:password: postgres
:database: acts_as_paranoid_plugin_test
:min_messages: ERROR
mysql:
:adapter: mysql
:host: localhost
:username: rails
:password:
:database: acts_as_paranoid_plugin_test

View file

@ -1,19 +0,0 @@
category_1:
id: 1
widget_id: 1
title: 'category 1'
category_2:
id: 2
widget_id: 1
title: 'category 2'
deleted_at: '2005-01-01 00:00:00'
category_3:
id: 3
widget_id: 2
title: 'category 3'
deleted_at: '2005-01-01 00:00:00'
category_4:
id: 4
widget_id: 2
title: 'category 4'
deleted_at: '2005-01-01 00:00:00'

View file

@ -1,12 +0,0 @@
cw_1:
category_id: 1
widget_id: 1
cw_2:
category_id: 2
widget_id: 1
cw_3:
category_id: 3
widget_id: 2
cw_4:
category_id: 4
widget_id: 2

View file

@ -1,9 +0,0 @@
tagging_1:
id: 1
tag_id: 1
widget_id: 1
deleted_at: '2005-01-01 00:00:00'
tagging_2:
id: 2
tag_id: 2
widget_id: 1

View file

@ -1,6 +0,0 @@
tag_1:
id: 1
name: 'tag 1'
tag_2:
id: 2
name: 'tag 1'

View file

@ -1,8 +0,0 @@
widget_1:
id: 1
title: 'widget 1'
widget_2:
id: 2
title: 'deleted widget 2'
deleted_at: '2005-01-01 00:00:00'
category_id: 3

View file

@ -1,287 +0,0 @@
require File.join(File.dirname(__FILE__), 'test_helper')
class Widget < ActiveRecord::Base
acts_as_paranoid
has_many :categories, :dependent => :destroy
has_and_belongs_to_many :habtm_categories, :class_name => 'Category'
has_one :category
belongs_to :parent_category, :class_name => 'Category'
has_many :taggings
has_many :tags, :through => :taggings
has_many :any_tags, :through => :taggings, :class_name => 'Tag', :source => :tag, :with_deleted => true
end
class Category < ActiveRecord::Base
belongs_to :widget
belongs_to :any_widget, :class_name => 'Widget', :foreign_key => 'widget_id', :with_deleted => true
acts_as_paranoid
def self.search(name, options = {})
find :all, options.merge(:conditions => ['LOWER(title) LIKE ?', "%#{name.to_s.downcase}%"])
end
def self.search_with_deleted(name, options = {})
find_with_deleted :all, options.merge(:conditions => ['LOWER(title) LIKE ?', "%#{name.to_s.downcase}%"])
end
end
class Tag < ActiveRecord::Base
has_many :taggings
has_many :widgets, :through => :taggings
end
class Tagging < ActiveRecord::Base
belongs_to :tag
belongs_to :widget
acts_as_paranoid
end
class NonParanoidAndroid < ActiveRecord::Base
end
class ParanoidTest < Test::Unit::TestCase
fixtures :widgets, :categories, :categories_widgets, :tags, :taggings
def test_should_recognize_with_deleted_option
assert_equal [1, 2], Widget.find(:all, :with_deleted => true).collect { |w| w.id }
assert_equal [1], Widget.find(:all, :with_deleted => false).collect { |w| w.id }
end
def test_should_recognize_only_deleted_option
assert_equal [2], Widget.find(:all, :only_deleted => true).collect { |w| w.id }
assert_equal [1], Widget.find(:all, :only_deleted => false).collect { |w| w.id }
end
def test_should_exists_with_deleted
assert Widget.exists_with_deleted?(2)
assert !Widget.exists?(2)
end
def test_should_exists_only_deleted
assert Widget.exists_only_deleted?(2)
assert !Widget.exists_only_deleted?(1)
end
def test_should_count_with_deleted
assert_equal 1, Widget.count
assert_equal 2, Widget.count_with_deleted
assert_equal 1, Widget.count_only_deleted
assert_equal 2, Widget.calculate_with_deleted(:count, :all)
end
def test_should_set_deleted_at
assert_equal 1, Widget.count
assert_equal 1, Category.count
widgets(:widget_1).destroy
assert_equal 0, Widget.count
assert_equal 0, Category.count
assert_equal 2, Widget.calculate_with_deleted(:count, :all)
assert_equal 4, Category.calculate_with_deleted(:count, :all)
end
def test_should_destroy
assert_equal 1, Widget.count
assert_equal 1, Category.count
widgets(:widget_1).destroy!
assert_equal 0, Widget.count
assert_equal 0, Category.count
assert_equal 1, Widget.count_only_deleted
assert_equal 1, Widget.calculate_with_deleted(:count, :all)
# Category doesn't get destroyed because the dependent before_destroy callback uses #destroy
assert_equal 4, Category.calculate_with_deleted(:count, :all)
end
def test_should_delete_all
assert_equal 1, Widget.count
assert_equal 2, Widget.calculate_with_deleted(:count, :all)
assert_equal 1, Category.count
Widget.delete_all
assert_equal 0, Widget.count
# delete_all doesn't call #destroy, so the dependent callback never fires
assert_equal 1, Category.count
assert_equal 2, Widget.calculate_with_deleted(:count, :all)
end
def test_should_delete_all_with_conditions
assert_equal 1, Widget.count
assert_equal 2, Widget.calculate_with_deleted(:count, :all)
Widget.delete_all("id < 3")
assert_equal 0, Widget.count
assert_equal 2, Widget.calculate_with_deleted(:count, :all)
end
def test_should_delete_all2
assert_equal 1, Category.count
assert_equal 4, Category.calculate_with_deleted(:count, :all)
Category.delete_all!
assert_equal 0, Category.count
assert_equal 0, Category.calculate_with_deleted(:count, :all)
end
def test_should_delete_all_with_conditions2
assert_equal 1, Category.count
assert_equal 4, Category.calculate_with_deleted(:count, :all)
Category.delete_all!("id < 3")
assert_equal 0, Category.count
assert_equal 2, Category.calculate_with_deleted(:count, :all)
end
def test_should_not_count_deleted
assert_equal 1, Widget.count
assert_equal 1, Widget.count(:all, :conditions => ['title=?', 'widget 1'])
assert_equal 2, Widget.calculate_with_deleted(:count, :all)
assert_equal 1, Widget.count_only_deleted
end
def test_should_find_only_deleted
assert_equal [2], Widget.find_only_deleted(:all).collect { |w| w.id }
assert_equal [1, 2], Widget.find_with_deleted(:all, :order => 'id').collect { |w| w.id }
end
def test_should_not_find_deleted
assert_equal [widgets(:widget_1)], Widget.find(:all)
assert_equal [1, 2], Widget.find_with_deleted(:all, :order => 'id').collect { |w| w.id }
end
def test_should_not_find_deleted_has_many_associations
assert_equal 1, widgets(:widget_1).categories.size
assert_equal [categories(:category_1)], widgets(:widget_1).categories
end
def test_should_not_find_deleted_habtm_associations
assert_equal 1, widgets(:widget_1).habtm_categories.size
assert_equal [categories(:category_1)], widgets(:widget_1).habtm_categories
end
def test_should_not_find_deleted_has_many_through_associations
assert_equal 1, widgets(:widget_1).tags.size
assert_equal [tags(:tag_2)], widgets(:widget_1).tags
end
def test_should_find_has_many_through_associations_with_deleted
assert_equal 2, widgets(:widget_1).any_tags.size
assert_equal Tag.find(:all), widgets(:widget_1).any_tags
end
def test_should_not_find_deleted_belongs_to_associations
assert_nil Category.find_with_deleted(3).widget
end
def test_should_find_belongs_to_assocation_with_deleted
assert_equal Widget.find_with_deleted(2), Category.find_with_deleted(3).any_widget
end
def test_should_find_first_with_deleted
assert_equal widgets(:widget_1), Widget.find(:first)
assert_equal 2, Widget.find_with_deleted(:first, :order => 'id desc').id
end
def test_should_find_single_id
assert Widget.find(1)
assert Widget.find_with_deleted(2)
assert_raises(ActiveRecord::RecordNotFound) { Widget.find(2) }
end
def test_should_find_multiple_ids
assert_equal [1,2], Widget.find_with_deleted(1,2).sort_by { |w| w.id }.collect { |w| w.id }
assert_equal [1,2], Widget.find_with_deleted([1,2]).sort_by { |w| w.id }.collect { |w| w.id }
assert_raises(ActiveRecord::RecordNotFound) { Widget.find(1,2) }
end
def test_should_ignore_multiple_includes
Widget.class_eval { acts_as_paranoid }
assert Widget.find(1)
end
def test_should_not_override_scopes_when_counting
assert_equal 1, Widget.send(:with_scope, :find => { :conditions => "title = 'widget 1'" }) { Widget.count }
assert_equal 0, Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) { Widget.count }
assert_equal 1, Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) { Widget.calculate_with_deleted(:count, :all) }
end
def test_should_not_override_scopes_when_finding
assert_equal [1], Widget.send(:with_scope, :find => { :conditions => "title = 'widget 1'" }) { Widget.find(:all) }.ids
assert_equal [], Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) { Widget.find(:all) }.ids
assert_equal [2], Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) { Widget.find_with_deleted(:all) }.ids
end
def test_should_allow_multiple_scoped_calls_when_finding
Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) do
assert_equal [2], Widget.find_with_deleted(:all).ids
assert_equal [2], Widget.find_with_deleted(:all).ids, "clobbers the constrain on the unmodified find"
assert_equal [], Widget.find(:all).ids
assert_equal [], Widget.find(:all).ids, 'clobbers the constrain on a paranoid find'
end
end
def test_should_allow_multiple_scoped_calls_when_counting
Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) do
assert_equal 1, Widget.calculate_with_deleted(:count, :all)
assert_equal 1, Widget.calculate_with_deleted(:count, :all), "clobbers the constrain on the unmodified find"
assert_equal 0, Widget.count
assert_equal 0, Widget.count, 'clobbers the constrain on a paranoid find'
end
end
def test_should_give_paranoid_status
assert Widget.paranoid?
assert !NonParanoidAndroid.paranoid?
end
def test_should_give_record_status
assert_equal false, Widget.find(1).deleted?
Widget.find(1).destroy
assert Widget.find_with_deleted(1).deleted?
end
def test_should_find_deleted_has_many_assocations_on_deleted_records_by_default
w = Widget.find_with_deleted 2
assert_equal 2, w.categories.find_with_deleted(:all).length
assert_equal 2, w.categories.find_with_deleted(:all).size
end
def test_should_find_deleted_habtm_assocations_on_deleted_records_by_default
w = Widget.find_with_deleted 2
assert_equal 2, w.habtm_categories.find_with_deleted(:all).length
assert_equal 2, w.habtm_categories.find_with_deleted(:all).size
end
def test_dynamic_finders
assert Widget.find_by_id(1)
assert_nil Widget.find_by_id(2)
end
def test_custom_finder_methods
w = Widget.find_with_deleted(:all).inject({}) { |all, w| all.merge(w.id => w) }
assert_equal [1], Category.search('c').ids
assert_equal [1,2,3,4], Category.search_with_deleted('c', :order => 'id').ids
assert_equal [1], widgets(:widget_1).categories.search('c').collect(&:id)
assert_equal [1,2], widgets(:widget_1).categories.search_with_deleted('c').ids
assert_equal [], w[2].categories.search('c').ids
assert_equal [3,4], w[2].categories.search_with_deleted('c').ids
end
def test_should_recover_record
Widget.find(1).destroy
assert_equal true, Widget.find_with_deleted(1).deleted?
Widget.find_with_deleted(1).recover!
assert_equal false, Widget.find(1).deleted?
end
def test_should_recover_record_and_has_many_associations
Widget.find(1).destroy
assert_equal true, Widget.find_with_deleted(1).deleted?
assert_equal true, Category.find_with_deleted(1).deleted?
Widget.find_with_deleted(1).recover_with_associations!(:categories)
assert_equal false, Widget.find(1).deleted?
assert_equal false, Category.find(1).deleted?
end
end
class Array
def ids
collect &:id
end
end

View file

@ -1,30 +0,0 @@
ActiveRecord::Schema.define(:version => 1) do
create_table :widgets, :force => true do |t|
t.column :title, :string, :limit => 50
t.column :category_id, :integer
t.column :deleted_at, :timestamp
end
create_table :categories, :force => true do |t|
t.column :widget_id, :integer
t.column :title, :string, :limit => 50
t.column :deleted_at, :timestamp
end
create_table :categories_widgets, :force => true, :id => false do |t|
t.column :category_id, :integer
t.column :widget_id, :integer
end
create_table :tags, :force => true do |t|
t.column :name, :string, :limit => 50
end
create_table :taggings, :force => true do |t|
t.column :tag_id, :integer
t.column :widget_id, :integer
t.column :deleted_at, :timestamp
end
end

View file

@ -1,33 +0,0 @@
$:.unshift(File.dirname(__FILE__) + '/../lib')
require 'test/unit'
require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
require 'rubygems'
require 'active_record/fixtures'
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite'])
load(File.dirname(__FILE__) + "/schema.rb")
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
$LOAD_PATH.unshift(Test::Unit::TestCase.fixture_path)
class Test::Unit::TestCase #:nodoc:
def create_fixtures(*table_names)
if block_given?
Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names) { yield }
else
Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names)
end
end
# Turn off transactional fixtures if you're working with MyISAM tables in MySQL
self.use_transactional_fixtures = true
# Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david)
self.use_instantiated_fixtures = false
# Add more helper methods to be used by all tests here...
end

View file

@ -13,6 +13,6 @@ rescue LoadError
end
end
# Load Haml and Sass.
# Load Haml.
# Haml may be undefined if we're running gems:install.
Haml.init_rails(binding) if defined?(Haml)