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.
- data/lib/generators/mdwa/association/association_generator.rb +11 -10
- data/lib/generators/mdwa/association/templates/migrate/many_to_many.rb +3 -3
- data/lib/generators/mdwa/code/USAGE +5 -0
- data/lib/generators/mdwa/code/code_generator.rb +166 -0
- data/lib/generators/mdwa/code/templates/migration.rb +15 -0
- data/lib/generators/mdwa/entity/USAGE +5 -0
- data/lib/generators/mdwa/entity/entity_generator.rb +25 -0
- data/lib/generators/mdwa/entity/templates/entity.rb +50 -0
- data/lib/generators/mdwa/sandbox/sandbox_generator.rb +3 -1
- data/lib/generators/mdwa/sandbox/templates/app/controllers/a/home_controller.rb +4 -0
- data/lib/generators/mdwa/sandbox/templates/app/views/a/administrators/_form.html.erb +6 -38
- data/lib/generators/mdwa/sandbox/templates/app/views/a/administrators/_form_fields.html.erb +25 -0
- data/lib/generators/mdwa/sandbox/templates/db/seeds/site.rb +2 -1
- data/lib/generators/mdwa/scaffold/scaffold_generator.rb +5 -3
- data/lib/generators/mdwa/scaffold/templates/views/_list.html.erb +1 -1
- data/lib/generators/mdwa/user/USAGE +3 -0
- data/lib/generators/mdwa/user/templates/controllers/ajax_controller.rb +78 -0
- data/lib/generators/mdwa/user/templates/controllers/controller.rb +77 -0
- data/lib/generators/mdwa/user/templates/migrate.rb +15 -0
- data/lib/generators/mdwa/user/templates/model.rb +11 -0
- data/lib/generators/mdwa/user/templates/views/update.js.erb +12 -0
- data/lib/generators/mdwa/user/user_generator.rb +113 -0
- data/lib/mdwa/dsl.rb +7 -1
- data/lib/mdwa/dsl/entities.rb +14 -2
- data/lib/mdwa/dsl/entity.rb +94 -9
- data/lib/mdwa/dsl/entity_association.rb +59 -0
- data/lib/mdwa/dsl/entity_attribute.rb +46 -0
- data/lib/mdwa/dsl/generator.rb +10 -0
- data/lib/mdwa/generators/model.rb +13 -4
- data/lib/mdwa/generators/model_association.rb +1 -1
- data/lib/mdwa/generators/model_attribute.rb +10 -9
- data/lib/mdwa/version.rb +1 -1
- data/mdd.gemspec +1 -0
- data/test/entity_test.rb +188 -13
- 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::
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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")
|
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<%= @
|
2
|
+
class Create<%= @association.ordered.first.plural_name.camelize %><%= @association.ordered.last.plural_name.camelize %> < ActiveRecord::Migration
|
3
3
|
def change
|
4
|
-
create_table :<%= @
|
5
|
-
t.references :<%= @
|
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,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,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
|
-
|
135
|
+
|
136
|
+
controller :home do
|
135
137
|
get '/edit_account' => :edit_own_account
|
136
138
|
end
|
137
139
|
|
@@ -1,45 +1,13 @@
|
|
1
1
|
<%= form_for([:a, @administrator]) do |f| %>
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
18
|
-
|
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">
|