contactable 0.1.0 → 1.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.
Files changed (110) hide show
  1. data/CHANGELOG +2 -0
  2. data/Manifest +94 -14
  3. data/README.rdoc +27 -1
  4. data/Rakefile +1 -1
  5. data/app/controllers/addresses_controller.rb +3 -0
  6. data/app/controllers/cities_controller.rb +16 -0
  7. data/app/controllers/contact_field_actions.rb +60 -0
  8. data/app/controllers/divisions_controller.rb +17 -0
  9. data/app/controllers/emails_controller.rb +3 -0
  10. data/app/controllers/identifications_controller.rb +3 -0
  11. data/app/controllers/instant_messengers_controller.rb +3 -0
  12. data/app/controllers/phones_controller.rb +3 -0
  13. data/app/controllers/websites_controller.rb +3 -0
  14. data/app/helpers/contactable_helper.rb +46 -0
  15. data/app/models/address.rb +96 -0
  16. data/app/models/address_type.rb +5 -0
  17. data/app/models/city.rb +21 -0
  18. data/app/models/country.rb +8 -0
  19. data/app/models/division.rb +26 -0
  20. data/{generators/contactable/templates → app}/models/email.rb +0 -0
  21. data/app/models/email_type.rb +5 -0
  22. data/app/models/identification.rb +7 -0
  23. data/app/models/identification_type.rb +5 -0
  24. data/{generators/contactable/templates → app}/models/instant_messenger.rb +0 -0
  25. data/{generators/contactable/templates → app}/models/instant_messenger_protocol.rb +2 -2
  26. data/{generators/contactable/templates → app}/models/instant_messenger_type.rb +3 -3
  27. data/{generators/contactable/templates → app}/models/phone.rb +0 -0
  28. data/app/models/phone_type.rb +5 -0
  29. data/{generators/contactable/templates → app}/models/province.rb +0 -0
  30. data/{generators/contactable/templates → app}/models/website.rb +0 -0
  31. data/app/models/website_type.rb +5 -0
  32. data/app/views/addresses/_address.html.erb +31 -0
  33. data/app/views/cities/index.html.erb +6 -0
  34. data/app/views/contactable/_contactable.html.erb +11 -0
  35. data/app/views/contactable/_contactable_field.html.erb +8 -0
  36. data/app/views/contactable/_fields.html.erb +49 -0
  37. data/app/views/divisions/index.html.erb +9 -0
  38. data/app/views/emails/_email.html.erb +2 -0
  39. data/app/views/identifications/_identification.html.erb +2 -0
  40. data/app/views/instant_messengers/_instant_messenger.html.erb +3 -0
  41. data/app/views/phones/_phone.html.erb +2 -0
  42. data/app/views/websites/_website.html.erb +2 -0
  43. data/config/contactable_routes.rb +4 -0
  44. data/contactable.gemspec +5 -5
  45. data/generators/contactable/USAGE +1 -10
  46. data/generators/contactable/contactable_generator.rb +35 -32
  47. data/generators/contactable/lib/insert_commands.rb +33 -0
  48. data/generators/contactable/templates/README +12 -0
  49. data/generators/contactable/templates/migrations/create_contactable_related_tables.rb +153 -26
  50. data/generators/contactable_views/USAGE +1 -0
  51. data/generators/contactable_views/contactable_views_generator.rb +24 -0
  52. data/generators/contactable_views/templates/views/formtastic/addresses/_address.html.erb +31 -0
  53. data/generators/contactable_views/templates/views/formtastic/cities/index.html.erb +6 -0
  54. data/generators/contactable_views/templates/views/formtastic/contactable/_contactable.html.erb +11 -0
  55. data/generators/contactable_views/templates/views/formtastic/contactable/_contactable_field.html.erb +8 -0
  56. data/generators/contactable_views/templates/views/formtastic/contactable/_fields.html.erb +49 -0
  57. data/generators/contactable_views/templates/views/formtastic/divisions/index.html.erb +9 -0
  58. data/generators/contactable_views/templates/views/formtastic/emails/_email.html.erb +2 -0
  59. data/generators/contactable_views/templates/views/formtastic/identifications/_identification.html.erb +2 -0
  60. data/generators/contactable_views/templates/views/formtastic/instant_messengers/_instant_messenger.html.erb +3 -0
  61. data/generators/contactable_views/templates/views/formtastic/phones/_phone.html.erb +2 -0
  62. data/generators/contactable_views/templates/views/formtastic/websites/_website.html.erb +2 -0
  63. data/generators/contactable_views/templates/views/jintastic/addresses/_address.html.erb +31 -0
  64. data/generators/contactable_views/templates/views/jintastic/addresses/_form.html.erb +9 -0
  65. data/generators/contactable_views/templates/views/jintastic/addresses/create.js.rjs +3 -0
  66. data/generators/contactable_views/templates/views/jintastic/addresses/destroy.js.rjs +3 -0
  67. data/generators/contactable_views/templates/views/jintastic/addresses/update.js.rjs +3 -0
  68. data/generators/contactable_views/templates/views/jintastic/cities/index.html.erb +6 -0
  69. data/generators/contactable_views/templates/views/jintastic/contactable/_birthday.html.erb +1 -0
  70. data/generators/contactable_views/templates/views/jintastic/contactable/_contactable.html.erb +16 -0
  71. data/generators/contactable_views/templates/views/jintastic/contactable/_contactable_field.html.erb +14 -0
  72. data/generators/contactable_views/templates/views/jintastic/contactable/_fields.html.erb +49 -0
  73. data/generators/contactable_views/templates/views/jintastic/contactable/_name.html.erb +3 -0
  74. data/generators/contactable_views/templates/views/jintastic/divisions/index.html.erb +9 -0
  75. data/generators/contactable_views/templates/views/jintastic/emails/_email.html.erb +2 -0
  76. data/generators/contactable_views/templates/views/jintastic/emails/_form.html.erb +9 -0
  77. data/generators/contactable_views/templates/views/jintastic/emails/create.js.rjs +3 -0
  78. data/generators/contactable_views/templates/views/jintastic/emails/destroy.js.rjs +3 -0
  79. data/generators/contactable_views/templates/views/jintastic/emails/update.js.rjs +3 -0
  80. data/generators/contactable_views/templates/views/jintastic/identifications/_form.html.erb +9 -0
  81. data/generators/contactable_views/templates/views/jintastic/identifications/_identification.html.erb +2 -0
  82. data/generators/contactable_views/templates/views/jintastic/identifications/create.js.rjs +3 -0
  83. data/generators/contactable_views/templates/views/jintastic/identifications/destroy.js.rjs +3 -0
  84. data/generators/contactable_views/templates/views/jintastic/identifications/update.js.rjs +3 -0
  85. data/generators/contactable_views/templates/views/jintastic/instant_messengers/_form.html.erb +9 -0
  86. data/generators/contactable_views/templates/views/jintastic/instant_messengers/_instant_messenger.html.erb +3 -0
  87. data/generators/contactable_views/templates/views/jintastic/instant_messengers/create.js.rjs +3 -0
  88. data/generators/contactable_views/templates/views/jintastic/instant_messengers/destroy.js.rjs +3 -0
  89. data/generators/contactable_views/templates/views/jintastic/instant_messengers/update.js.rjs +3 -0
  90. data/generators/contactable_views/templates/views/jintastic/phones/_form.html.erb +9 -0
  91. data/generators/contactable_views/templates/views/jintastic/phones/_phone.html.erb +2 -0
  92. data/generators/contactable_views/templates/views/jintastic/phones/create.js.rjs +3 -0
  93. data/generators/contactable_views/templates/views/jintastic/phones/destroy.js.rjs +3 -0
  94. data/generators/contactable_views/templates/views/jintastic/phones/update.js.rjs +3 -0
  95. data/generators/contactable_views/templates/views/jintastic/websites/_form.html.erb +9 -0
  96. data/generators/contactable_views/templates/views/jintastic/websites/_website.html.erb +2 -0
  97. data/generators/contactable_views/templates/views/jintastic/websites/create.js.rjs +3 -0
  98. data/generators/contactable_views/templates/views/jintastic/websites/destroy.js.rjs +3 -0
  99. data/generators/contactable_views/templates/views/jintastic/websites/update.js.rjs +3 -0
  100. data/lib/contactable.rb +6 -2
  101. data/lib/contactable/extensions/routes.rb +22 -0
  102. data/rails/init.rb +1 -0
  103. metadata +109 -19
  104. data/generators/contactable/templates/models/address.rb +0 -33
  105. data/generators/contactable/templates/models/address_type.rb +0 -5
  106. data/generators/contactable/templates/models/city.rb +0 -4
  107. data/generators/contactable/templates/models/country.rb +0 -4
  108. data/generators/contactable/templates/models/email_type.rb +0 -5
  109. data/generators/contactable/templates/models/phone_type.rb +0 -5
  110. data/generators/contactable/templates/models/website_type.rb +0 -5
@@ -0,0 +1,8 @@
1
+ class Country < ActiveRecord::Base
2
+ has_many :cities
3
+ has_many :divisions
4
+
5
+ def first_level_divisions
6
+ self.divisions.level_equals(1)
7
+ end
8
+ end
@@ -0,0 +1,26 @@
1
+ class Division < ActiveRecord::Base
2
+ belongs_to :country
3
+ belongs_to :parent, :class_name => "Division"
4
+ has_many :cities
5
+
6
+ # Returns an array with all the parents of this administrative region
7
+ #
8
+ # The first position in the array is the +country+ and up to 3 more positions
9
+ # can contain the ADM1, ADM2 and ADM3 divisions containing this one
10
+ def containers
11
+ return @containers unless @containers.nil?
12
+ container_codes = []
13
+ codes = code.split('|')
14
+ container_codes << (codes = codes[0..-2]).join('|') while codes.size > 1
15
+ # first is country code
16
+ @containers = [country]
17
+ # second, third can be parent administrative division if not nil
18
+ # NOTE container codes is like: ["ES|58|PO", "ES|58", "ES"] (country is last)
19
+ @containers += Division.find_all_by_code container_codes[0..-2], :order => :level if container_codes.size > 1
20
+ return @containers
21
+ end
22
+
23
+ def children
24
+ Division.find_all_by_parent_id(self.id)
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ class EmailType < ActiveRecord::Base
2
+ translates :name
3
+
4
+ validates_presence_of :name
5
+ end
@@ -0,0 +1,7 @@
1
+ class Identification < ActiveRecord::Base
2
+
3
+ validates_presence_of :code
4
+
5
+ belongs_to :owner, :polymorphic => true
6
+ belongs_to :type, :class_name => 'IdentificationType'
7
+ end
@@ -0,0 +1,5 @@
1
+ class IdentificationType < ActiveRecord::Base
2
+ translates :name
3
+
4
+ validates_presence_of :name
5
+ end
@@ -1,5 +1,5 @@
1
1
  class InstantMessengerProtocol < ActiveRecord::Base
2
-
2
+
3
3
  validates_presence_of :name
4
-
4
+
5
5
  end
@@ -1,5 +1,5 @@
1
1
  class InstantMessengerType < ActiveRecord::Base
2
-
3
- validates_presence_of :description
4
-
2
+ translates :name
3
+
4
+ validates_presence_of :name
5
5
  end
@@ -0,0 +1,5 @@
1
+ class PhoneType < ActiveRecord::Base
2
+ translates :name
3
+
4
+ validates_presence_of :name
5
+ end
@@ -0,0 +1,5 @@
1
+ class WebsiteType < ActiveRecord::Base
2
+ translates :name
3
+
4
+ validates_presence_of :name
5
+ end
@@ -0,0 +1,31 @@
1
+ <% address ||= @field %>
2
+ <span id='<%= dom_id address %>_country'>
3
+ <% clear_children = "$('.#{dom_id address}.division').html('')" %>
4
+ <% update_child_division = remote_function(:url => {:controller => 'divisions', :action => 'index'}, :with => "'field_dom_id=#{dom_id address}&search[country_id]=' + $('##{dom_id address}_country #address_country_id').val()", :update => "#{dom_id address}_division1") %>
5
+ <%= f.input :country, :prompt => t('countries.prompt'), :include_blank => t('actions.clear'), :input_html => {:onchange => "#{clear_children};#{update_child_division}"}%>
6
+ </span>
7
+ <% (1..4).each do |level| %>
8
+ <span id='<%= dom_id address %>_division<%= level %>' class='<%= dom_id address %> division <%= (0..level - 1).to_a.reverse.map {|i| "child#{i} "} %>'>
9
+ <% if level == 1
10
+ empty = address.country.blank? || address.country.first_level_divisions.empty?
11
+ collection = address.country.first_level_divisions unless empty
12
+ else
13
+ empty = address.send("division#{level - 1}").blank? || address.send("division#{level - 1}").children.empty?
14
+ collection = address.send("division#{level - 1}").children unless empty
15
+ end %>
16
+ <% unless empty %>
17
+ <% clear_children = "$('.#{dom_id address}.division.child#{level}').html('')" %>
18
+ <% update_child_division = remote_function(:url => {:controller => 'divisions', :action => 'index'}, :with => "'field_dom_id=#{dom_id address}&search[country_id]=' + $('##{dom_id address}_country #address_country_id').val() + '&search[parent_id]=' + $('##{dom_id address}_division#{level} #address_division#{level}_id').val() +'&search[level]=#{level + 1}'", :update => "#{dom_id address}_division#{level + 1}") %>
19
+ <% update_city = remote_function(:url => {:controller => 'cities', :action => 'index'}, :with => "'field_dom_id=#{dom_id address}&search[country_id]=' + $('##{dom_id address}_country #address_country_id').val() + '&search[division_id]=' + $('##{dom_id address}_division#{level} #address_division#{level}_id').val()", :update => "#{dom_id address}_city") %>
20
+ <%= f.input "division#{level}".to_sym, :collection => collection, :prompt => t('divisions.prompt'), :include_blank => t('actions.clear'), :input_html => {:onchange => "#{clear_children};#{update_child_division};#{update_city}"} %>
21
+ <% end %>
22
+ </span>
23
+ <% end %>
24
+ <span id='<%= dom_id address %>_city' class='<%= dom_id address %> division child1 child2 child3 child4'>
25
+ <% unless address.cities.empty? %>
26
+ <%= f.input :city, :collection => address.cities, :prompt => t('cities.prompt'), :include_blank => t('actions.clear') %>
27
+ <% end %>
28
+ </span>
29
+ <%= f.input :address %>
30
+ <%= f.input :zip %>
31
+ <%= f.input :type %>
@@ -0,0 +1,6 @@
1
+ <% unless @cities.empty? %>
2
+ <li id="address_city_input" class="select optional">
3
+ <label for="address_city_id">City</label>
4
+ <%= collection_select :address, :city_id, @cities, :id, :name, {:prompt => t('cities.prompt'), :include_blank => t('actions.clear')} %>
5
+ </li>
6
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <%= render contactable rescue nil%>
2
+
3
+ <p>
4
+ <span class='label'><%= contactable.class.human_attribute_name('name') %>:</span> <%= contactable.name %>
5
+ </p>
6
+ <p>
7
+ <span class='label'><%= contactable.class.human_attribute_name('birthday') %>:</span> <%= contactable.birthday %>
8
+ </p>
9
+ <% ['identification','phone', 'email', 'address', 'instant_messenger', 'website'].each do |field_name| %>
10
+ <%= render :partial => 'contactable/contactable_field', :locals => {:contactable => contactable, :field_name => field_name} %>
11
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <div class='multi <%= field_name.pluralize %>'>
2
+ <span class='label'><%= contactable.class.human_attribute_name(field_name.pluralize) %>:</span>
3
+ <ul>
4
+ <% contactable.send(field_name.pluralize).each do |field| %>
5
+ <li><%= send(field_name + '_label',field) %></li>
6
+ <% end %>
7
+ </ul>
8
+ </div>
@@ -0,0 +1,49 @@
1
+ <%= f.input :first_name %>
2
+ <%= f.input :middle_name %>
3
+ <%= f.input :last_name %>
4
+ <%= f.input :birthday, :as => :calendar %>
5
+
6
+ <div id='phones' class='multi phones'>
7
+ <%= f.label :phones, 'Phones' %>
8
+ <% f.inputs :for => :phones do |pf|%>
9
+ <%= render :partial => 'phones/phone', :locals => {:f => pf} %>
10
+ <%= remove_link_unless_new_record(pf) %>
11
+ <% end %>
12
+ </div>
13
+ <%= add_new_record_link f.object, :phone, f %>
14
+
15
+ <div id='addresses' class='multi addresses'>
16
+ <%= f.label :addresses, 'Addresses' %>
17
+ <% f.inputs :for => :addresses do |af|%>
18
+ <%= render :partial => 'addresses/address', :locals => {:address => af.object, :f => af} %>
19
+ <%= remove_link_unless_new_record(af) %>
20
+ <% end %>
21
+ </div>
22
+ <%= add_new_record_link f.object, :address, f %>
23
+
24
+ <div id="emails" class='multi emails'>
25
+ <%= f.label :emails, 'Emails' %>
26
+ <% f.inputs :for => :emails do |ef| %>
27
+ <%= render :partial => 'emails/email', :locals => {:f => ef} %>
28
+ <%= remove_link_unless_new_record(ef) %>
29
+ <% end %>
30
+ </div>
31
+ <%= add_new_record_link f.object, :email, f %>
32
+
33
+ <div id='instant_messengers' class='multi instant_messengers'>
34
+ <%= f.label :instant_messengers, 'Instant Messengers' %>
35
+ <% f.inputs :for => :instant_messengers do |imf|%>
36
+ <%= render :partial => 'instant_messengers/instant_messenger', :locals => {:f => imf } %>
37
+ <%= remove_link_unless_new_record(imf) %>
38
+ <% end %>
39
+ </div>
40
+ <%= add_new_record_link f.object, :instant_messenger, f %>
41
+
42
+ <div id='websites' class='multi websites'>
43
+ <%= f.label :websites, 'Websites'%>
44
+ <% f.inputs :for => :websites do |wf|%>
45
+ <%= render :partial => 'websites/website', :locals => {:f => wf} %>
46
+ <%= remove_link_unless_new_record(wf) %>
47
+ <% end %>
48
+ </div>
49
+ <%= add_new_record_link f.object, :website, f %>
@@ -0,0 +1,9 @@
1
+ <% unless @divisions.empty? %>
2
+ <li id="address_division<%= @level %>_input" class="select optional">
3
+ <label for="address_division<%= @level %>_id">Division<%=@level%></label>
4
+ <% clear_children = "$('.#{@field_dom_id}.division.child#{@level}').html('')" %>
5
+ <% update_child_division = remote_function(:url => {:controller => 'divisions', :action => 'index'}, :with => "'field_dom_id=#{@field_dom_id}&search[country_id]=' + $('##{@field_dom_id}_country #address_country_id').val() + '&search[parent_id]=' + $('##{@field_dom_id}_division#{@level} #address_division#{@level}_id').val() +'&search[level]=#{@level + 1}'", :update => "#{@field_dom_id}_division#{@level + 1}") %>
6
+ <% update_city = remote_function(:url => {:controller => 'cities', :action => 'index'}, :with => "'field_dom_id=#{@field_dom_id}&search[country_id]=' + $('##{@field_dom_id}_country #address_country_id').val() + '&search[division_id]=' + $('##{@field_dom_id}_division#{@level} #address_division#{@level}_id').val()", :update => "#{@field_dom_id}_city") %>
7
+ <%= collection_select :address, "division#{@level}_id", @divisions, :id, :name, {:prompt => t('divisions.prompt'), :include_blank => t('actions.clear')} , {:onchange => "#{clear_children};#{update_child_division};#{update_city}"} %>
8
+ </li>
9
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <%= f.input :address %>
2
+ <%= f.input :type %>
@@ -0,0 +1,2 @@
1
+ <%= f.input :code %>
2
+ <%= f.input :type %>
@@ -0,0 +1,3 @@
1
+ <%= f.input :nick %>
2
+ <%= f.input :protocol %>
3
+ <%= f.input :type %>
@@ -0,0 +1,2 @@
1
+ <%= f.input :number %>
2
+ <%= f.input :type %>
@@ -0,0 +1,2 @@
1
+ <%= f.input :address %>
2
+ <%= f.input :type %>
@@ -0,0 +1,4 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.resources :divisions, :only => :index
3
+ map.resources :cities, :only => :index
4
+ end
@@ -2,20 +2,20 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{contactable}
5
- s.version = "0.1.0"
5
+ s.version = "1.0.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Luis Perichon"]
9
- s.date = %q{2009-11-18}
9
+ s.date = %q{2010-03-29}
10
10
  s.description = %q{Adds contact information to an active record model}
11
11
  s.email = %q{info@luisperichon.com.ar}
12
- s.extra_rdoc_files = ["LICENSE", "README.rdoc", "lib/contactable.rb"]
13
- s.files = ["LICENSE", "Manifest", "README.rdoc", "Rakefile", "generators/contactable/USAGE", "generators/contactable/contactable_generator.rb", "generators/contactable/templates/migrations/create_contactable_related_tables.rb", "generators/contactable/templates/models/address.rb", "generators/contactable/templates/models/address_type.rb", "generators/contactable/templates/models/city.rb", "generators/contactable/templates/models/country.rb", "generators/contactable/templates/models/email.rb", "generators/contactable/templates/models/email_type.rb", "generators/contactable/templates/models/instant_messenger.rb", "generators/contactable/templates/models/instant_messenger_protocol.rb", "generators/contactable/templates/models/instant_messenger_type.rb", "generators/contactable/templates/models/phone.rb", "generators/contactable/templates/models/phone_type.rb", "generators/contactable/templates/models/province.rb", "generators/contactable/templates/models/website.rb", "generators/contactable/templates/models/website_type.rb", "lib/contactable.rb", "test/contactable_test.rb", "contactable.gemspec"]
12
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.rdoc", "lib/contactable.rb", "lib/contactable/extensions/routes.rb"]
13
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.rdoc", "Rakefile", "app/controllers/addresses_controller.rb", "app/controllers/cities_controller.rb", "app/controllers/contact_field_actions.rb", "app/controllers/divisions_controller.rb", "app/controllers/emails_controller.rb", "app/controllers/identifications_controller.rb", "app/controllers/instant_messengers_controller.rb", "app/controllers/phones_controller.rb", "app/controllers/websites_controller.rb", "app/helpers/contactable_helper.rb", "app/models/address.rb", "app/models/address_type.rb", "app/models/city.rb", "app/models/country.rb", "app/models/division.rb", "app/models/email.rb", "app/models/email_type.rb", "app/models/identification.rb", "app/models/identification_type.rb", "app/models/instant_messenger.rb", "app/models/instant_messenger_protocol.rb", "app/models/instant_messenger_type.rb", "app/models/phone.rb", "app/models/phone_type.rb", "app/models/province.rb", "app/models/website.rb", "app/models/website_type.rb", "app/views/addresses/_address.html.erb", "app/views/cities/index.html.erb", "app/views/contactable/_contactable.html.erb", "app/views/contactable/_contactable_field.html.erb", "app/views/contactable/_fields.html.erb", "app/views/divisions/index.html.erb", "app/views/emails/_email.html.erb", "app/views/identifications/_identification.html.erb", "app/views/instant_messengers/_instant_messenger.html.erb", "app/views/phones/_phone.html.erb", "app/views/websites/_website.html.erb", "config/contactable_routes.rb", "generators/contactable/USAGE", "generators/contactable/contactable_generator.rb", "generators/contactable/lib/insert_commands.rb", "generators/contactable/templates/README", "generators/contactable/templates/migrations/create_contactable_related_tables.rb", "generators/contactable_views/USAGE", "generators/contactable_views/contactable_views_generator.rb", "generators/contactable_views/templates/views/formtastic/addresses/_address.html.erb", "generators/contactable_views/templates/views/formtastic/cities/index.html.erb", "generators/contactable_views/templates/views/formtastic/contactable/_contactable.html.erb", "generators/contactable_views/templates/views/formtastic/contactable/_contactable_field.html.erb", "generators/contactable_views/templates/views/formtastic/contactable/_fields.html.erb", "generators/contactable_views/templates/views/formtastic/divisions/index.html.erb", "generators/contactable_views/templates/views/formtastic/emails/_email.html.erb", "generators/contactable_views/templates/views/formtastic/identifications/_identification.html.erb", "generators/contactable_views/templates/views/formtastic/instant_messengers/_instant_messenger.html.erb", "generators/contactable_views/templates/views/formtastic/phones/_phone.html.erb", "generators/contactable_views/templates/views/formtastic/websites/_website.html.erb", "generators/contactable_views/templates/views/jintastic/addresses/_address.html.erb", "generators/contactable_views/templates/views/jintastic/addresses/_form.html.erb", "generators/contactable_views/templates/views/jintastic/addresses/create.js.rjs", "generators/contactable_views/templates/views/jintastic/addresses/destroy.js.rjs", "generators/contactable_views/templates/views/jintastic/addresses/update.js.rjs", "generators/contactable_views/templates/views/jintastic/cities/index.html.erb", "generators/contactable_views/templates/views/jintastic/contactable/_birthday.html.erb", "generators/contactable_views/templates/views/jintastic/contactable/_contactable.html.erb", "generators/contactable_views/templates/views/jintastic/contactable/_contactable_field.html.erb", "generators/contactable_views/templates/views/jintastic/contactable/_fields.html.erb", "generators/contactable_views/templates/views/jintastic/contactable/_name.html.erb", "generators/contactable_views/templates/views/jintastic/divisions/index.html.erb", "generators/contactable_views/templates/views/jintastic/emails/_email.html.erb", "generators/contactable_views/templates/views/jintastic/emails/_form.html.erb", "generators/contactable_views/templates/views/jintastic/emails/create.js.rjs", "generators/contactable_views/templates/views/jintastic/emails/destroy.js.rjs", "generators/contactable_views/templates/views/jintastic/emails/update.js.rjs", "generators/contactable_views/templates/views/jintastic/identifications/_form.html.erb", "generators/contactable_views/templates/views/jintastic/identifications/_identification.html.erb", "generators/contactable_views/templates/views/jintastic/identifications/create.js.rjs", "generators/contactable_views/templates/views/jintastic/identifications/destroy.js.rjs", "generators/contactable_views/templates/views/jintastic/identifications/update.js.rjs", "generators/contactable_views/templates/views/jintastic/instant_messengers/_form.html.erb", "generators/contactable_views/templates/views/jintastic/instant_messengers/_instant_messenger.html.erb", "generators/contactable_views/templates/views/jintastic/instant_messengers/create.js.rjs", "generators/contactable_views/templates/views/jintastic/instant_messengers/destroy.js.rjs", "generators/contactable_views/templates/views/jintastic/instant_messengers/update.js.rjs", "generators/contactable_views/templates/views/jintastic/phones/_form.html.erb", "generators/contactable_views/templates/views/jintastic/phones/_phone.html.erb", "generators/contactable_views/templates/views/jintastic/phones/create.js.rjs", "generators/contactable_views/templates/views/jintastic/phones/destroy.js.rjs", "generators/contactable_views/templates/views/jintastic/phones/update.js.rjs", "generators/contactable_views/templates/views/jintastic/websites/_form.html.erb", "generators/contactable_views/templates/views/jintastic/websites/_website.html.erb", "generators/contactable_views/templates/views/jintastic/websites/create.js.rjs", "generators/contactable_views/templates/views/jintastic/websites/destroy.js.rjs", "generators/contactable_views/templates/views/jintastic/websites/update.js.rjs", "lib/contactable.rb", "lib/contactable/extensions/routes.rb", "rails/init.rb", "test/contactable_test.rb", "contactable.gemspec"]
14
14
  s.homepage = %q{http://github.com/lperichon/contactable}
15
15
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Contactable", "--main", "README.rdoc"]
16
16
  s.require_paths = ["lib"]
17
17
  s.rubyforge_project = %q{contactable}
18
- s.rubygems_version = %q{1.3.5}
18
+ s.rubygems_version = %q{1.3.6}
19
19
  s.summary = %q{Adds contact information to an active record model}
20
20
  s.test_files = ["test/contactable_test.rb"]
21
21
 
@@ -1,10 +1 @@
1
- Description:
2
- Creates a migration that adds contactable fields to the given model
3
-
4
- Example:
5
- ./script/generate contactable contact [--skip_related]
6
-
7
- This will create:
8
- db/migrate/TIMESTAMP_create_contactable_related_tables.rb
9
- app/models/...
10
- db/migrate/TIMESTAMP_add_contactable_fields_to_contact.rb
1
+ script/generate contactable
@@ -1,45 +1,48 @@
1
- class ContactableGenerator < Rails::Generator::NamedBase
2
- default_options :skip_related => false
1
+ require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb")
3
2
 
4
- def add_options!(opt)
5
- opt.on('-sr', '--skip_related') { |value| options[:skip_related] = value }
6
- end
3
+ class ContactableGenerator < Rails::Generator::NamedBase
7
4
 
8
5
  def manifest
9
6
  record do |m|
10
- unless options[:skip_related]
11
- # migration
7
+ # migration for related tables if not there already
8
+ unless ActiveRecord::Base.connection.table_exists?(:divisions)
12
9
  m.file 'migrations/create_contactable_related_tables.rb', "db/migrate/#{Time.now.strftime('%Y%m%d%H%M%S')}_create_contactable_related_tables.rb"
13
-
14
- # models
15
- %w( address address_type phone phone_type instant_messenger
16
- instant_messenger_type instant_messenger_protocol website website_type
17
- email email_type country province city ).each do |model|
18
- m.file "models/#{model}.rb", "app/models/#{model}.rb"
19
- end
20
10
  end
21
- m.migration_template 'migration:migration.rb', "db/migrate", {:assigns => contactable_local_assigns,
11
+
12
+ # migration for contactable fields
13
+ m.migration_template 'migration:migration.rb', "db/migrate", {
14
+ :assigns => contactable_local_assigns,
22
15
  :migration_file_name => "add_contactable_fields_to_#{custom_file_name}"
23
- }
16
+ }
17
+
18
+ # contactable model
19
+ contactable_model_file_path = "app/models/#{custom_file_name.singularize}.rb"
20
+ m.insert_into(contactable_model_file_path, 'contactable')
21
+
22
+ # contactable controller
23
+ contactable_controller_file_path = "app/models/#{custom_file_name}_controller.rb"
24
+ m.insert_into(contactable_model_file_path, "helper ContactableHelper")
25
+
26
+ m.readme "README"
24
27
  end
25
28
  end
26
29
 
27
30
  private
28
- def custom_file_name
29
- custom_name = class_name.underscore.downcase
30
- custom_name = custom_name.pluralize if ActiveRecord::Base.pluralize_table_names
31
- end
31
+ def custom_file_name
32
+ custom_name = class_name.underscore.downcase
33
+ custom_name = custom_name.pluralize if ActiveRecord::Base.pluralize_table_names
34
+ end
32
35
 
33
- def contactable_local_assigns
34
- returning(assigns = {}) do
35
- assigns[:migration_action] = "add"
36
- assigns[:class_name] = "add_contactable_fields_to_#{custom_file_name}"
37
- assigns[:table_name] = custom_file_name
38
- assigns[:attributes] = []
39
- assigns[:attributes] << Rails::Generator::GeneratedAttribute.new("first_name", "string")
40
- assigns[:attributes] << Rails::Generator::GeneratedAttribute.new("middle_name", "string")
41
- assigns[:attributes] << Rails::Generator::GeneratedAttribute.new("last_name", "string")
42
- assigns[:attributes] << Rails::Generator::GeneratedAttribute.new("birthday", "date")
43
- end
36
+ def contactable_local_assigns
37
+ returning(assigns = {}) do
38
+ assigns[:migration_action] = "add"
39
+ assigns[:class_name] = "add_contactable_fields_to_#{custom_file_name}"
40
+ assigns[:table_name] = custom_file_name
41
+ assigns[:attributes] = []
42
+ assigns[:attributes] << Rails::Generator::GeneratedAttribute.new("first_name", "string")
43
+ assigns[:attributes] << Rails::Generator::GeneratedAttribute.new("middle_name", "string")
44
+ assigns[:attributes] << Rails::Generator::GeneratedAttribute.new("last_name", "string")
45
+ assigns[:attributes] << Rails::Generator::GeneratedAttribute.new("birthday", "date")
44
46
  end
45
- end
47
+ end
48
+ end
@@ -0,0 +1,33 @@
1
+ # Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master
2
+
3
+ Rails::Generator::Commands::Base.class_eval do
4
+ def file_contains?(relative_destination, line)
5
+ File.read(destination_path(relative_destination)).include?(line)
6
+ end
7
+ end
8
+
9
+ Rails::Generator::Commands::Create.class_eval do
10
+ def insert_into(file, line)
11
+ logger.insert "#{line} into #{file}"
12
+ unless options[:pretend] || file_contains?(file, line)
13
+ gsub_file file, /^(class|module|.*Routes).*$/ do |match|
14
+ "#{match}\n #{line}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ Rails::Generator::Commands::Destroy.class_eval do
21
+ def insert_into(file, line)
22
+ logger.remove "#{line} from #{file}"
23
+ unless options[:pretend]
24
+ gsub_file file, "\n #{line}", ''
25
+ end
26
+ end
27
+ end
28
+
29
+ Rails::Generator::Commands::List.class_eval do
30
+ def insert_into(file, line)
31
+ logger.insert "#{line} into #{file}"
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+
2
+ *******************************************************************************
3
+
4
+ You're almost done! Don't forget to add contactable routes to your model.
5
+
6
+ for example:
7
+
8
+ map.resources :contacts do |contact|
9
+ contact.contactable_resources
10
+ end
11
+
12
+ *******************************************************************************
@@ -3,12 +3,17 @@ class CreateContactableRelatedTables < ActiveRecord::Migration
3
3
  create_table :addresses do |t|
4
4
  t.integer :owner_id
5
5
  t.string :owner_type
6
- t.integer :type_id, :default => 1
6
+ t.integer :type_id
7
7
  t.string :address
8
8
  t.integer :city_id
9
- t.integer :province_id
9
+ t.integer :division1_id
10
+ t.integer :division2_id
11
+ t.integer :division3_id
12
+ t.integer :division4_id
10
13
  t.integer :country_id
11
14
  t.string :zip
15
+ t.decimal :lat, :precision => 15, :scale => 10
16
+ t.decimal :lng, :precision => 15, :scale => 10
12
17
 
13
18
  t.timestamps
14
19
  end
@@ -16,7 +21,7 @@ class CreateContactableRelatedTables < ActiveRecord::Migration
16
21
  create_table :emails do |t|
17
22
  t.integer :owner_id
18
23
  t.string :owner_type
19
- t.integer :type_id, :default => 1
24
+ t.integer :type_id
20
25
  t.string :address
21
26
 
22
27
  t.timestamps
@@ -25,8 +30,8 @@ class CreateContactableRelatedTables < ActiveRecord::Migration
25
30
  create_table :instant_messengers do |t|
26
31
  t.integer :owner_id
27
32
  t.string :owner_type
28
- t.integer :protocol_id, :default => 1
29
- t.integer :type_id, :default => 1
33
+ t.integer :protocol_id
34
+ t.integer :type_id
30
35
  t.string :nick
31
36
 
32
37
  t.timestamps
@@ -35,7 +40,7 @@ class CreateContactableRelatedTables < ActiveRecord::Migration
35
40
  create_table :phones do |t|
36
41
  t.integer :owner_id
37
42
  t.string :owner_type
38
- t.integer :type_id, :default => 1
43
+ t.integer :type_id
39
44
  t.string :number
40
45
 
41
46
  t.timestamps
@@ -44,27 +49,25 @@ class CreateContactableRelatedTables < ActiveRecord::Migration
44
49
  create_table :websites do |t|
45
50
  t.integer :owner_id
46
51
  t.string :owner_type
47
- t.integer :type_id, :default => 1
52
+ t.integer :type_id
48
53
  t.string :address
49
54
 
50
55
  t.timestamps
51
56
  end
52
57
 
53
- create_table :address_types do |t|
54
- t.string :description
55
- end
58
+ create_table :identifications do |t|
59
+ t.integer :owner_id
60
+ t.string :owner_type
61
+ t.integer :type_id
62
+ t.string :code
56
63
 
57
- create_table :cities do |t|
58
- t.references :province
59
- t.string :name
64
+ t.timestamps
60
65
  end
61
66
 
62
- create_table :countries do |t|
63
- t.string :name
67
+ create_table :address_types do |t|
64
68
  end
65
69
 
66
70
  create_table :email_types do |t|
67
- t.string :description
68
71
  end
69
72
 
70
73
  create_table :instant_messenger_protocols do |t|
@@ -72,37 +75,161 @@ class CreateContactableRelatedTables < ActiveRecord::Migration
72
75
  end
73
76
 
74
77
  create_table :instant_messenger_types do |t|
75
- t.string :description
76
78
  end
77
79
 
78
80
  create_table :phone_types do |t|
79
- t.string :description
80
81
  end
81
82
 
82
- create_table :provinces do |t|
83
- t.references :country
84
- t.string :name
83
+ create_table :website_types do |t|
85
84
  end
86
85
 
87
- create_table :website_types do |t|
88
- t.string :description
86
+ create_table :identification_types do |t|
87
+ end
88
+
89
+ # # create countries
90
+ create_table :countries do |t|
91
+ # [0] iso alpha2
92
+ t.string :iso_code_two_letter, :null => false
93
+ # [1] iso alpha3
94
+ t.string :iso_code_three_letter, :null => false
95
+ # [2] iso numeric
96
+ t.integer :iso_number, :null => false
97
+ # [3] fips code
98
+ # [4] name
99
+ t.string :name, :null => false
100
+ # [5] capital
101
+ t.string :capital
102
+ # [6] areaInSqKm
103
+ # [7] population
104
+ # [8] continent
105
+ t.string :continent
106
+ # [9] top level domain
107
+ # [10] Currency code
108
+ # [11] Currency name
109
+ # [12] Phone
110
+ # [13] Postal Code Format
111
+ # [14] Postal Code Regex
112
+ # [15] Languages
113
+ # [16] Geoname id
114
+ t.integer :geonames_id, :null => false
115
+ # [17] Neighbours
116
+ # [18] Equivalent Fips Code
117
+
118
+ # Added for text-indexing
119
+ t.string :alternate_names, :limit => 5000
120
+ end
121
+
122
+ add_index :countries, :iso_code_two_letter, :unique => true
123
+ add_index :countries, :geonames_id, :null => false
124
+
125
+ # create divisions
126
+ create_table :divisions do |t|
127
+ t.integer :country_id, :null => false
128
+ # Higher level division, nil for ADM1
129
+ t.integer :parent_id
130
+ # Level for the administrative division (1 for ADM1, 2 for ADM2...)
131
+ t.integer :level, :default => 1
132
+ # Unique code generated by joining the country code and all ADM codes
133
+ t.string :code, :null => false
134
+ # [0] geonameid : integer id of record in geonames database
135
+ t.integer :geonames_id, :null => false
136
+ # [1] name : name of geographical point (utf8) varchar(200)
137
+ t.string :name, :null => false
138
+ # [2] asciiname : name of geographical point in plain ascii characters, varchar(200)
139
+ # [3] alternatenames : alternatenames, comma separated varchar(4000)
140
+ t.string :alternate_names, :limit => 5000
141
+ # [4] latitude : latitude in decimal degrees (wgs84)
142
+ t.decimal :latitude, :precision => 14, :scale => 8, :null => false
143
+ # [5] longitude : longitude in decimal degrees (wgs84)
144
+ t.decimal :longitude, :precision => 14, :scale => 8, :null => false
145
+ # [6] feature class : see http://www.geonames.org/export/codes.html, char(1)
146
+ # [7] feature code : see http://www.geonames.org/export/codes.html, varchar(10)
147
+ # [8] country code : ISO-3166 2-letter country code, 2 characters
148
+ t.string :country_iso_code_two_letters
149
+ # [9] cc2 : alternate country codes, comma separated, ISO-3166 2-letter country code, 60 characters
150
+ # [10] admin1 code : fipscode (subject to change to iso code), isocode for the us and ch, see file admin1Codes.txt for display names of this code; varchar(20)
151
+ # [11] admin2 code : code for the second administrative division, a county in the US, see file admin2Codes.txt; varchar(80)
152
+ # [12] admin3 code : code for third level administrative division, varchar(20)
153
+ # [13] admin4 code : code for fourth level administrative division, varchar(20)
154
+ # [14] population : integer
155
+ # [15] elevation : in meters, integer
156
+ # [16] gtopo30 : average elevation of 30'x30' (ca 900mx900m) area in meters, integer
157
+ # [17] timezone : the timezone id (see file timeZone.txt)
158
+ t.integer :geonames_timezone_id
159
+ # [18] modification date : date of last modification in yyyy-MM-dd format
160
+ end
161
+ add_index :divisions, :geonames_id, :unique => true
162
+ add_index :divisions, :parent_id
163
+ add_index :divisions, :code
164
+
165
+ # create cities
166
+ create_table :cities do |t|
167
+ t.integer :country_id, :null => false
168
+ # [0] geonameid : integer id of record in geonames database
169
+ t.integer :geonames_id, :null => false
170
+ # [1] name : name of geographical point (utf8) varchar(200)
171
+ t.string :name, :null => false
172
+ # [2] asciiname : name of geographical point in plain ascii characters, varchar(200)
173
+ # [3] alternatenames : alternatenames, comma separated varchar(4000)
174
+ # [4] latitude : latitude in decimal degrees (wgs84)
175
+ t.decimal :latitude, :precision => 14, :scale => 8, :null => false
176
+ # [5] longitude : longitude in decimal degrees (wgs84)
177
+ t.decimal :longitude, :precision => 14, :scale => 8, :null => false
178
+ # [6] feature class : see http://www.geonames.org/export/codes.html, char(1)
179
+ # [7] feature code : see http://www.geonames.org/export/codes.html, varchar(10)
180
+ # [8] country code : ISO-3166 2-letter country code, 2 characters
181
+ t.string :country_iso_code_two_letters
182
+ # [9] cc2 : alternate country codes, comma separated, ISO-3166 2-letter country code, 60 characters
183
+ # [10] admin1 code : fipscode (subject to change to iso code), isocode for the us and ch, see file admin1Codes.txt for display names of this code; varchar(20)
184
+ # [11] admin2 code : code for the second administrative division, a county in the US, see file admin2Codes.txt; varchar(80)
185
+ # [12] admin3 code : code for third level administrative division, varchar(20)
186
+ # [13] admin4 code : code for fourth level administrative division, varchar(20)
187
+ # [14] population : integer
188
+ # [15] elevation : in meters, integer
189
+ # [16] gtopo30 : average elevation of 30'x30' (ca 900mx900m) area in meters, integer
190
+ # [17] timezone : the timezone id (see file timeZone.txt)
191
+ t.integer :geonames_timezone_id
192
+ # [18] modification date : date of last modification in yyyy-MM-dd format
193
+
194
+ # Extras for linking to containers and divisions
195
+ t.string :code
196
+ t.integer :division_id
197
+ end
198
+
199
+ add_index :cities, :geonames_id, :unique => true
200
+ add_index :cities, :division_id
201
+ add_index :cities, :code
202
+
203
+ [:email_type, :website_type, :phone_type, :instant_messenger_type, :address_type, :identification_type].each do |clazz|
204
+ create_table "#{clazz}_translations" do |t|
205
+ t.string :locale
206
+ t.references clazz
207
+ t.string :name
208
+ t.timestamps
209
+ end
89
210
  end
90
211
  end
91
212
 
92
213
  def self.down
93
214
  drop_table :addresses
94
215
  drop_table :emails
216
+ drop_table :identifications
95
217
  drop_table :instant_messengers
96
218
  drop_table :phones
97
219
  drop_table :websites
98
220
  drop_table :address_types
99
- drop_table :cities
100
- drop_table :countries
221
+ drop_table :address_type_translations
101
222
  drop_table :email_types
223
+ drop_table :email_type
102
224
  drop_table :instant_messenger_protocols
103
225
  drop_table :instant_messenger_types
226
+ drop_table :instant_messenger_type_translations
104
227
  drop_table :phone_types
105
- drop_table :provinces
228
+ drop_table :phone_type_translations
106
229
  drop_table :website_types
230
+ drop_table :website_type_translations
231
+ drop_table :identification_types
232
+ drop_table :identification_type_translations
233
+ %w(countries divisions cities).each { |t| drop_table t }
107
234
  end
108
235
  end