mdd 3.0.0 → 3.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 (35) hide show
  1. data/lib/generators/mdwa/association/association_generator.rb +11 -10
  2. data/lib/generators/mdwa/association/templates/migrate/many_to_many.rb +3 -3
  3. data/lib/generators/mdwa/code/USAGE +5 -0
  4. data/lib/generators/mdwa/code/code_generator.rb +166 -0
  5. data/lib/generators/mdwa/code/templates/migration.rb +15 -0
  6. data/lib/generators/mdwa/entity/USAGE +5 -0
  7. data/lib/generators/mdwa/entity/entity_generator.rb +25 -0
  8. data/lib/generators/mdwa/entity/templates/entity.rb +50 -0
  9. data/lib/generators/mdwa/sandbox/sandbox_generator.rb +3 -1
  10. data/lib/generators/mdwa/sandbox/templates/app/controllers/a/home_controller.rb +4 -0
  11. data/lib/generators/mdwa/sandbox/templates/app/views/a/administrators/_form.html.erb +6 -38
  12. data/lib/generators/mdwa/sandbox/templates/app/views/a/administrators/_form_fields.html.erb +25 -0
  13. data/lib/generators/mdwa/sandbox/templates/db/seeds/site.rb +2 -1
  14. data/lib/generators/mdwa/scaffold/scaffold_generator.rb +5 -3
  15. data/lib/generators/mdwa/scaffold/templates/views/_list.html.erb +1 -1
  16. data/lib/generators/mdwa/user/USAGE +3 -0
  17. data/lib/generators/mdwa/user/templates/controllers/ajax_controller.rb +78 -0
  18. data/lib/generators/mdwa/user/templates/controllers/controller.rb +77 -0
  19. data/lib/generators/mdwa/user/templates/migrate.rb +15 -0
  20. data/lib/generators/mdwa/user/templates/model.rb +11 -0
  21. data/lib/generators/mdwa/user/templates/views/update.js.erb +12 -0
  22. data/lib/generators/mdwa/user/user_generator.rb +113 -0
  23. data/lib/mdwa/dsl.rb +7 -1
  24. data/lib/mdwa/dsl/entities.rb +14 -2
  25. data/lib/mdwa/dsl/entity.rb +94 -9
  26. data/lib/mdwa/dsl/entity_association.rb +59 -0
  27. data/lib/mdwa/dsl/entity_attribute.rb +46 -0
  28. data/lib/mdwa/dsl/generator.rb +10 -0
  29. data/lib/mdwa/generators/model.rb +13 -4
  30. data/lib/mdwa/generators/model_association.rb +1 -1
  31. data/lib/mdwa/generators/model_attribute.rb +10 -9
  32. data/lib/mdwa/version.rb +1 -1
  33. data/mdd.gemspec +1 -0
  34. data/test/entity_test.rb +188 -13
  35. metadata +35 -2
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'rails/generators'
4
4
  require 'rails/generators/migration'
5
+
5
6
  require 'mdwa/generators'
6
7
 
7
8
  module Mdwa
@@ -27,14 +28,14 @@ module Mdwa
27
28
 
28
29
  super
29
30
 
30
- @association = Generators::ModelAssocation.new(model1, model2, relation)
31
+ @association = MDWA::Generators::ModelAssociation.new(model1, model2, relation)
31
32
 
32
33
  end
33
34
 
34
35
 
35
36
  def model
36
37
  if @association.belongs_to?
37
- inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.klass.classify.constantize do
38
+ inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.model_class do
38
39
  ret = []
39
40
  ret << "\n\tbelongs_to :#{@association.model2.singular_name}, :class_name => '#{@association.model2.klass}'"
40
41
  ret << "\tattr_accessible :#{@association.model2.singular_name.foreign_key}"
@@ -42,25 +43,25 @@ module Mdwa
42
43
  end
43
44
  end
44
45
  if @association.has_one?
45
- inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.klass.classify.constantize do
46
+ inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.model_class do
46
47
  "\n\thas_one :#{@association.model2.singular_name}, :class_name => '#{@association.model2.klass}'\n"
47
48
  end
48
49
  end
49
50
  if @association.has_many?
50
- inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.klass.classify.constantize do
51
+ inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.model_class do
51
52
  "\n\thas_many :#{@association.model2.plural_name}, :class_name => '#{@association.model2.klass}'\n"
52
53
  end
53
54
  end
54
55
  if @association.has_and_belongs_to_many?
55
- inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.klass.classify.constantize do
56
+ inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.model_class do
56
57
  "\n\thas_and_belongs_to_many :#{@association.model2.plural_name}, :join_table => :#{many_to_many_table_name}\n"
57
58
  end
58
- inject_into_class "app/models/#{@association.model2.space}/#{@association.model2.singular_name}.rb", @association.model2.klass.classify.constantize do
59
+ inject_into_class "app/models/#{@association.model2.space}/#{@association.model2.singular_name}.rb", @association.model2.model_class do
59
60
  "\n\thas_and_belongs_to_many :#{@association.model1.plural_name}, :join_table => :#{many_to_many_table_name}\n"
60
61
  end
61
62
  end
62
63
  if @association.nested_one?
63
- inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.klass.classify.constantize do
64
+ inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.model_class do
64
65
  # belongs_to
65
66
  # attr_accessible attributes
66
67
  # attr_nested_attributes
@@ -68,7 +69,7 @@ module Mdwa
68
69
  end
69
70
  end
70
71
  if @association.nested_many?
71
- inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.klass.classify.constantize do
72
+ inject_into_class "app/models/#{@association.model1.space}/#{@association.model1.singular_name}.rb", @association.model1.model_class do
72
73
  # belongs_to
73
74
  # attr_accessible attributes
74
75
  # attr_nested_attributes
@@ -133,9 +134,9 @@ module Mdwa
133
134
  end
134
135
 
135
136
  # Implement the required interface for Rails::Generators::Migration.
136
- def self.next_migration_number(dirname)
137
+ def self.next_migration_number(dirname) #:nodoc:
137
138
  if ActiveRecord::Base.timestamped_migrations
138
- Time.now.utc.strftime("%Y%m%d%H%M%S").to_s
139
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
139
140
  else
140
141
  "%.3d" % (current_migration_number(dirname) + 1)
141
142
  end
@@ -1,8 +1,8 @@
1
1
  # -*- encoding : utf-8 -*-
2
- class Create<%= @ordered_models.first.plural_name.camelize %><%= @ordered_models.last.plural_name.camelize %> < ActiveRecord::Migration
2
+ class Create<%= @association.ordered.first.plural_name.camelize %><%= @association.ordered.last.plural_name.camelize %> < ActiveRecord::Migration
3
3
  def change
4
- create_table :<%= @ordered_models.first.plural_name %>_<%= @ordered_models.last.plural_name %>, :id => false do |t|
5
- t.references :<%= @ordered_models.first.singular_name %>, :<%= @ordered_models.last.singular_name %>
4
+ create_table :<%= @association.ordered.first.plural_name %>_<%= @association.ordered.last.plural_name %>, :id => false do |t|
5
+ t.references :<%= @association.ordered.first.singular_name %>, :<%= @association.ordered.last.singular_name %>
6
6
  end
7
7
  end
8
8
  end
@@ -0,0 +1,5 @@
1
+ Generates code for MDWA structural models.
2
+ Examples:
3
+
4
+ rails g mdwa:code # Generates code for all entities
5
+ rails g mdwa:code Product Category Client # Generates code for Product, Category and Client entities
@@ -0,0 +1,166 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/migration'
5
+
6
+ require 'mdwa/dsl'
7
+
8
+ module Mdwa
9
+ module Generators
10
+ class CodeGenerator < Rails::Generators::Base
11
+
12
+ include Rails::Generators::Migration
13
+
14
+ source_root File.expand_path("../templates", __FILE__)
15
+
16
+ attr_accessor :all_entities, :code_changes, :random_migration_key
17
+
18
+ argument :entities, :type => :array, :banner => 'Specific entities', :default => []
19
+
20
+ class_option :run_migrations, :type => :boolean, :default => false, :desc => 'Run rake db:migrate directly'
21
+ class_option :only_interface, :type => :boolean, :default => false, :desc => 'Generate only user interface'
22
+
23
+ def initialize(*args, &block)
24
+ super
25
+
26
+ # include files with entities
27
+ inside Rails.root do
28
+ if entities.count.zero?
29
+ require_all MDWA::DSL::STRUCTURAL_PATH
30
+ else
31
+ files = entities.collect{ |e| "#{MDWA::DSL::STRUCTURAL_PATH}#{MDWA::DSL::Entity.new(e).file_name}.rb" }
32
+ require_all files.join(', ')
33
+ end
34
+ end
35
+
36
+ # select models that will be generated
37
+ # only required models are included
38
+ @all_entities = MDWA::DSL.entities.all
39
+
40
+ @changes = []
41
+ @random_migration_key = rand.to_s.gsub('.','').to_i
42
+
43
+ end
44
+
45
+ def code_generation
46
+
47
+ return false if options.only_interface
48
+
49
+ @all_entities.each do |entity|
50
+
51
+ # if it's not a resource, ignore
52
+ next unless entity.resource?
53
+
54
+ # if model has not a database yet, run the generate command
55
+ begin
56
+ # if model does not exist, should generate scaffold
57
+ model_class = entity.model_class
58
+ rescue
59
+ model_class = nil
60
+ end
61
+ if entity.force? or model_class.nil? or !model_class.table_exists?
62
+ puts "===================================================="
63
+ puts "Generating code for '#{entity.name}'"
64
+ puts "===================================================="
65
+ generation_string = "#{entity.generate} #{'--skip_rake_migrate' unless options.run_migrations} #{'--force' if options.force} --skip-questions"
66
+ generate generation_string
67
+
68
+ # append generated code to entity
69
+ append_to_file "#{MDWA::DSL::STRUCTURAL_PATH}#{entity.file_name}.rb", "\n\nMDWA::DSL.entity('#{entity.name}').code_generations << '#{generation_string}'"
70
+
71
+ next # nothing's changed, go to the next entity
72
+ end
73
+
74
+ # check what changed
75
+ model_class.columns.each do |column|
76
+ # ignore rails default columns and attributes used in associations
77
+ next if column.name == 'id' or column.name == 'created_at' or column.name == 'updated_at' or column.name.end_with? '_id'
78
+
79
+ entity_attribute = entity.attributes[column.name]
80
+ # model attribute exists, but not in entity -> was erased
81
+ if entity_attribute.nil?
82
+ @changes << {:entity => entity, :type => 'remove_column', :column => column.name}
83
+ # attribute exists in model and entity, but changed type
84
+ elsif entity_attribute.type.to_sym != column.type.to_sym
85
+ next if entity_attribute.type.to_sym == :file or entity_attribute.type.to_sym == :password
86
+ @changes << {:entity => entity, :type => 'change_column', :column => column.name, :attr_type => entity_attribute.type, :from => column.type}
87
+ end
88
+
89
+ end
90
+
91
+ # new attributes
92
+ entity.attributes.each do |key, attr|
93
+ # no column with that name -> column must be added
94
+ if model_class.columns.select {|c| c.name == attr.name}.count.zero?
95
+ @changes << {:entity => entity, :type => 'add_column', :column => attr.name, :attr_type => attr.type}
96
+ end
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+
103
+ def only_interface_generation
104
+
105
+ if options.only_interface
106
+ @all_entities.each do |entity|
107
+
108
+ # if it's not a resource, ignore
109
+ next unless entity.resource?
110
+
111
+ # if model has not a database yet, run the generate command
112
+ begin
113
+ # if model does not exist, should generate scaffold
114
+ model_class = entity.model_class
115
+ rescue
116
+ model_class = nil
117
+ end
118
+ if entity.force? or model_class.nil? or !model_class.table_exists?
119
+ puts "===================================================="
120
+ puts "Generating code for '#{entity.name}'"
121
+ puts "===================================================="
122
+ generate "#{entity.generate} --only_interface #{'--force' if options.force}"
123
+
124
+ # append generated code to entity
125
+ append_to_file "#{MDWA::DSL::STRUCTURAL_PATH}#{entity.file_name}.rb", "\n\nMDWA::DSL.entity('#{entity.name}').code_generations << '#{generation_string}'"
126
+ end
127
+ end
128
+ end
129
+
130
+ end
131
+
132
+ def migration_generation
133
+ unless @changes.empty?
134
+ # generate changed code
135
+ migration_template 'migration.rb', "db/migrate/alter_#{@all_entities.select{|e| e.resource?}.collect{|e| e.file_name}.join('_')}#{@random_migration_key}.rb"
136
+ end
137
+ end
138
+
139
+ def rake_db_migrate
140
+ if options.run_migrations
141
+ rake 'db:migrate'
142
+ end
143
+ end
144
+
145
+ # Implement the required interface for Rails::Generators::Migration.
146
+ def self.next_migration_number(dirname) #:nodoc:
147
+ if ActiveRecord::Base.timestamped_migrations
148
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
149
+ else
150
+ "%.3d" % (current_migration_number(dirname) + 1)
151
+ end
152
+ end
153
+
154
+ private
155
+ def inverse_migration_type(type)
156
+ case type.to_sym
157
+ when :add_column then 'remove_column'
158
+ when :remove_column then 'add_column'
159
+ when :change_column then 'change_column'
160
+ end
161
+ end
162
+
163
+ end # class
164
+ end # generators
165
+ end # mdwa
166
+
@@ -0,0 +1,15 @@
1
+ class Alter<%= @all_entities.select{|e| e.resource?}.collect{|e| e.file_name.camelize}.join('') %><%= @random_migration_key %> < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ <%- @changes.each do |change| -%>
5
+ <%= change[:type] %> :<%= MDWA::Generators::Model.new(change[:entity].model_name).plural_name %>, :<%= change[:column] %> <%= ", :#{change[:attr_type]}" unless change[:attr_type].blank? %>
6
+ <%- end -%>
7
+ end
8
+
9
+ def self.down
10
+ <%- @changes.each do |change| -%>
11
+ <%= inverse_migration_type change[:type] %> :<%= MDWA::Generators::Model.new(change[:entity].model_name).plural_name %>, :<%= change[:column] %> <%= ", :#{change[:attr_type]}" if inverse_migration_type(change[:type]) == 'add_column' %> <%= ", :#{change[:from]}" unless change[:from].blank? %>
12
+ <%- end -%>
13
+ end
14
+
15
+ end
@@ -0,0 +1,5 @@
1
+ Generates a clean entity for MDWA structural model.
2
+
3
+ Example:
4
+ rails g mdwa:entity Product
5
+ rails g mdwa:entity a/category
@@ -0,0 +1,25 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/migration'
5
+
6
+ require 'mdwa/dsl'
7
+
8
+ module Mdwa
9
+ module Generators
10
+ class EntityGenerator < Rails::Generators::Base
11
+
12
+ source_root File.expand_path("../templates", __FILE__)
13
+
14
+ argument :name, :type => :string, :banner => 'Entity name'
15
+
16
+ class_option :user, :type => :boolean, :default => false, :desc => 'Is this entity a loggable user?'
17
+ class_option :no_comments, :type => :boolean, :default => false, :desc => 'Generates entity without comments.'
18
+
19
+ def code_generation
20
+ template 'entity.rb', "#{MDWA::DSL::STRUCTURAL_PATH}#{MDWA::DSL::Entity.new(name).file_name}.rb"
21
+ end
22
+
23
+ end # entity
24
+ end #generators
25
+ end #mdwa
@@ -0,0 +1,50 @@
1
+ # -*- encoding : utf-8 -*-
2
+ MDWA::DSL.entities.register "<%= name.singularize.camelize %>" do |e|
3
+
4
+ <%- if options.user -%>
5
+ # NOTE: Users have the following attributes predefined (Devise defaults):
6
+ # "email", "password", "password_confirmation", "encrypted_password", "name", "type", "reset_password_token",
7
+ # "reset_password_sent_at", "remember_created_at", "sign_in_count", "current_sign_in_at", "last_sign_in_at",
8
+ # "current_sign_in_ip", "last_sign_in_ip", "created_at", "updated_at"
9
+ e.user = true
10
+ <%- end -%>
11
+
12
+ <%- unless options.no_comments -%>
13
+ # e.purpose = %q{To-do} # what this entity does?
14
+ # e.resource = true # should it be stored like a resource?
15
+ # e.ajax = true # scaffold with ajax?
16
+ # e.user = false # is this entity a loggable user?
17
+ # e.scaffold_name = 'a/<%= name.singularize.underscore %>' # mdwa sandbox specific code?
18
+ # e.model_name = 'a/<%= name.singularize.underscore %>' # use specific model name? or different namespace?
19
+
20
+ ##
21
+ ## Define entity attributes
22
+ ##
23
+ # e.attribute do |attr|
24
+ # attr.name = 'name'
25
+ # attr.type = 'string'
26
+ # end
27
+ # e.attribute do |attr|
28
+ # attr.name = 'category'
29
+ # attr.type = 'integer'
30
+ # end
31
+
32
+ ##
33
+ ## Define entity associations
34
+ ##
35
+ # e.association do |a|
36
+ # a.type = 'many_to_one'
37
+ # a.destination = 'Category' # entity name
38
+ # a.description = '<%= name.singularize.humanize %> belongs to category'
39
+ # end
40
+ #
41
+ # e.association do |a|
42
+ # a.name = 'address' # specify a name for the associations
43
+ # a.type = 'one_to_one'
44
+ # a.destination = 'Address'
45
+ # a.composition = true
46
+ # a.description = 'This entity has a composite address.'
47
+ # end
48
+ <%- end -%>
49
+
50
+ end
@@ -27,6 +27,7 @@ module Mdwa
27
27
  gem 'cancan'
28
28
  gem 'will_paginate'
29
29
  gem 'nested_form'
30
+ gem 'require_all'
30
31
 
31
32
  inside Rails.root do
32
33
  run "bundle install"
@@ -131,7 +132,8 @@ module Mdwa
131
132
  devise_for :users, :skip => :registrations, :controllers => {:sessions => 'a/users/sessions', :passwords => 'a/users/passwords' }
132
133
 
133
134
  resources :administrators
134
- controller :administrators do
135
+
136
+ controller :home do
135
137
  get '/edit_account' => :edit_own_account
136
138
  end
137
139
 
@@ -6,5 +6,9 @@ class A::HomeController < A::BackendController
6
6
 
7
7
  def index
8
8
  end
9
+
10
+ def edit_own_account
11
+ redirect_to "/a/#{current_user.type.underscore.split('/').last.pluralize}/#{current_user.id}/edit?static_html=1"
12
+ end
9
13
 
10
14
  end
@@ -1,45 +1,13 @@
1
1
  <%= form_for([:a, @administrator]) do |f| %>
2
2
 
3
- <% if @administrator.errors.any? %>
4
- <div id="error_explanation">
5
- <h2><%= pluralize(@administrator.errors.count, t('system.error')) %> :</h2>
6
-
7
- <ul>
8
- <% @administrator.errors.full_messages.each do |msg| %>
9
- <li><%= msg %></li>
10
- <% end %>
11
- </ul>
12
- </div>
13
- <% end %>
3
+ <div id="mdwa_error">
4
+ <%%= render '/template/mdwa/crud_error', :object => @administrator %>
5
+ </div>
14
6
 
15
7
  <div class="yui3-g">
16
-
17
- <div class="yui3-u-1-2">
18
- <div class="field">
19
- <%= f.label :name %>
20
- <%= f.text_field :name %>
21
- </div>
22
- <div class="field">
23
- <%= f.label :email %>
24
- <%= f.text_field :email %>
25
- </div>
26
- </div>
27
-
28
- <div class="yui3-u-1-2">
29
- <% unless @administrator.new_record? %>
30
- <p class="description"><%= raw t('administrators.edit_form_password_text') %></p>
31
- <% end %>
32
-
33
- <div class="field">
34
- <%= f.label :password, t('administrators.edit_form_password') %>
35
- <%= f.password_field :password %>
36
- </div>
37
- <div class="field">
38
- <%= f.label :password_confirmation, t('administrators.edit_form_password_confirmation') %>
39
- <%= f.password_field :password_confirmation %>
40
- </div>
41
- </div>
42
-
8
+ <div class="yui3-u">
9
+ <%= render 'form_fields', :f => f %>
10
+ </div>
43
11
  </div>
44
12
 
45
13
  <div class="actions">