filthy 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Manifest ADDED
@@ -0,0 +1,8 @@
1
+ README.md
2
+ Rakefile
3
+ filthy.gemspec
4
+ lib/filthy.rb
5
+ test/database.yml
6
+ test/filthy_test.rb
7
+ test/helper.rb
8
+ Manifest
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # Filthy
2
+
3
+ Rails gem to check if an attribute was changed on the last save. Useful in after_save callbacks.
4
+
5
+ # Install
6
+ ```bash
7
+ gem install filthy
8
+ ```
9
+ ### Usage
10
+
11
+ ```ruby
12
+ class Movie < ActiveRecord::Base
13
+
14
+ filthy_attributes :title, :director
15
+
16
+ end
17
+
18
+ @movie = Movie.find(1)
19
+ @movie.title = "28 days later"
20
+ @movie.title_filthy?
21
+ => false
22
+ @movie.save
23
+ => true
24
+ @movie.title_filthy?
25
+ => true
26
+ @movie.save
27
+ => true
28
+ @movie.title_filthy?
29
+ => false
30
+ ```
31
+
32
+ # Credits
33
+
34
+ Filthy is maintained by [Mike Taylor](http://github.com/sealabcore) and is funded by [BookRenter.com](http://www.bookrenter.com "BookRenter.com"). Many of the ideas that have inspired Filthy come from practical usage by the Bookrenter software development team and conversations with Bookrenter developers [Andrew Wheeler](http://github.com/jawheeler), [Michael Pearce](http://github.com/michaelgpearce), and [Philippe Huibonhoa](http://github.com/phuibonhoa).
35
+
36
+ ![BookRenter.com Logo](http://assets0.bookrenter.com/images/header/bookrenter_logo.gif "BookRenter.com")
37
+
38
+ # Copyright
39
+
40
+ Copyright (c) 2012 Mike Taylor, Bookrenter.com.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('filthy', '1.0.0') do |p|
6
+ p.description = "Check if an attribute was changed after the last save."
7
+ p.url = "http://github.com/sealabcore/filthy"
8
+ p.author = "Mike Taylor"
9
+ p.email = "michael.taylor@bookrenter.com"
10
+ p.ignore_pattern = ["tmp/*", "script/*"]
11
+ p.development_dependencies = ["sqlite3", "active_record", "active_support", 'test/unit', 'shoulda-context']
12
+ end
13
+
14
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
data/filthy.gemspec ADDED
@@ -0,0 +1,45 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "filthy"
5
+ s.version = "1.0.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Mike Taylor"]
9
+ s.date = "2012-01-20"
10
+ s.description = "Check if an attribute was changed after the last save."
11
+ s.email = "michael.taylor@bookrenter.com"
12
+ s.extra_rdoc_files = ["README.md", "lib/filthy.rb"]
13
+ s.files = ["README.md", "Rakefile", "filthy.gemspec", "lib/filthy.rb", "test/database.yml", "test/filthy_test.rb", "test/helper.rb", "Manifest"]
14
+ s.homepage = "http://github.com/sealabcore/filthy"
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Filthy", "--main", "README.md"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = "filthy"
18
+ s.rubygems_version = "1.8.10"
19
+ s.summary = "Check if an attribute was changed after the last save."
20
+ s.test_files = ["test/filthy_test.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
26
+ s.add_development_dependency(%q<sqlite3>, [">= 0"])
27
+ s.add_development_dependency(%q<active_record>, [">= 0"])
28
+ s.add_development_dependency(%q<active_support>, [">= 0"])
29
+ s.add_development_dependency(%q<test/unit>, [">= 0"])
30
+ s.add_development_dependency(%q<shoulda-context>, [">= 0"])
31
+ else
32
+ s.add_dependency(%q<sqlite3>, [">= 0"])
33
+ s.add_dependency(%q<active_record>, [">= 0"])
34
+ s.add_dependency(%q<active_support>, [">= 0"])
35
+ s.add_dependency(%q<test/unit>, [">= 0"])
36
+ s.add_dependency(%q<shoulda-context>, [">= 0"])
37
+ end
38
+ else
39
+ s.add_dependency(%q<sqlite3>, [">= 0"])
40
+ s.add_dependency(%q<active_record>, [">= 0"])
41
+ s.add_dependency(%q<active_support>, [">= 0"])
42
+ s.add_dependency(%q<test/unit>, [">= 0"])
43
+ s.add_dependency(%q<shoulda-context>, [">= 0"])
44
+ end
45
+ end
data/lib/filthy.rb ADDED
@@ -0,0 +1,53 @@
1
+ require 'active_record'
2
+ require 'active_support'
3
+
4
+ module Filthy
5
+
6
+ module ClassMethods
7
+
8
+ def filthy_attributes(*args)
9
+ class_variable_set(:@@filthy_attributes, args)
10
+
11
+ class_variable_set(:@@filthy_attribute_methods, class_variable_get(:@@filthy_attributes).collect { |attribute| :"#{attribute}_filthy" })
12
+
13
+ class_variable_get(:@@filthy_attribute_methods).each do |method|
14
+ attr_accessor method
15
+
16
+ send(:define_method, :"#{method}?") do
17
+ !!send(method)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ module InstanceMethods
24
+
25
+ def has_filthy_attributes?
26
+ self.class.class_variables.include?("@@filthy_attributes")
27
+ end
28
+
29
+ def set_filthy_before_save
30
+ clean_filthy_attributes
31
+ filthy_attributes = changes.keys.select { |attribute| self.class.send(:class_variable_get, :@@filthy_attributes).include? attribute.to_sym }
32
+ filthy_attributes.each do |filthy_attribute|
33
+ send("#{filthy_attribute}_filthy=", true)
34
+ end
35
+ end
36
+
37
+ def clean_filthy_attributes
38
+ self.class.send(:class_variable_get, :@@filthy_attribute_methods).each { |fa| send("#{fa}=", nil) }
39
+ end
40
+
41
+ end
42
+
43
+ def self.included(base)
44
+ base.extend ClassMethods
45
+ base.send(:include, InstanceMethods)
46
+ base.before_save :set_filthy_before_save, :if => Proc.new { |object| object.has_filthy_attributes? }
47
+ end
48
+
49
+ end
50
+
51
+ class ActiveRecord::Base
52
+ include Filthy
53
+ end
data/test/database.yml ADDED
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: ":memory:"
@@ -0,0 +1,88 @@
1
+ require File.join(File.dirname(__FILE__), %w[helper])
2
+
3
+ class MovieTest < Test::Unit::TestCase
4
+
5
+ context "filthy_attributes" do
6
+ setup do
7
+ @movie = Movie.new
8
+ end
9
+
10
+ context "with passed attributes" do
11
+ context "on a new record" do
12
+ should "create accessors" do
13
+ assert_nil @movie.director_filthy
14
+ assert_nil @movie.title_filthy
15
+ end
16
+
17
+ should "create boolean methods" do
18
+ assert !@movie.director_filthy?
19
+ assert !@movie.title_filthy?
20
+ end
21
+ end
22
+
23
+ context "after_save" do
24
+ setup do
25
+ @movie.title = "The Dream Warrior"
26
+ @movie.save
27
+ end
28
+
29
+ context "when only title changed" do
30
+ should "be true for filthy attributese" do
31
+ assert @movie.title_filthy?
32
+ assert !@movie.director_filthy?
33
+ end
34
+ end
35
+
36
+ context "after another save" do
37
+ setup do
38
+ @movie.director = "Rob Zombie"
39
+ @movie.save
40
+ end
41
+
42
+ should "be true for filthy attributes" do
43
+ assert !@movie.title_filthy?
44
+ assert @movie.director_filthy?
45
+ end
46
+
47
+ context "after another save when nothing changed" do
48
+ setup do
49
+ @movie.save
50
+ end
51
+
52
+ should "not have filthy attributes" do
53
+ assert !@movie.title_filthy?
54
+ assert !@movie.director_filthy?
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ context "a model without filthy attributes" do
63
+ setup do
64
+ @actor = Actor.new
65
+ end
66
+
67
+ should "save" do
68
+ assert @actor.save
69
+ end
70
+ end
71
+
72
+ context "a model with filthy attributes" do
73
+ context "with a subclass with no filthy_attributes defined" do
74
+ setup do
75
+ @short = Short.new
76
+ @short.title = "Intruder"
77
+ @short.save
78
+ end
79
+
80
+ should "have filthy attributes" do
81
+ assert !@short.director_filthy?
82
+ assert @short.title_filthy?
83
+ end
84
+ end
85
+ end
86
+
87
+ end
88
+
data/test/helper.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'sqlite3'
4
+ require 'filthy'
5
+ require 'shoulda-context'
6
+
7
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
8
+ ActiveRecord::Base.establish_connection(config['test'])
9
+
10
+ ActiveRecord::Base.connection.create_table :movies, :force => true do |table|
11
+ table.column :title, :string
12
+ table.column :director, :string
13
+ end
14
+
15
+ ActiveRecord::Base.connection.create_table :actors, :force => true do |table|
16
+ table.column :id, :integer
17
+ table.column :name, :string
18
+ end
19
+
20
+ class Movie < ActiveRecord::Base
21
+
22
+ filthy_attributes :title, :director
23
+
24
+ end
25
+
26
+ class Short < Movie
27
+ end
28
+
29
+ class Actor < ActiveRecord::Base
30
+
31
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: filthy
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Mike Taylor
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-01-20 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: sqlite3
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: active_record
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: active_support
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: test/unit
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ type: :development
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: shoulda-context
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 3
85
+ segments:
86
+ - 0
87
+ version: "0"
88
+ type: :development
89
+ version_requirements: *id005
90
+ description: Check if an attribute was changed after the last save.
91
+ email: michael.taylor@bookrenter.com
92
+ executables: []
93
+
94
+ extensions: []
95
+
96
+ extra_rdoc_files:
97
+ - README.md
98
+ - lib/filthy.rb
99
+ files:
100
+ - README.md
101
+ - Rakefile
102
+ - filthy.gemspec
103
+ - lib/filthy.rb
104
+ - test/database.yml
105
+ - test/filthy_test.rb
106
+ - test/helper.rb
107
+ - Manifest
108
+ homepage: http://github.com/sealabcore/filthy
109
+ licenses: []
110
+
111
+ post_install_message:
112
+ rdoc_options:
113
+ - --line-numbers
114
+ - --inline-source
115
+ - --title
116
+ - Filthy
117
+ - --main
118
+ - README.md
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: 3
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ hash: 11
136
+ segments:
137
+ - 1
138
+ - 2
139
+ version: "1.2"
140
+ requirements: []
141
+
142
+ rubyforge_project: filthy
143
+ rubygems_version: 1.8.10
144
+ signing_key:
145
+ specification_version: 3
146
+ summary: Check if an attribute was changed after the last save.
147
+ test_files:
148
+ - test/filthy_test.rb