contactable 0.1.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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