classy-inheritance 0.6.2 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ *.DS_Store
2
+ *.swp
3
+ nbproject/**
4
+ pkg/**
5
+ doc/**
6
+ email.txt
7
+ test/database.sqlite3
@@ -1,26 +1,12 @@
1
1
  History.txt
2
2
  License.txt
3
3
  Manifest.txt
4
- PostInstall.txt
5
- README
6
4
  README.txt
7
5
  Rakefile
8
- config/hoe.rb
9
- config/requirements.rb
10
6
  lib/classy-inheritance.rb
11
- lib/classy-inheritance/version.rb
12
- script/console
13
- script/destroy
14
- script/generate
15
- script/txt2html
16
- setup.rb
17
- tasks/deployment.rake
18
- tasks/environment.rake
19
- tasks/website.rake
20
7
  test/test_classy-inheritance.rb
21
8
  test/test_helper.rb
22
- website/index.html
23
- website/index.txt
24
- website/javascripts/rounded_corners_lite.inc.js
25
- website/stylesheets/screen.css
26
- website/template.html.erb
9
+ test/test_polymorphic_associations.rb
10
+ test/test_with_optional_dependency.rb
11
+ test/test_with_prefix_postfix.rb
12
+ test/test_with_standard_attributes.rb
data/README.txt CHANGED
@@ -1,32 +1,37 @@
1
- = classy-inheritance
2
-
3
- * FIX (url)
1
+ classy-inheritance
2
+ by Andrew Stone
3
+ http://stonean.com
4
4
 
5
5
  == DESCRIPTION:
6
6
 
7
- FIX (describe your package)
8
-
9
- == FEATURES/PROBLEMS:
7
+ Classy Inheritance adds a depends_on class method to your ActiveRecord model so that you can define requisite objects.
10
8
 
11
- * FIX (list of features or problems)
9
+ This functionality is provided using the existing ActiveRecord methods without monkey patching any core code. Essentially, it provides an easy interface to generate code that anyone could add to their model to receive the same result. Depending on the parameters to your depends_on call, it may add some of the following methods: validates_presence_of, validates_associated, has_one or belongs_to.
12
10
 
13
11
  == SYNOPSIS:
14
12
 
15
- FIX (code sample of usage)
13
+ class User < ActiveRecord::Base
14
+ depends_on :profile, :attrs => [:first_name, :last_name, :email]
15
+ end
16
16
 
17
- == REQUIREMENTS:
17
+ # Pass-through methods to profile attributes. Now you don't have to manage
18
+ # two different objects.
19
+ @user.first_name = 'Andrew'
20
+ @user.last_name = 'Stone'
21
+ @user.email = 'andy@stonean.com'
18
22
 
19
- * FIX (list of requirements)
23
+ # Manages profile relationship for you
24
+ @user.save
20
25
 
21
26
  == INSTALL:
22
27
 
23
- * FIX (sudo gem install, anything else)
28
+ sudo gem install classy-inheritance
24
29
 
25
30
  == LICENSE:
26
31
 
27
32
  (The MIT License)
28
33
 
29
- Copyright (c) 2008 FIX
34
+ Copyright (c) 2009 Andrew Stone
30
35
 
31
36
  Permission is hereby granted, free of charge, to any person obtaining
32
37
  a copy of this software and associated documentation files (the
@@ -45,4 +50,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
50
  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
51
  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
52
  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
53
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,4 +1,30 @@
1
- require 'config/requirements'
2
- require 'config/hoe' # setup Hoe + all gem configuration
3
-
4
- Dir['tasks/**/*.rake'].each { |rake| load rake }
1
+ # Look in the tasks/setup.rb file for the various options that can be
2
+ # configured in this Rakefile. The .rake files in the tasks directory
3
+ # are where the options are used.
4
+
5
+ begin
6
+ require 'bones'
7
+ Bones.setup
8
+ rescue LoadError
9
+ begin
10
+ load 'tasks/setup.rb'
11
+ rescue LoadError
12
+ raise RuntimeError, '### please install the "bones" gem ###'
13
+ end
14
+ end
15
+
16
+ ensure_in_path 'lib'
17
+ require 'classy-inheritance'
18
+
19
+ task :default => 'spec:run'
20
+
21
+ PROJ.name = 'classy-inheritance'
22
+ PROJ.authors = 'Andrew Stone'
23
+ PROJ.email = 'andy@stonean.com'
24
+ PROJ.url = 'http://stonean.com/wiki/classy-inheritance'
25
+ PROJ.version = Stonean::ClassyInheritance::VERSION
26
+ PROJ.rubyforge.name = 'classyinherit'
27
+
28
+ PROJ.spec.opts << '--color'
29
+
30
+ # EOF
@@ -1,28 +1,10 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
-
4
-
5
- module ActiveRecord::Validations::ClassMethods
6
- def validates_associated(*attr_names)
7
- configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save }
8
- configuration.update(attr_names.extract_options!)
9
-
10
- validates_each(attr_names, configuration) do |record, attr_name, value|
11
- associate = record.send(attr_name)
12
- if associate && !associate.valid?
13
- associate.errors.each do |key, value|
14
- record.errors.add(key, value)
15
- end
16
- end
17
- end
18
- end
19
- end
20
-
21
1
 
22
2
  module Stonean
23
3
  module ClassyInheritance
24
- def self.included(base)
25
- base.extend Stonean::ClassyInheritance::ClassMethods
4
+ VERSION = '0.6.4'
5
+
6
+ def self.version
7
+ VERSION
26
8
  end
27
9
 
28
10
  module ClassMethods
@@ -40,10 +22,10 @@ module Stonean
40
22
 
41
23
  if options.has_key?(:validates_associated_if) && options[:validates_associated_if] != true
42
24
  if [Symbol, String, Proc].include?(options[:validates_associated_if].class)
43
- validates_associated model_sym, :if => options[:validates_associated_if]
25
+ validates_associated_dependent model_sym, options, :if => options[:validates_associated_if]
44
26
  end
45
27
  else
46
- validates_associated model_sym
28
+ validates_associated_dependent model_sym, options
47
29
  end
48
30
 
49
31
  # Before save functionality to create/update the requisite object
@@ -53,7 +35,7 @@ module Stonean
53
35
  define_find_with_method(model_sym)
54
36
 
55
37
  if options[:as]
56
- define_can_be_method_on_requisite_class(options[:class_name] || model_sym, options[:as])
38
+ define_can_be_method_on_requisite_class(options[:class_name] || model_sym.to_s.classify, options[:as])
57
39
  end
58
40
 
59
41
  options[:attrs].each{|attr| define_accessors(model_sym, attr, options)}
@@ -175,11 +157,11 @@ module Stonean
175
157
  end
176
158
 
177
159
  def define_can_be_method_on_requisite_class(model_sym, polymorphic_name)
178
- klass = model_sym.to_s.classify
160
+ klass = model_sym.to_s
179
161
  requisite_klass = eval(klass)
180
162
  unless requisite_klass.respond_to?(self.name.underscore.to_sym)
181
163
  requisite_klass.send :can_be, self.name.underscore,
182
- :as => polymorphic_name
164
+ :as => polymorphic_name
183
165
  end
184
166
  end
185
167
 
@@ -190,4 +172,32 @@ module Stonean
190
172
  end # ClassMethods
191
173
  end # ClassyInheritance module
192
174
  end # Stonean module
193
- ActiveRecord::Base.send :include, Stonean::ClassyInheritance
175
+
176
+ if Object.const_defined?("ActiveRecord") && ActiveRecord.const_defined?("Base")
177
+ module ActiveRecord::Validations::ClassMethods
178
+
179
+ def validates_associated_dependent(model_sym, options, configuration = {})
180
+ configuration = { :message => I18n.translate('activerecord.errors.messages.invalid'), :on => :save }.update(configuration)
181
+
182
+ validates_each(model_sym, configuration) do |record, attr_name, value|
183
+ associate = record.send(attr_name)
184
+ if associate && !associate.valid?
185
+ associate.errors.each do |key, value|
186
+ if options[:prefix]
187
+ key = (options[:prefix] == true) ? "#{model_sym}_#{key}" : "#{options[:prefix]}_#{key}"
188
+ end
189
+ if options[:postfix]
190
+ key = (options[:postfix] == true) ? "#{key}_#{model_sym}" : "#{key}_#{options[:postfix]}"
191
+ end
192
+ record.errors.add(key, value) unless record.errors[key]
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
198
+
199
+
200
+ ActiveRecord::Base.class_eval do
201
+ extend Stonean::ClassyInheritance::ClassMethods
202
+ end
203
+ end
@@ -0,0 +1,80 @@
1
+
2
+ begin
3
+ require 'bones/smtp_tls'
4
+ rescue LoadError
5
+ require 'net/smtp'
6
+ end
7
+ require 'time'
8
+
9
+ namespace :ann do
10
+
11
+ # A prerequisites task that all other tasks depend upon
12
+ task :prereqs
13
+
14
+ file PROJ.ann.file do
15
+ ann = PROJ.ann
16
+ puts "Generating #{ann.file}"
17
+ File.open(ann.file,'w') do |fd|
18
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
19
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
20
+ fd.puts(" #{PROJ.url}") if PROJ.url.valid?
21
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
22
+ fd.puts
23
+ fd.puts("== DESCRIPTION")
24
+ fd.puts
25
+ fd.puts(PROJ.description)
26
+ fd.puts
27
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
28
+ fd.puts
29
+ ann.paragraphs.each do |p|
30
+ fd.puts "== #{p.upcase}"
31
+ fd.puts
32
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
33
+ fd.puts
34
+ end
35
+ fd.puts ann.text if ann.text
36
+ end
37
+ end
38
+
39
+ desc "Create an announcement file"
40
+ task :announcement => ['ann:prereqs', PROJ.ann.file]
41
+
42
+ desc "Send an email announcement"
43
+ task :email => ['ann:prereqs', PROJ.ann.file] do
44
+ ann = PROJ.ann
45
+ from = ann.email[:from] || Array(PROJ.authors).first || PROJ.email
46
+ to = Array(ann.email[:to])
47
+
48
+ ### build a mail header for RFC 822
49
+ rfc822msg = "From: #{from}\n"
50
+ rfc822msg << "To: #{to.join(',')}\n"
51
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
52
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
53
+ rfc822msg << "\n"
54
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
55
+ rfc822msg << "Message-Id: "
56
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
57
+ rfc822msg << File.read(ann.file)
58
+
59
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
60
+ ann.email[key]
61
+ end
62
+
63
+ params[3] = PROJ.email if params[3].nil?
64
+
65
+ if params[4].nil?
66
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
67
+ params[4] = STDIN.gets.chomp
68
+ end
69
+
70
+ ### send email
71
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
72
+ end
73
+ end # namespace :ann
74
+
75
+ desc 'Alias to ann:announcement'
76
+ task :ann => 'ann:announcement'
77
+
78
+ CLOBBER << PROJ.ann.file
79
+
80
+ # EOF
@@ -0,0 +1,20 @@
1
+
2
+ if HAVE_BONES
3
+
4
+ namespace :bones do
5
+
6
+ desc 'Show the PROJ open struct'
7
+ task :debug do |t|
8
+ atr = if t.application.top_level_tasks.length == 2
9
+ t.application.top_level_tasks.pop
10
+ end
11
+
12
+ if atr then Bones::Debug.show_attr(PROJ, atr)
13
+ else Bones::Debug.show PROJ end
14
+ end
15
+
16
+ end # namespace :bones
17
+
18
+ end # HAVE_BONES
19
+
20
+ # EOF
@@ -0,0 +1,201 @@
1
+
2
+ require 'find'
3
+ require 'rake/packagetask'
4
+ require 'rubygems/user_interaction'
5
+ require 'rubygems/builder'
6
+
7
+ module Bones
8
+ class GemPackageTask < Rake::PackageTask
9
+ # Ruby GEM spec containing the metadata for this package. The
10
+ # name, version and package_files are automatically determined
11
+ # from the GEM spec and don't need to be explicitly provided.
12
+ #
13
+ attr_accessor :gem_spec
14
+
15
+ # Tasks from the Bones gem directory
16
+ attr_reader :bones_files
17
+
18
+ # Create a GEM Package task library. Automatically define the gem
19
+ # if a block is given. If no block is supplied, then +define+
20
+ # needs to be called to define the task.
21
+ #
22
+ def initialize(gem_spec)
23
+ init(gem_spec)
24
+ yield self if block_given?
25
+ define if block_given?
26
+ end
27
+
28
+ # Initialization tasks without the "yield self" or define
29
+ # operations.
30
+ #
31
+ def init(gem)
32
+ super(gem.name, gem.version)
33
+ @gem_spec = gem
34
+ @package_files += gem_spec.files if gem_spec.files
35
+ @bones_files = []
36
+
37
+ local_setup = File.join(Dir.pwd, %w[tasks setup.rb])
38
+ if !test(?e, local_setup)
39
+ Dir.glob(::Bones.path(%w[lib bones tasks *])).each {|fn| bones_files << fn}
40
+ end
41
+ end
42
+
43
+ # Create the Rake tasks and actions specified by this
44
+ # GemPackageTask. (+define+ is automatically called if a block is
45
+ # given to +new+).
46
+ #
47
+ def define
48
+ super
49
+ task :prereqs
50
+ task :package => ['gem:prereqs', "#{package_dir_path}/#{gem_file}"]
51
+ file "#{package_dir_path}/#{gem_file}" => [package_dir_path] + package_files + bones_files do
52
+ when_writing("Creating GEM") {
53
+ chdir(package_dir_path) do
54
+ Gem::Builder.new(gem_spec).build
55
+ verbose(true) {
56
+ mv gem_file, "../#{gem_file}"
57
+ }
58
+ end
59
+ }
60
+ end
61
+
62
+ file package_dir_path => bones_files do
63
+ mkdir_p package_dir rescue nil
64
+
65
+ gem_spec.files = (gem_spec.files +
66
+ bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
67
+
68
+ bones_files.each do |fn|
69
+ base_fn = File.join('tasks', File.basename(fn))
70
+ f = File.join(package_dir_path, base_fn)
71
+ fdir = File.dirname(f)
72
+ mkdir_p(fdir) if !File.exist?(fdir)
73
+ if File.directory?(fn)
74
+ mkdir_p(f)
75
+ else
76
+ raise "file name conflict for '#{base_fn}' (conflicts with '#{fn}')" if test(?e, f)
77
+ safe_ln(fn, f)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ def gem_file
84
+ if @gem_spec.platform == Gem::Platform::RUBY
85
+ "#{package_name}.gem"
86
+ else
87
+ "#{package_name}-#{@gem_spec.platform}.gem"
88
+ end
89
+ end
90
+ end # class GemPackageTask
91
+ end # module Bones
92
+
93
+ namespace :gem do
94
+
95
+ PROJ.gem._spec = Gem::Specification.new do |s|
96
+ s.name = PROJ.name
97
+ s.version = PROJ.version
98
+ s.summary = PROJ.summary
99
+ s.authors = Array(PROJ.authors)
100
+ s.email = PROJ.email
101
+ s.homepage = Array(PROJ.url).first
102
+ s.rubyforge_project = PROJ.rubyforge.name
103
+
104
+ s.description = PROJ.description
105
+
106
+ PROJ.gem.dependencies.each do |dep|
107
+ s.add_dependency(*dep)
108
+ end
109
+
110
+ PROJ.gem.development_dependencies.each do |dep|
111
+ s.add_development_dependency(*dep)
112
+ end
113
+
114
+ s.files = PROJ.gem.files
115
+ s.executables = PROJ.gem.executables.map {|fn| File.basename(fn)}
116
+ s.extensions = PROJ.gem.files.grep %r/extconf\.rb$/
117
+
118
+ s.bindir = 'bin'
119
+ dirs = Dir["{#{PROJ.libs.join(',')}}"]
120
+ s.require_paths = dirs unless dirs.empty?
121
+
122
+ incl = Regexp.new(PROJ.rdoc.include.join('|'))
123
+ excl = PROJ.rdoc.exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
124
+ excl = Regexp.new(excl.join('|'))
125
+ rdoc_files = PROJ.gem.files.find_all do |fn|
126
+ case fn
127
+ when excl; false
128
+ when incl; true
129
+ else false end
130
+ end
131
+ s.rdoc_options = PROJ.rdoc.opts + ['--main', PROJ.rdoc.main]
132
+ s.extra_rdoc_files = rdoc_files
133
+ s.has_rdoc = true
134
+
135
+ if test ?f, PROJ.test.file
136
+ s.test_file = PROJ.test.file
137
+ else
138
+ s.test_files = PROJ.test.files.to_a
139
+ end
140
+
141
+ # Do any extra stuff the user wants
142
+ PROJ.gem.extras.each do |msg, val|
143
+ case val
144
+ when Proc
145
+ val.call(s.send(msg))
146
+ else
147
+ s.send "#{msg}=", val
148
+ end
149
+ end
150
+ end # Gem::Specification.new
151
+
152
+ Bones::GemPackageTask.new(PROJ.gem._spec) do |pkg|
153
+ pkg.need_tar = PROJ.gem.need_tar
154
+ pkg.need_zip = PROJ.gem.need_zip
155
+ end
156
+
157
+ desc 'Show information about the gem'
158
+ task :debug => 'gem:prereqs' do
159
+ puts PROJ.gem._spec.to_ruby
160
+ end
161
+
162
+ desc 'Write the gemspec '
163
+ task :spec => 'gem:prereqs' do
164
+ File.open("#{PROJ.name}.gemspec", 'w') do |f|
165
+ f.write PROJ.gem._spec.to_ruby
166
+ end
167
+ end
168
+
169
+ desc 'Install the gem'
170
+ task :install => [:clobber, 'gem:package'] do
171
+ sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
172
+
173
+ # use this version of the command for rubygems > 1.0.0
174
+ #sh "#{SUDO} #{GEM} install --no-update-sources pkg/#{PROJ.gem._spec.full_name}"
175
+ end
176
+
177
+ desc 'Uninstall the gem'
178
+ task :uninstall do
179
+ installed_list = Gem.source_index.find_name(PROJ.name)
180
+ if installed_list and installed_list.collect { |s| s.version.to_s}.include?(PROJ.version) then
181
+ sh "#{SUDO} #{GEM} uninstall --version '#{PROJ.version}' --ignore-dependencies --executables #{PROJ.name}"
182
+ end
183
+ end
184
+
185
+ desc 'Reinstall the gem'
186
+ task :reinstall => [:uninstall, :install]
187
+
188
+ desc 'Cleanup the gem'
189
+ task :cleanup do
190
+ sh "#{SUDO} #{GEM} cleanup #{PROJ.gem._spec.name}"
191
+ end
192
+ end # namespace :gem
193
+
194
+
195
+ desc 'Alias to gem:package'
196
+ task :gem => 'gem:package'
197
+
198
+ task :clobber => 'gem:clobber_package'
199
+ remove_desc_for_task 'gem:clobber_package'
200
+
201
+ # EOF