has_emails 0.0.1

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/CHANGELOG ADDED
@@ -0,0 +1,23 @@
1
+ *SVN*
2
+
3
+ *0.0.1* (September 26th, 2007)
4
+
5
+ * Refactor has_email_address/has_email_addresses so that new associations for unsent/sent emails isn't created for has_email_address
6
+
7
+ * Add state changes fixtures for tests
8
+
9
+ * Add tests for ApplicationMailer
10
+
11
+ * Add support for tracking the original email address for senders/recipients even if the email address changes on the associated model (i.e. EmailAddress/User/etc.)
12
+
13
+ * Support converting models with an email_address/email_addresses association
14
+
15
+ * Allow the sender of emails to be an arbitrary string email address
16
+
17
+ * Add documentation
18
+
19
+ * Move test fixtures out of the test application root directory
20
+
21
+ * Convert dos newlines to unix newlines
22
+
23
+ * Update against latest changes to has_messages
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006-2007 Aaron Pfeifer & Neil Abraham
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,130 @@
1
+ = has_emails
2
+
3
+ +has_emails+ adds support for emailing capabilities between ActiveRecord models.
4
+
5
+ == Resources
6
+
7
+ API
8
+
9
+ * http://api.pluginaweek.org/has_emails
10
+
11
+ Wiki
12
+
13
+ * http://wiki.pluginaweek.org/Has_emails
14
+
15
+ Announcement
16
+
17
+ * http://www.pluginaweek.org
18
+
19
+ Source
20
+
21
+ * http://svn.pluginaweek.org/trunk/plugins/active_record/has/has_emails
22
+
23
+ Development
24
+
25
+ * http://dev.pluginaweek.org/browser/trunk/plugins/active_record/has/has_emails
26
+
27
+ == Description
28
+
29
+ Emailing between users and other parts of a system is a fairly common feature in
30
+ web applications, especially for those that support social networking. Emailing
31
+ doesn't necessarily need to be between users, but can also act as a way for the
32
+ web application to send notices and other notifications to users.
33
+
34
+ Rails already provides ActionMailer as a way of sending emails. However, the
35
+ framework does not provide an easy way to persist emails, track their status, and
36
+ process them asynchronously. Designing and building this type of framework can
37
+ become complex and cumbersome and takes away from the focus of the web application.
38
+ This plugin helps ease that process by providing a complete implementation for
39
+ sending and receiving emails to and between models in your application.
40
+
41
+ == Usage
42
+
43
+ === Adding emailing support
44
+
45
+ If you want to use the built-in support for email addresses (using the EmailAddress
46
+ model), you can add emailing support for users like so:
47
+
48
+ class User < ActiveRecord::Base
49
+ has_email_address
50
+ # has_email_addresses if you want to support multiple addresses
51
+ end
52
+
53
+ On the other hand, if you already have the email address for users stored as a
54
+ column in your users table, you can add emailing support like so:
55
+
56
+ class User < ActiveRecord::Base
57
+ has_messages :emails,
58
+ :message_class => 'Email'
59
+ end
60
+
61
+ === Creating new emails
62
+
63
+ email = user.emails.build
64
+ email.to << [user1, email_address1, 'someone@somewhere.com']
65
+ email.subject = 'Hey!'
66
+ email.body = 'Does anyone want to go out tonight?'
67
+ email.deliver!
68
+
69
+ As can be seen in the above example, you can use Users, EmailAddresses, or even
70
+ Strings as recipients in emails. Each will be automatically converted to the
71
+ EmailRecipient class so that it can be stored in the database.
72
+
73
+ === Replying to emails
74
+
75
+ reply = email.reply_to_all
76
+ reply.body = "I'd love to go out!"
77
+ reply.deliver!
78
+
79
+ === Forwarding emails
80
+
81
+ forward = email.forward
82
+ forward.body = 'Interested?'
83
+ forward.deliver!
84
+
85
+ === External process messaging
86
+
87
+ In addition to delivering emails immediately, you can also *queue* emails so
88
+ that an external application processes and delivers them. This is especially
89
+ useful when you want to asynchronously send e-mails so that it doesn't block the
90
+ user interface on your web application.
91
+
92
+ To queue emails for external processing, you can simply use the <tt>queue!</tt>
93
+ event, rather than <tt>deliver!</tt>. This will indicate to any external processes
94
+ that the email is ready to be sent. The external process can then invoke <tt>deliver!</tt>
95
+ whenever it is ready to send the queued email.
96
+
97
+ === Running migrations
98
+
99
+ To migrate the tables required for this plugin, you can either run the
100
+ migration from the command line like so:
101
+
102
+ rake db:migrate:plugins PLUGIN=has_emails
103
+
104
+ or (more ideally) generate a migration file that will integrate into your main
105
+ application's migration path:
106
+
107
+ ruby script/generate plugin_migration has_emails
108
+
109
+ == Testing
110
+
111
+ Before you can run any tests, the following gems must be installed:
112
+ * plugin_test_helper[http://wiki.pluginaweek.org/Plugin_test_helper]
113
+ * dry_validity_assertions[http://wiki.pluginaweek.org/Dry_validity_assertions]
114
+
115
+ == Dependencies
116
+
117
+ This plugin depends on the presence of the following plugins:
118
+ * has_messages[http://wiki.pluginaweek.org/Has_messages]
119
+
120
+ This plugin is also a plugin+. That means that it contains a slice of an
121
+ application, such as models and migrations. To test or use a plugin+, you
122
+ must have the following plugins/gems installed:
123
+ * plugin_dependencies[http://wiki.pluginaweek.org/Plugin_dependencies]
124
+ * loaded_plugins[http://wiki.pluginaweek.org/Loaded_plugins]
125
+ * appable_plugins[http://wiki.pluginaweek.org/Appable_plugins]
126
+ * plugin_migrations[http://wiki.pluginaweek.org/Plugin_migrations]
127
+
128
+ Instead of installing each individual plugin+ feature, you can install them all
129
+ at once using the plugins+[http://wiki.pluginaweek.org/Plugins_plus] meta package,
130
+ which contains all additional features.
data/Rakefile ADDED
@@ -0,0 +1,81 @@
1
+ require 'rake/testtask'
2
+ require 'rake/rdoctask'
3
+ require 'rake/gempackagetask'
4
+ require 'rake/contrib/sshpublisher'
5
+
6
+ PKG_NAME = 'has_emails'
7
+ PKG_VERSION = '0.0.1'
8
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
9
+ RUBY_FORGE_PROJECT = 'pluginaweek'
10
+
11
+ desc 'Default: run unit tests.'
12
+ task :default => :test
13
+
14
+ desc 'Test the has_emails plugin.'
15
+ Rake::TestTask.new(:test) do |t|
16
+ t.libs << 'lib'
17
+ t.pattern = 'test/**/*_test.rb'
18
+ t.verbose = true
19
+ end
20
+
21
+ desc 'Generate documentation for the has_emails plugin.'
22
+ Rake::RDocTask.new(:rdoc) do |rdoc|
23
+ rdoc.rdoc_dir = 'rdoc'
24
+ rdoc.title = 'HasEmails'
25
+ rdoc.options << '--line-numbers' << '--inline-source'
26
+ rdoc.rdoc_files.include('README')
27
+ rdoc.rdoc_files.include('lib/**/*.rb')
28
+ end
29
+
30
+ spec = Gem::Specification.new do |s|
31
+ s.name = PKG_NAME
32
+ s.version = PKG_VERSION
33
+ s.platform = Gem::Platform::RUBY
34
+ s.summary = 'Adds support for emailing capabilities between ActiveRecord models.'
35
+
36
+ s.files = FileList['{app,db,lib,test}/**/*'].to_a + %w(CHANGELOG init.rb MIT-LICENSE Rakefile README)
37
+ s.require_path = 'lib'
38
+ s.autorequire = 'has_emails'
39
+ s.has_rdoc = true
40
+ s.test_files = Dir['test/**/*_test.rb']
41
+ s.add_dependency 'has_messages', '>= 0.0.1'
42
+ s.add_dependency 'validates_as_email_address', '>= 0.0.1'
43
+
44
+ s.author = 'Aaron Pfeifer, Neil Abraham'
45
+ s.email = 'info@pluginaweek.org'
46
+ s.homepage = 'http://www.pluginaweek.org'
47
+ end
48
+
49
+ Rake::GemPackageTask.new(spec) do |p|
50
+ p.gem_spec = spec
51
+ p.need_tar = true
52
+ p.need_zip = true
53
+ end
54
+
55
+ desc 'Publish the beta gem'
56
+ task :pgem => [:package] do
57
+ Rake::SshFilePublisher.new('pluginaweek@pluginaweek.org', '/home/pluginaweek/gems.pluginaweek.org/gems', 'pkg', "#{PKG_FILE_NAME}.gem").upload
58
+ end
59
+
60
+ desc 'Publish the API documentation'
61
+ task :pdoc => [:rdoc] do
62
+ Rake::SshDirPublisher.new('pluginaweek@pluginaweek.org', "/home/pluginaweek/api.pluginaweek.org/#{PKG_NAME}", 'rdoc').upload
63
+ end
64
+
65
+ desc 'Publish the API docs and gem'
66
+ task :publish => [:pdoc, :release]
67
+
68
+ desc 'Publish the release files to RubyForge.'
69
+ task :release => [:gem, :package] do
70
+ require 'rubyforge'
71
+
72
+ ruby_forge = RubyForge.new
73
+ ruby_forge.login
74
+
75
+ %w( gem tgz zip ).each do |ext|
76
+ file = "pkg/#{PKG_FILE_NAME}.#{ext}"
77
+ puts "Releasing #{File.basename(file)}..."
78
+
79
+ ruby_forge.add_release(RUBY_FORGE_PROJECT, PKG_NAME, PKG_VERSION, file)
80
+ end
81
+ end
@@ -0,0 +1,85 @@
1
+ # Provides base operations for emailing
2
+ class ApplicationMailer < ActionMailer::Base
3
+ @@default_subject_prefix = "[#{File.basename(File.expand_path(RAILS_ROOT)).camelize}] "
4
+ cattr_accessor :default_subject_prefix
5
+
6
+ # Specify the prefix to use for the subject. This defaults to the
7
+ # +default_subject_prefix+ specified for ApplicationMailer.
8
+ adv_attr_accessor :subject_prefix
9
+
10
+ class << self
11
+ def method_missing(method_symbol, *parameters) #:nodoc:
12
+ case method_symbol.id2name
13
+ when /^queue_([_a-z]\w*)/ then new($1, *parameters).queue
14
+ else super
15
+ end
16
+ end
17
+ end
18
+
19
+ alias_method :to, :recipients
20
+
21
+ # Sets or gets the subject of the email. All subjects are prefixed with a
22
+ # value indicating the application it is coming from.
23
+ def subject(*parameters)
24
+ if parameters.empty?
25
+ super
26
+ else
27
+ super(subject_prefix + super)
28
+ end
29
+ end
30
+ alias_method :subject=, :subject
31
+
32
+ # Delivers an email based on the content in the specified email
33
+ def email(email)
34
+ @from = email.sender
35
+ @recipients = email.to
36
+ @cc = email.cc
37
+ @bcc = email.bcc
38
+ @subject = email.subject
39
+ @body = email.body
40
+ @sent_on = email.sent_at || Time.now
41
+ end
42
+
43
+ # Queues the current e-mail that has been constructed
44
+ def queue
45
+ Email.transaction do
46
+ # Create the main email
47
+ email = Email.create!(
48
+ :sender => from,
49
+ :subject => subject,
50
+ :body => body
51
+ )
52
+
53
+ # Add recipients
54
+ email.to = [to].flatten
55
+ email.cc = [cc].flatten
56
+ email.bcc = [bcc].flatten
57
+ email.queue!
58
+ end
59
+ end
60
+
61
+ private
62
+ def initialize_defaults(method_name) #:nodoc
63
+ @sent_on ||= Time.now
64
+ @subject_prefix ||= @@default_subject_prefix.dup
65
+ @recipients ||= []
66
+ @cc ||= []
67
+ @bcc ||= []
68
+
69
+ super
70
+ end
71
+
72
+ def quote_address_if_necessary_with_conversion(address, charset) #:nodoc
73
+ # Uses is_a? instead of === because of AssociationProxy
74
+ if !address.is_a?(Array)
75
+ if EmailAddress === address || EmailRecipient === address
76
+ address = address.with_name
77
+ elsif !(String === address)
78
+ address = EmailAddress.convert_from(address).to_s
79
+ end
80
+ end
81
+
82
+ quote_address_if_necessary_without_conversion(address, charset)
83
+ end
84
+ alias_method_chain :quote_address_if_necessary, :conversion
85
+ end
@@ -0,0 +1,84 @@
1
+ # Represents an email which has been sent to one or more recipients. This is
2
+ # essentially the same as the Message class, but overrides the +to+, +cc+, and +bcc+
3
+ # associations to that proper instances of the MessageRecipient class are created.
4
+ class Email < Message
5
+ validates_presence_of :sender_spec
6
+ validates_as_email_address :sender_spec,
7
+ :allow_nil => true
8
+
9
+ with_options(
10
+ :class_name => 'EmailRecipient',
11
+ :foreign_key => 'message_id',
12
+ :order => 'position ASC',
13
+ :dependent => true
14
+ ) do |e|
15
+ e.has_many :to,
16
+ :conditions => ['kind = ?', 'to'],
17
+ :extend => [MessageRecipientToBuildExtension, EmailRecipientBuildExtension]
18
+ e.has_many :cc,
19
+ :conditions => ['kind = ?', 'cc'],
20
+ :extend => [MessageRecipientCcBuildExtension, EmailRecipientBuildExtension]
21
+ e.has_many :bcc,
22
+ :conditions => ['kind = ?', 'bcc'],
23
+ :extend => [MessageRecipientBccBuildExtension, EmailRecipientBuildExtension]
24
+ end
25
+
26
+ # Returns the sender of the message. This can be a string if being sent
27
+ # from an arbitrary e-mail address.
28
+ def sender_with_spec
29
+ sender_without_spec || sender_spec
30
+ end
31
+ alias_method_chain :sender, :spec
32
+
33
+ # If sender is a string, then sets the spec, otherwise uses the original
34
+ # sender setter
35
+ def sender_with_spec=(value)
36
+ self.sender_spec = EmailAddress.convert_from(value).spec
37
+ self.sender_without_spec = value if !value.is_a?(String)
38
+ end
39
+ alias_method_chain :sender=, :spec
40
+
41
+ # Converts the sender into an Email Address, whether it be a string,
42
+ # EmailAddress, or other model type
43
+ def sender_email_address
44
+ EmailAddress.convert_from(sender_spec)
45
+ end
46
+
47
+ # The name of the person whose sending the email
48
+ def sender_name
49
+ sender_without_spec ? EmailAddress.convert_from(sender_without_spec).name : sender_email_address.name
50
+ end
51
+
52
+ # Returns a string version of the email address plus any name like
53
+ # "John Doe <john.doe@gmail.com>"..
54
+ def sender_with_name
55
+ address = self.email_address
56
+ address.name = self.name
57
+ address.with_name
58
+ end
59
+
60
+ # Actually delivers the email to the recipients
61
+ def deliver
62
+ ApplicationMailer.deliver_email(self)
63
+ end
64
+
65
+ # Saves the +sender_spec+ in the forwarded message
66
+ def forward
67
+ message = super
68
+ message.sender_spec = sender_spec
69
+ message
70
+ end
71
+
72
+ # Saves the +sender_spec+ in the replied message
73
+ def reply
74
+ message = super
75
+ message.sender_spec = sender_spec
76
+ message
77
+ end
78
+
79
+ private
80
+ # Strings are allowed to participate in messaging
81
+ def model_participant?
82
+ sender_id && sender_type || sender_spec.nil?
83
+ end
84
+ end
@@ -0,0 +1,123 @@
1
+ # Represents a valid RFC822 email address
2
+ class EmailAddress < ActiveRecord::Base
3
+ class << self
4
+ # Converts the specified record to an EmailAddress. It will convert the
5
+ # following types:
6
+ # 1. String
7
+ # 2. A record with an +email_address+ String attribute
8
+ # 3. A record with an +email_address+ association
9
+ # 4. A record with an +email_addresses+ association (first record will be chosen)
10
+ #
11
+ # If an EmailAddress is specified, the same model will be returned. An
12
+ # ArgumentError is raised if it doesn't match any of the above criteria.
13
+ def convert_from(record)
14
+ if record
15
+ if EmailAddress === record
16
+ record
17
+ elsif String === record
18
+ EmailAddress.new(:spec => record)
19
+ elsif record.respond_to?(:email_address)
20
+ if record.email_address.is_a?(String)
21
+ address = EmailAddress.new(:spec => record.email_address)
22
+ address.name = record.name if record.respond_to?(:name)
23
+ address
24
+ else
25
+ record.email_address
26
+ end
27
+ elsif record.respond_to?(:email_addresses)
28
+ record.email_addresses.first
29
+ else
30
+ raise ArgumentError, "Cannot convert #{record.class} to an EmailAddress"
31
+ end
32
+ end
33
+ end
34
+
35
+ # Determines if the given spec is a valid address using the RFC822 spec
36
+ def valid?(spec)
37
+ !RFC822::EmailAddress.match(spec).nil?
38
+ end
39
+ end
40
+
41
+ acts_as_tokenized :token_field => 'verification_code', :token_length => 32
42
+
43
+ # Support e-mail address verification
44
+ has_states :initial => :unverified
45
+
46
+ # Add messaging capabilities. This will give us an email_box.
47
+ has_messages :emails,
48
+ :message_class => 'Email'
49
+ belongs_to :emailable,
50
+ :polymorphic => true
51
+
52
+ validates_presence_of :spec
53
+
54
+ with_options(:allow_nil => true) do |klass|
55
+ klass.validates_uniqueness_of :spec
56
+ klass.validates_as_email_address :spec
57
+ end
58
+
59
+ # The name of the person who owns this email address
60
+ attr_accessor :name
61
+
62
+ # Ensure that the e-mail address has a verification code that can be sent
63
+ # to the user
64
+ before_create :set_code_expiry
65
+
66
+ state :unverified, :verified
67
+
68
+ # Verifies that the email address is valid
69
+ event :verify do
70
+ transition_to :verified, :from => :unverified
71
+ end
72
+
73
+ # Sets the full address
74
+ def spec=(new_spec)
75
+ @local_name = @domain = nil
76
+ write_attribute(:spec, new_spec)
77
+ end
78
+
79
+ # The part of the e-mail address before the @
80
+ def local_name
81
+ parse_spec if !@local_name
82
+ @local_name
83
+ end
84
+
85
+ # The part of the e-mail address after the @
86
+ def domain
87
+ parse_spec if !@domain
88
+ @domain
89
+ end
90
+
91
+ # Gets the name of the person whose email address this is. Default is an
92
+ # empty string. Override this if you want it to appear in with_name
93
+ def name
94
+ @name || ''
95
+ end
96
+
97
+ # Returns a string version of the email address plus any name like
98
+ # "John Doe <john.doe@gmail.com>". In order to have a valid name within the
99
+ # string, you must override +name+.
100
+ def with_name
101
+ name.blank? ? to_s : "#{name} <#{to_s}>"
102
+ end
103
+
104
+ # Returns the full email address (without the name)
105
+ def to_s #:nodoc
106
+ spec
107
+ end
108
+
109
+ private
110
+ # Sets the time at which the verification code will expire
111
+ def set_code_expiry
112
+ self.code_expiry = 48.hour.from_now
113
+ end
114
+
115
+ # Parses the current spec and sets +@local_name+ and +@domain+ based on the
116
+ # matching groups within the regular expression
117
+ def parse_spec
118
+ if !@local_name && !@domain && match = RFC822::EmailAddress.match(spec)
119
+ @local_name = match.captures[0]
120
+ @domain = match.captures[1]
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,78 @@
1
+ # Represents a recipient on an email
2
+ class EmailRecipient < MessageRecipient
3
+ validates_presence_of :receiver_spec
4
+ validates_as_email_address :receiver_spec,
5
+ :allow_nil => true
6
+
7
+ before_save :ensure_exclusive_references
8
+
9
+ # Alias for domain-specific language
10
+ alias_method :email, :message
11
+ alias_method :email=, :message=
12
+ alias_attribute :email_id, :message_id
13
+
14
+ delegate :to_s,
15
+ :to => :email_address
16
+
17
+ # Returns the receiver of the message. This can be a string if being sent
18
+ # to an arbitrary e-mail address.
19
+ def receiver_with_spec
20
+ receiver_without_spec || receiver_spec
21
+ end
22
+ alias_method_chain :receiver, :spec
23
+
24
+ # If receiver is a string, then sets the spec, otherwise uses the original
25
+ # receiver setter
26
+ def receiver_with_spec=(value)
27
+ self.receiver_spec = EmailAddress.convert_from(value).spec
28
+ self.receiver_without_spec = value if !value.is_a?(String)
29
+ end
30
+ alias_method_chain :receiver=, :spec
31
+
32
+ # Converts the receiver into an Email Address, whether it be a string,
33
+ # EmailAddress, or other model type
34
+ def email_address
35
+ EmailAddress.convert_from(receiver_spec)
36
+ end
37
+
38
+ # The name of the person whose receiving the email
39
+ def name
40
+ receiver_without_spec ? EmailAddress.convert_from(receiver_without_spec).name : email_address.name
41
+ end
42
+
43
+ # Returns a string version of the email address plus any name like
44
+ # "John Doe <john.doe@gmail.com>"..
45
+ def with_name
46
+ address = self.email_address
47
+ address.name = self.name
48
+ address.with_name
49
+ end
50
+
51
+ private
52
+ def validate_on_create #:nodoc:
53
+ begin
54
+ email_address if receiver
55
+ true
56
+ rescue ArgumentError
57
+ errors.add 'receiver_id', 'must be a string, have a email_address attribute, or be a class that has_email_addresses'
58
+ end
59
+ end
60
+
61
+ # Strings are allowed to participate in messaging
62
+ def model_participant?
63
+ receiver_id && receiver_type || receiver_spec.nil?
64
+ end
65
+
66
+ # Ensures that the country id/user region combo is not set at the same time as
67
+ # the region id
68
+ def ensure_exclusive_references
69
+ if model_participant?
70
+ self.receiver_spec = nil
71
+ else
72
+ self.receiver_id = nil
73
+ self.receiver_type = nil
74
+ end
75
+
76
+ true
77
+ end
78
+ end
@@ -0,0 +1,7 @@
1
+ module EmailRecipientBuildExtension #:nodoc:
2
+ # Checks if the recipient and record are equal, using the recipient's
3
+ # email_address
4
+ def is_recipient_equal?(recipient, record) #:nodoc:
5
+ recipient.email_address.to_s == EmailAddress.convert_from(record).to_s
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ verify:
2
+ id: 601
3
+ name: verify
4
+ owner_type: EmailAddress
@@ -0,0 +1,9 @@
1
+ unverified:
2
+ id: 601
3
+ name: unverified
4
+ owner_type: EmailAddress
5
+
6
+ verified:
7
+ id: 602
8
+ name: verified
9
+ owner_type: EmailAddress
@@ -0,0 +1,23 @@
1
+ class CreateEmailAddresses < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :email_addresses do |t|
4
+ t.column :emailable_id, :integer, :null => false, :references => nil
5
+ t.column :emailable_type, :string, :null => false
6
+ t.column :spec, :string, :null => false, :limit => 382
7
+ t.column :verification_code, :string, :limit => 40
8
+ t.column :code_expiry, :datetime
9
+ t.column :created_at, :timestamp, :null => false
10
+ t.column :updated_at, :datetime, :null => false
11
+ end
12
+ add_index :email_addresses, :spec, :unique => true
13
+ add_index :email_addresses, :verification_code, :unique => true
14
+
15
+ PluginAWeek::Has::States.migrate_up(:email_addresses)
16
+ end
17
+
18
+ def self.down
19
+ PluginAWeek::Has::States.migrate_down(:email_addresses)
20
+
21
+ drop_table :email_addresses
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ class AddEmailSpecs < ActiveRecord::Migration
2
+ def self.up
3
+ # Workaround change_column not allowing change to :null => true
4
+ remove_column :messages, :sender_id
5
+ remove_column :messages, :sender_type
6
+
7
+ add_column :messages, :sender_id, :integer, :null => true, :default => nil, :references => nil
8
+ add_column :messages, :sender_type, :string, :null => true, :default => nil
9
+ add_column :messages, :sender_spec, :string, :limit => 320
10
+ end
11
+
12
+ def self.down
13
+ remove_column :messages, :sender_spec
14
+
15
+ change_column :messages, :sender_id, :integer, :null => false, :references => nil
16
+ change_column :messages, :sender_type, :string, :null => false
17
+ end
18
+ end