inactive_record 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,13 @@
1
+ == 1.0.3 2010-01-04
2
+
3
+ * Added a :methods option to #to_xml that acts just as its ActiveRecord counterpart does.
4
+ * Refactored #to_xml to be more concise.
5
+
6
+ == 1.0.2 2009-06-24
7
+
8
+ * Add attr_human_name method.
9
+
10
+
11
+ == 1.0.0 2009-04-03
12
+
13
+ * Initial release
data/README.rdoc ADDED
@@ -0,0 +1,82 @@
1
+ = inactive_record
2
+
3
+ http://github.com/midas/inactive_record/tree/master
4
+
5
+
6
+ == DESCRIPTION:
7
+
8
+ InactiveRecord gives you many of the features you know and love from ActiveRecord without the need for a backing
9
+ database table.
10
+
11
+
12
+ == FEATURES:
13
+
14
+ * An initialize method that accepts an attribute hash, including the Rails Date/Time select methods (ie. start_date(1i), etc...)
15
+ * A to_xml method that accepts the same options as its respective ActiveRecord method
16
+ * All validations work when you call valid?, excluding validates_uniqueness_of
17
+ * Supports errors_for method (when validations fail, just render the new or edit form as you mormaly would)
18
+ * Works with Rails 2.3
19
+
20
+
21
+ ==PROBLEMS:
22
+
23
+
24
+ == INSTALL:
25
+
26
+ sudo gem install midas-inactive_record
27
+
28
+
29
+ == USE:
30
+
31
+ Add gem requirement to your environment.rb file:
32
+
33
+ config.gem 'midas-inactive_record', :version => '1.0.0', :lib => 'inactive_record', :source => 'http://gems.github.com'
34
+
35
+ Create a model class:
36
+
37
+ class Thing < InactiveRecord::Base
38
+ attr_accessor :name, :begin_date, :end_date
39
+ validates_presence_of :name, :begin_date, :end_date
40
+ end
41
+
42
+ In things_controller.rb:
43
+
44
+ @thing = Thing.new( params[:thing] )
45
+
46
+ unless @thing.valid?
47
+ render :new
48
+ return
49
+ end
50
+
51
+ Now you can use errors_for, etc in your forms.
52
+
53
+
54
+ == REQUIREMENTS:
55
+
56
+ * ActiveRecord >= 2.2.0
57
+
58
+
59
+ == LICENSE:
60
+
61
+ (The MIT License)
62
+
63
+ Copyright (c) 2009 C. Jason Harrelson (midas)
64
+
65
+ Permission is hereby granted, free of charge, to any person obtaining
66
+ a copy of this software and associated documentation files (the
67
+ 'Software'), to deal in the Software without restriction, including
68
+ without limitation the rights to use, copy, modify, merge, publish,
69
+ distribute, sublicense, and/or sell copies of the Software, and to
70
+ permit persons to whom the Software is furnished to do so, subject to
71
+ the following conditions:
72
+
73
+ The above copyright notice and this permission notice shall be
74
+ included in all copies or substantial portions of the Software.
75
+
76
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
77
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
78
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
79
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
80
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
81
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
82
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "inactive_record"
8
+ gem.summary = %Q{InactiveRecord gives you many of the features you know and love from ActiveRecord without the need for a backing database table.}
9
+ gem.description = %Q{InactiveRecord gives you many of the features you know and love from ActiveRecord without the need for a backing database table.}
10
+ gem.email = "jason@lookforwardenterprises.com"
11
+ gem.homepage = "http://github.com/midas/inactive_record"
12
+ gem.authors = ["C. Jason Harrelson (midas)"]
13
+ gem.add_dependency "activerecord", ">= 2.2"
14
+ gem.add_development_dependency "rspec", ">= 1.2.9"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'spec/rake/spectask'
23
+ Spec::Rake::SpecTask.new(:spec) do |spec|
24
+ spec.libs << 'lib' << 'spec'
25
+ spec.spec_files = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.pattern = 'spec/**/*_spec.rb'
31
+ spec.rcov = true
32
+ end
33
+
34
+ task :spec => :check_dependencies
35
+
36
+ task :default => :spec
37
+
38
+ require 'rake/rdoctask'
39
+ Rake::RDocTask.new do |rdoc|
40
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
+
42
+ rdoc.rdoc_dir = 'rdoc'
43
+ rdoc.title = "inactive_record #{version}"
44
+ rdoc.rdoc_files.include('README*')
45
+ rdoc.rdoc_files.include('lib/**/*.rb')
46
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.3
@@ -0,0 +1,62 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{inactive_record}
8
+ s.version = "1.0.3"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["C. Jason Harrelson (midas)"]
12
+ s.date = %q{2010-01-04}
13
+ s.description = %q{InactiveRecord gives you many of the features you know and love from ActiveRecord without the need for a backing database table.}
14
+ s.email = %q{jason@lookforwardenterprises.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ "History.txt",
20
+ "README.rdoc",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "inactive_record.gemspec",
24
+ "lib/inactive_record.rb",
25
+ "lib/inactive_record/base.rb",
26
+ "script/console",
27
+ "script/destroy",
28
+ "script/generate",
29
+ "spec/inactive_record/base_spec.rb",
30
+ "spec/inactive_record_spec.rb",
31
+ "spec/spec.opts",
32
+ "spec/spec_helper.rb",
33
+ "tasks/rspec.rake"
34
+ ]
35
+ s.homepage = %q{http://github.com/midas/inactive_record}
36
+ s.rdoc_options = ["--charset=UTF-8"]
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = %q{1.3.5}
39
+ s.summary = %q{InactiveRecord gives you many of the features you know and love from ActiveRecord without the need for a backing database table.}
40
+ s.test_files = [
41
+ "spec/inactive_record/base_spec.rb",
42
+ "spec/inactive_record_spec.rb",
43
+ "spec/spec_helper.rb"
44
+ ]
45
+
46
+ if s.respond_to? :specification_version then
47
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
+ s.specification_version = 3
49
+
50
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
51
+ s.add_runtime_dependency(%q<activerecord>, [">= 2.2"])
52
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
53
+ else
54
+ s.add_dependency(%q<activerecord>, [">= 2.2"])
55
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
56
+ end
57
+ else
58
+ s.add_dependency(%q<activerecord>, [">= 2.2"])
59
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
60
+ end
61
+ end
62
+
@@ -0,0 +1,191 @@
1
+ require 'active_record'
2
+ require 'active_record/base'
3
+
4
+ module InactiveRecord
5
+ class Base
6
+
7
+ def initialize( attributes={} )
8
+ unless attributes.nil?
9
+ # Fix any dates/times from rails date_select
10
+ keys = attributes.keys
11
+ date_keys = keys.grep(/(1i)/)
12
+ time_keys = keys.grep(/(4i)/)
13
+ date_keys.each do |date_key|
14
+ key = date_key.to_s.gsub( /\(1i\)/, '' )
15
+ num = keys.grep( /#{key.to_s}/ ).size
16
+ if num == 3
17
+ # Date
18
+ attributes[key.to_sym] = Date.civil( attributes.delete( "#{key}(1i)".to_sym ).to_i,
19
+ attributes.delete( "#{key}(2i)".to_sym ).to_i, attributes.delete( "#{key}(3i)".to_sym ).to_i )
20
+ elsif num == 5
21
+ #DateTime
22
+ attributes[key.to_sym] = DateTime.civil( attributes.delete( "#{key}(1i)".to_sym ).to_i,
23
+ attributes.delete( "#{key}(2i)".to_sym ).to_i, attributes.delete( "#{key}(3i)".to_sym ).to_i,
24
+ attributes.delete( "#{key}(4i)".to_sym ).to_i, attributes.delete( "#{key}(5i)".to_sym ).to_i )
25
+ elsif num == 6
26
+ #DateTime
27
+ attributes[key.to_sym] = DateTime.civil( attributes.delete( "#{key}(1i)".to_sym ).to_i,
28
+ attributes.delete( "#{key}(2i)".to_sym ).to_i, attributes.delete( "#{key}(3i)".to_sym ).to_i,
29
+ attributes.delete( "#{key}(4i)".to_sym ).to_i, attributes.delete( "#{key}(5i)".to_sym ).to_i,
30
+ attributes.delete( "#{key}(6i)".to_sym ).to_i )
31
+ end
32
+ end
33
+
34
+ attributes.each do |key, value|
35
+ self.instance_variable_set("@#{key}", value)
36
+ end
37
+ end
38
+ yield self if block_given?
39
+ end
40
+
41
+ def []( key )
42
+ instance_variable_get("@#{key}")
43
+ end
44
+
45
+ def method_missing( method_id, *args )
46
+ if md = /_before_type_cast$/.match(method_id.to_s)
47
+ attr_name = md.pre_match
48
+ return self[attr_name] if self.respond_to?(attr_name)
49
+ end
50
+ super
51
+ end
52
+
53
+ # Instructions on how to build xml for an object.
54
+ #
55
+ # *options*
56
+ # :only - A symbol or array of symbols of instance variable names to include in the xml.
57
+ # :except - A symbol or array of symbols of instance variable names to exclude in the xml.
58
+ # :methods - A symbol or array of symbols of methods to evaluate and include in the xml.
59
+ # :skip_instruct - If true, output the document type, otherwise do not.
60
+ # :skip_types - (not yet) If true, do not output types of variables that are not strings.
61
+ # :include - (not yet) First level associations to include.
62
+ # :dasherize - If true, convert underscored variable names to dasherized variable names.
63
+ #
64
+ def to_xml( options={} )
65
+ options[:indent] ||= 2
66
+ except = options[:except]
67
+ methods = options[:methods]
68
+ only = options[:only]
69
+ throw 'Both the :except and :only options cannot be used simultaneously.' if !except.nil? && !only.nil?
70
+
71
+ only = only.map { |attribute| attribute.to_sym } if only.is_a?( Array )
72
+ only = Array.new << only.to_sym if only.is_a?( String )
73
+ only = Array.new << only if only.is_a?( Symbol )
74
+ except = except.map { |attribute| attribute.to_sym } if except.is_a?( Array )
75
+ except = Array.new << except.to_sym if except.is_a?( String )
76
+ except = Array.new << except if except.is_a?( Symbol )
77
+ methods = methods.map { |attribute| attribute.to_sym } if methods.is_a?( Array )
78
+ methods = Array.new << methods.to_sym if methods.is_a?( String )
79
+ methods = Array.new << methods if methods.is_a?( Symbol )
80
+ dasherize = options[:dasherize]
81
+ dasherize = true unless !dasherize.nil?
82
+
83
+ attrs = self.instance_variables.map { |var| var.to_s.gsub( /@/, '' ).to_sym }
84
+ to_serialize = []
85
+ to_serialize += methods unless methods.nil?
86
+ if only
87
+ to_serialize += (attrs.select { |var| only.include?( var ) })
88
+ elsif except
89
+ to_serialize += (attrs - except)
90
+ else
91
+ to_serialize += attrs unless attrs.nil?
92
+ end
93
+
94
+ xml = options[:builder] ||= Builder::XmlMarkup.new( :indent => options[:indent] )
95
+ xml.instruct! unless options[:skip_instruct]
96
+ el_tag_name = dasherize ? self.class.to_s.underscore.dasherize : self.class.to_s.underscore
97
+ xml.tag!( el_tag_name ) do
98
+ to_serialize.each do |attribute|
99
+ var_name = dasherize ? attribute.to_s.dasherize : attribute
100
+ attr_val = self.send( attribute ) if self.respond_to?( attribute )
101
+ if attr_val.is_a?( Array )
102
+ xml << attr_val.to_xml( :skip_instruct => true )
103
+ else
104
+ if attr_val.nil?
105
+ is_nil = 'true'
106
+ elsif attr_val.is_a?( TrueClass ) || attr_val.is_a?( FalseClass )
107
+ type = 'boolean'
108
+ elsif attr_val.is_a?( Integer ) || attr_val.is_a?( Fixnum )
109
+ type = 'integer'
110
+ elsif attr_val.is_a?( Float )
111
+ type = 'float'
112
+ elsif attr_val.is_a?( DateTime ) || attr_val.is_a?( Date ) || attr_val.is_a?( Time )
113
+ type = 'datetime'
114
+ end
115
+
116
+ if is_nil
117
+ xml.tag!( var_name, attr_val, :nil => is_nil ) #unless attr_val.nil?
118
+ elsif type
119
+ xml.tag!( var_name, attr_val, :type => type ) #unless attr_val.nil?
120
+ else
121
+ xml.tag!( var_name, attr_val ) #unless attr_val.nil?
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ def new_record?
129
+ true
130
+ end
131
+
132
+ def self.self_and_descendents_from_active_record
133
+ [self]
134
+ end
135
+
136
+ def self.self_and_descendants_from_active_record
137
+ [self]
138
+ end
139
+
140
+ def self.human_name( options={} )
141
+ Base.human_attribute_name(@name)
142
+ end
143
+
144
+ # Allows alternate humanized versions of attributes to be set. For example, an attribute such as 'num_employees' would be
145
+ # converted to 'Num employees' normally using <tt>human_attribute_name</tt>. More descriptive text can be set. Example:
146
+ # attr_human_name 'num_employees' => 'Number of employees'
147
+ def self.attr_human_name(attributes) # :nodoc:
148
+ attributes.stringify_keys!
149
+ write_inheritable_hash("attr_human_name", attributes || {})
150
+
151
+ # assign the current class to each column that is being assigned a new human attribute name
152
+ #self.columns.reject{|c| !attributes.has_key?(c.name)}.each{|c| c.parent_record_class = self}
153
+ end
154
+
155
+ def self.human_name_attributes # :nodoc:
156
+ read_inheritable_attribute("attr_human_name")
157
+ end
158
+
159
+ # Transforms attribute key names into a more humane format, such as "First name" instead of "first_name". Example:
160
+ # Person.human_attribute_name("first_name") # => "First name"
161
+ def self.human_attribute_name(attribute_key_name) #:nodoc:
162
+ (read_inheritable_attribute("attr_human_name") || {})[attribute_key_name.to_s] || ""
163
+ end
164
+
165
+ protected
166
+
167
+ def raise_not_implemented_error(*params)
168
+ ValidatingModel.raise_not_implemented_error(*params)
169
+ end
170
+
171
+ alias save raise_not_implemented_error
172
+ alias update_attribute raise_not_implemented_error
173
+ alias save! raise_not_implemented_error
174
+
175
+ public
176
+ include ActiveRecord::Validations
177
+
178
+ class << self
179
+ def raise_not_implemented_error(*params)
180
+ raise NotImplementedError
181
+ end
182
+
183
+ alias validates_uniqueness_of raise_not_implemented_error
184
+ alias create! raise_not_implemented_error
185
+ alias validate_on_create raise_not_implemented_error
186
+ alias validate_on_update raise_not_implemented_error
187
+ alias save_with_validation raise_not_implemented_error
188
+ end
189
+
190
+ end
191
+ end
@@ -0,0 +1,8 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'inactive_record/base'
5
+
6
+ module InactiveRecord
7
+ VERSION = '1.0.3'
8
+ end
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/inactive_record.rb'}"
9
+ puts "Loading inactive_record gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
File without changes
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ # Time to add your specs!
4
+ # http://rspec.info/
5
+ describe "Place your specs here" do
6
+
7
+ it "find this spec in spec directory" do
8
+ violated "Be sure to write your specs"
9
+ end
10
+
11
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,10 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'inactive_record'
data/tasks/rspec.rake ADDED
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inactive_record
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.3
5
+ platform: ruby
6
+ authors:
7
+ - C. Jason Harrelson (midas)
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-04 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activerecord
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "2.2"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.9
34
+ version:
35
+ description: InactiveRecord gives you many of the features you know and love from ActiveRecord without the need for a backing database table.
36
+ email: jason@lookforwardenterprises.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ files:
44
+ - History.txt
45
+ - README.rdoc
46
+ - Rakefile
47
+ - VERSION
48
+ - inactive_record.gemspec
49
+ - lib/inactive_record.rb
50
+ - lib/inactive_record/base.rb
51
+ - script/console
52
+ - script/destroy
53
+ - script/generate
54
+ - spec/inactive_record/base_spec.rb
55
+ - spec/inactive_record_spec.rb
56
+ - spec/spec.opts
57
+ - spec/spec_helper.rb
58
+ - tasks/rspec.rake
59
+ has_rdoc: true
60
+ homepage: http://github.com/midas/inactive_record
61
+ licenses: []
62
+
63
+ post_install_message:
64
+ rdoc_options:
65
+ - --charset=UTF-8
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.3.5
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: InactiveRecord gives you many of the features you know and love from ActiveRecord without the need for a backing database table.
87
+ test_files:
88
+ - spec/inactive_record/base_spec.rb
89
+ - spec/inactive_record_spec.rb
90
+ - spec/spec_helper.rb