datamapper4rails 0.3.0

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 (38) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +37 -0
  3. data/README.txt +151 -0
  4. data/Rakefile +48 -0
  5. data/datamapper_rails_templates.rb +114 -0
  6. data/generators/datamapper_install/datamapper_install_generator.rb +12 -0
  7. data/generators/datamapper_install/templates/datamapper.rake +88 -0
  8. data/generators/datamapper_model/datamapper_model_generator.rb +18 -0
  9. data/generators/datamapper_model/templates/migration.rb +18 -0
  10. data/generators/datamapper_model/templates/model.rb +14 -0
  11. data/generators/datamapper_rspec_model/datamapper_rspec_model_generator.rb +18 -0
  12. data/generators/datamapper_rspec_model/templates/model_spec.rb +44 -0
  13. data/generators/datamapper_rspec_scaffold/datamapper_rspec_scaffold_generator.rb +20 -0
  14. data/generators/datamapper_rspec_scaffold/templates/controller_spec.rb +171 -0
  15. data/generators/datamapper_rspec_scaffold/templates/edit_erb_spec.rb +25 -0
  16. data/generators/datamapper_scaffold/datamapper_scaffold_generator.rb +31 -0
  17. data/generators/datamapper_scaffold/templates/controller.rb +90 -0
  18. data/generators/datamapper_scaffold/templates/functional_test.rb +49 -0
  19. data/generators/datamapper_scaffold/templates/view_edit.html.erb +18 -0
  20. data/generators/datamapper_scaffold/templates/view_index.html.erb +24 -0
  21. data/generators/datamapper_scaffold/templates/view_new.html.erb +17 -0
  22. data/generators/datamapper_scaffold/templates/view_show.html.erb +10 -0
  23. data/lib/datamapper4rails.rb +14 -0
  24. data/lib/datamapper4rails/adapters/base_adapter.rb +198 -0
  25. data/lib/datamapper4rails/adapters/restful_adapter.rb +320 -0
  26. data/lib/datamapper4rails/datamapper_store.rb +28 -0
  27. data/lib/datamapper4rails/identity_maps.rb +25 -0
  28. data/lib/datamapper4rails/integration_test.rb +45 -0
  29. data/lib/datamapper4rails/overlay.rb +69 -0
  30. data/lib/datamapper4rails/preload_models.rb +26 -0
  31. data/lib/datamapper4rails/restful_transactions.rb +43 -0
  32. data/lib/datamapper4rails/rspec.rb +8 -0
  33. data/lib/datamapper4rails/rspec_default_values.rb +23 -0
  34. data/lib/datamapper4rails/version.rb +3 -0
  35. data/spec/datamapper_store_spec.rb +23 -0
  36. data/spec/spec.opts +1 -0
  37. data/spec/spec_helper.rb +34 -0
  38. metadata +124 -0
@@ -0,0 +1,18 @@
1
+ require 'rails_generator/generators/components/model/model_generator'
2
+ require 'active_record'
3
+ require 'datamapper4rails/overlay'
4
+
5
+
6
+ class DatamapperModelGenerator < ModelGenerator
7
+
8
+ def manifest
9
+ overlay_dirs.add_generator("model")
10
+ super
11
+ end
12
+
13
+ def add_options!(opt)
14
+ super
15
+ opt.on("--skip-timestamps",
16
+ "Don't add timestamps for this model") { |v| options[:skip_timestamps] = v }
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ migration <%= Time.now.utc.strftime("%Y%m%d%H%M%S") %>, :<%= migration_name.underscore %> do
2
+ up do
3
+ create_table :<%= table_name %> do
4
+ column :id, Integer, :serial => true
5
+ <% Array(attributes).each do |attribute| -%>
6
+ column :<%= attribute.name if attribute %>, <%= attribute.type.to_s.capitalize %>, :nullable => false<% if attribute.type == :string %>, :length => 255<% end %>
7
+ <% end -%>
8
+ <% unless options[:skip_timestamps] -%>
9
+ column :created_at, DateTime, :nullable => false
10
+ column :updated_at, DateTime, :nullable => false
11
+ <% end -%>
12
+ end
13
+ end
14
+
15
+ down do
16
+ drop_table :<%= table_name %>
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ class <%= class_name %>
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+
6
+ <% Array(attributes).each do |attribute| -%>
7
+ property :<%= attribute.name %>, <%= attribute.type.to_s.capitalize %>, :nullable => false <% if attribute.type == :string or attribute.type == :text or attribute.type == :slug -%>, :format => /^[^<'&">]*$/<% if attribute.type == :string or attribute.type == :slug %>, :length => 255<% end -%><% end %>
8
+
9
+ <% end -%>
10
+ <% unless options[:skip_timestamps] -%>
11
+ timestamps :at
12
+ <% end -%>
13
+
14
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails_generator/generators/components/model/model_generator'
2
+ require 'active_record'
3
+ require 'datamapper4rails/overlay'
4
+
5
+ class DatamapperRspecModelGenerator < RspecModelGenerator
6
+
7
+ def manifest
8
+ overlay_dirs.add_generator("datamapper_model")
9
+ overlay_dirs.add_generator("rspec_model")
10
+ super
11
+ end
12
+
13
+ def add_options!(opt)
14
+ super
15
+ opt.on("--skip-timestamps",
16
+ "Don't add timestamps for this model") { |v| options[:skip_timestamps] = v }
17
+ end
18
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper')
2
+
3
+ describe <%= class_name %> do
4
+ before(:each) do
5
+ @valid_attributes = {
6
+ <% attributes.each_with_index do |attribute, attribute_index| -%>
7
+ :<%= attribute.name %> => <%= attribute.default_value %><%= attribute_index == attributes.length - 1 ? '' : ','%>
8
+ <% end -%>
9
+ }
10
+ end
11
+
12
+ it "should create a new instance given valid attributes" do
13
+ <%= class_name %>.create(@valid_attributes)
14
+ end
15
+ <% attributes.each do |attribute| -%>
16
+ it "should require <%= attribute.name %>" do
17
+ <%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => nil))
18
+ <%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
19
+ end
20
+
21
+ <% if [:string, :text, :slug].member? attribute.type -%>
22
+ it 'should not match <%= attribute.name %>' do
23
+ <%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "<script" ))
24
+ <%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
25
+ <%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "sc'ript" ))
26
+ <%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
27
+ <%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "scr&ipt" ))
28
+ <%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
29
+ <%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => 'scr"ipt' ))
30
+ <%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
31
+ <%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "script>" ))
32
+ <%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
33
+ end
34
+
35
+ <% elsif [:integer, :big_decimal, :float].member? attribute.type %>
36
+ it "should be numerical <%= attribute.name %>" do
37
+ <%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "none-numberic" ))
38
+ <%= singular_name %>.<%= attribute.name %>.to_i.should == 0
39
+ <%= singular_name %>.errors.size.should == 1
40
+ end
41
+
42
+ <% end -%>
43
+ <% end -%>
44
+ end
@@ -0,0 +1,20 @@
1
+ require 'datamapper4rails/overlay'
2
+ require 'datamapper4rails/rspec_default_values'
3
+
4
+ class DatamapperRspecScaffoldGenerator < RspecScaffoldGenerator
5
+
6
+ def manifest
7
+ overlay_dirs.add_generator("datamapper_rspec_model")
8
+ overlay_dirs.add_generator("datamapper_model")
9
+ overlay_dirs.add_generator("datamapper_scaffold")
10
+ overlay_dirs.add_generator("rspec_scaffold")
11
+ overlay_dirs.add_generator("scaffold")
12
+ super
13
+ end
14
+
15
+ def add_options!(opt)
16
+ super
17
+ opt.on("--skip-timestamps",
18
+ "Don't add timestamps for this model") { |v| options[:skip_timestamps] = v }
19
+ end
20
+ end
@@ -0,0 +1,171 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper')
2
+
3
+ describe <%= controller_class_name %>Controller do
4
+
5
+ def mock_<%= file_name %>(stubs={})
6
+ @mock_<%= file_name %> ||= mock_model(<%= class_name %>, stubs)
7
+ end
8
+
9
+ describe "GET index" do
10
+
11
+ it "exposes all <%= table_name %> as @<%= table_name %>" do
12
+ <%= class_name %>.should_receive(:all).and_return([mock_<%= file_name %>])
13
+ get :index
14
+ assigns[:<%= table_name %>].should == [mock_<%= file_name %>]
15
+ end
16
+
17
+ describe "with mime type of xml" do
18
+
19
+ it "renders all <%= table_name.pluralize %> as xml" do
20
+ <%= class_name %>.should_receive(:all).and_return(<%= file_name.pluralize %> = mock("Array of <%= class_name.pluralize %>"))
21
+ <%= file_name.pluralize %>.should_receive(:to_xml).and_return("generated XML")
22
+ get :index, :format => 'xml'
23
+ response.body.should == "generated XML"
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ describe "GET show" do
31
+
32
+ it "exposes the requested <%= file_name %> as @<%= file_name %>" do
33
+ <%= class_name %>.should_receive(:get!).with("37").and_return(mock_<%= file_name %>)
34
+ get :show, :id => "37"
35
+ assigns[:<%= file_name %>].should equal(mock_<%= file_name %>)
36
+ end
37
+
38
+ describe "with mime type of xml" do
39
+
40
+ it "renders the requested <%= file_name %> as xml" do
41
+ <%= class_name %>.should_receive(:get!).with("37").and_return(mock_<%= file_name %>)
42
+ mock_<%= file_name %>.should_receive(:to_xml).and_return("generated XML")
43
+ get :show, :id => "37", :format => 'xml'
44
+ response.body.should == "generated XML"
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
51
+ describe "GET new" do
52
+
53
+ it "exposes a new <%= file_name %> as @<%= file_name %>" do
54
+ <%= class_name %>.should_receive(:new).and_return(mock_<%= file_name %>)
55
+ get :new
56
+ assigns[:<%= file_name %>].should equal(mock_<%= file_name %>)
57
+ end
58
+
59
+ end
60
+
61
+ describe "GET edit" do
62
+
63
+ it "exposes the requested <%= file_name %> as @<%= file_name %>" do
64
+ <%= class_name %>.should_receive(:get!).with("37").and_return(mock_<%= file_name %>)
65
+ get :edit, :id => "37"
66
+ assigns[:<%= file_name %>].should equal(mock_<%= file_name %>)
67
+ end
68
+
69
+ end
70
+
71
+ describe "POST create" do
72
+
73
+ describe "with valid params" do
74
+
75
+ it "exposes a newly created <%= file_name %> as @<%= file_name %>" do
76
+ <%= class_name %>.should_receive(:new).with({'these' => 'params'}).and_return(mock_<%= file_name %>(:save => true))
77
+ post :create, :<%= file_name %> => {:these => 'params'}
78
+ assigns(:<%= file_name %>).should equal(mock_<%= file_name %>)
79
+ end
80
+
81
+ it "redirects to the created <%= file_name %>" do
82
+ <%= class_name %>.stub!(:new).and_return(mock_<%= file_name %>(:save => true))
83
+ post :create, :<%= file_name %> => {}
84
+ response.should redirect_to(<%= table_name.singularize %>_url(mock_<%= file_name %>))
85
+ end
86
+
87
+ end
88
+
89
+ describe "with invalid params" do
90
+
91
+ it "exposes a newly created but unsaved <%= file_name %> as @<%= file_name %>" do
92
+ <%= class_name %>.stub!(:new).with({'these' => 'params'}).and_return(mock_<%= file_name %>(:save => false))
93
+ post :create, :<%= file_name %> => {:these => 'params'}
94
+ assigns(:<%= file_name %>).should equal(mock_<%= file_name %>)
95
+ end
96
+
97
+ it "re-renders the 'new' template" do
98
+ <%= class_name %>.stub!(:new).and_return(mock_<%= file_name %>(:save => false))
99
+ post :create, :<%= file_name %> => {}
100
+ response.should render_template('new')
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
107
+ describe "PUT udpate" do
108
+
109
+ describe "with valid params" do
110
+
111
+ it "updates the requested <%= file_name %>" do
112
+ <%= class_name %>.should_receive(:get!).with("37").and_return(mock_<%= file_name %>)
113
+ mock_<%= file_name %>.should_receive(:update).with({'these' => 'params'})
114
+ put :update, :id => "37", :<%= file_name %> => {:these => 'params'}
115
+ end
116
+
117
+ it "exposes the requested <%= file_name %> as @<%= file_name %>" do
118
+ <%= class_name %>.stub!(:get!).and_return(mock_<%= file_name %>(:update => true))
119
+ put :update, :id => "1"
120
+ assigns(:<%= file_name %>).should equal(mock_<%= file_name %>)
121
+ end
122
+
123
+ it "redirects to the <%= file_name %>" do
124
+ <%= class_name %>.stub!(:get!).and_return(mock_<%= file_name %>(:update => true))
125
+ put :update, :id => "1"
126
+ response.should redirect_to(<%= table_name.singularize %>_url(mock_<%= file_name %>))
127
+ end
128
+
129
+ end
130
+
131
+ describe "with invalid params" do
132
+
133
+ it "updates the requested <%= file_name %>" do
134
+ <%= class_name %>.should_receive(:get!).with("37").and_return(mock_<%= file_name %>)
135
+ mock_<%= file_name %>.should_receive(:update).with({'these' => 'params'})
136
+ put :update, :id => "37", :<%= file_name %> => {:these => 'params'}
137
+ end
138
+
139
+ it "exposes the <%= file_name %> as @<%= file_name %>" do
140
+ <%= class_name %>.stub!(:get!).and_return(mock_<%= file_name %>(:update => false))
141
+ put :update, :id => "1"
142
+ assigns(:<%= file_name %>).should equal(mock_<%= file_name %>)
143
+ end
144
+
145
+ it "re-renders the 'edit' template" do
146
+ <%= class_name %>.stub!(:get!).and_return(mock_<%= file_name %>(:update => false))
147
+ put :update, :id => "1"
148
+ response.should render_template('edit')
149
+ end
150
+
151
+ end
152
+
153
+ end
154
+
155
+ describe "DELETE destroy" do
156
+
157
+ it "destroys the requested <%= file_name %>" do
158
+ <%= class_name %>.should_receive(:get).with("37").and_return(mock_<%= file_name %>)
159
+ mock_<%= file_name %>.should_receive(:destroy)
160
+ delete :destroy, :id => "37"
161
+ end
162
+
163
+ it "redirects to the <%= table_name %> list" do
164
+ <%= class_name %>.should_receive(:get).with("1").and_return(mock_<%= file_name %>(:destroy => true))
165
+ delete :destroy, :id => "1"
166
+ response.should redirect_to(<%= table_name %>_url)
167
+ end
168
+
169
+ end
170
+
171
+ end
@@ -0,0 +1,25 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../../spec_helper')
2
+
3
+ <% output_attributes = attributes.reject{|attribute| [:datetime, :timestamp, :time, :date].index(attribute.type) } -%>
4
+ describe "/<%= table_name %>/edit.<%= default_file_extension %>" do
5
+ include <%= controller_class_name %>Helper
6
+
7
+ before(:each) do
8
+ assigns[:<%= file_name %>] = @<%= file_name %> = stub_model(<%= class_name %>,
9
+ :new_record? => false<%= output_attributes.empty? ? '' : ',' %>
10
+ <% output_attributes.each_with_index do |attribute, attribute_index| -%>
11
+ :<%= attribute.name %> => <%= attribute.default_value %><%= attribute_index == output_attributes.length - 1 ? '' : ','%>
12
+ <% end -%>
13
+ )
14
+ end
15
+
16
+ it "renders the edit <%= file_name %> form" do
17
+ render
18
+
19
+ response.should have_tag("form[action=#{<%= file_name %>_path(@<%= file_name %>.key)}][method=post]") do
20
+ <% for attribute in output_attributes -%>
21
+ with_tag('<%= attribute.input_type -%>#<%= file_name %>_<%= attribute.name %>[name=?]', "<%= file_name %>[<%= attribute.name %>]")
22
+ <% end -%>
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ require 'datamapper4rails/overlay'
2
+ require 'datamapper4rails/rspec_default_values'
3
+
4
+ class DatamapperScaffoldGenerator < ScaffoldGenerator
5
+
6
+ def manifest
7
+ overlay_dirs.add_generator("datamapper_model")
8
+ overlay_dirs.add_generator("scaffold")
9
+
10
+ logger.warn
11
+ logger.warn
12
+ logger.warn
13
+ logger.warn
14
+ logger.warn " WARNING"
15
+ logger.warn
16
+ logger.warn "fixtures with datamapper do not work"
17
+ logger.warn "and so functional tests do not work"
18
+ logger.warn
19
+ logger.warn
20
+ logger.warn
21
+ logger.warn
22
+
23
+ super
24
+ end
25
+
26
+ def add_options!(opt)
27
+ super
28
+ opt.on("--skip-timestamps",
29
+ "Don't add timestamps for this model") { |v| options[:skip_timestamps] = v }
30
+ end
31
+ end
@@ -0,0 +1,90 @@
1
+ class <%= controller_class_name %>Controller < ApplicationController
2
+
3
+ # GET /<%= table_name %>
4
+ # GET /<%= table_name %>.xml
5
+ def index
6
+ @<%= table_name %> = <%= class_name %>.all()
7
+
8
+ respond_to do |format|
9
+ format.html
10
+ format.xml { render :xml => @<%= table_name %> }
11
+ end
12
+ end
13
+
14
+ # GET /<%= table_name %>/1
15
+ # GET /<%= table_name %>/1.xml
16
+ def show
17
+ @<%= file_name %> = <%= class_name %>.get!(params[:id])
18
+
19
+ respond_to do |format|
20
+ format.html # show.html.erb
21
+ format.xml { render :xml => @<%= file_name %> }
22
+ end
23
+ end
24
+
25
+ # GET /<%= table_name %>/new
26
+ # GET /<%= table_name %>/new.xml
27
+ def new
28
+ @<%= file_name %> = <%= class_name %>.new
29
+
30
+ respond_to do |format|
31
+ format.html # new.html.erb
32
+ format.xml { render :xml => @<%= file_name %> }
33
+ end
34
+ end
35
+
36
+ # GET /<%= table_name %>/1/edit
37
+ def edit
38
+ @<%= file_name %> = <%= class_name %>.get!(params[:id])
39
+ end
40
+
41
+ # POST /<%= table_name %>
42
+ # POST /<%= table_name %>.xml
43
+ def create
44
+ @<%= file_name %> = <%= class_name %>.new(params[:<%= file_name %>])
45
+
46
+ respond_to do |format|
47
+ if @<%= file_name %>.save
48
+ flash[:notice] = <% if options[:i18n] -%>t('<%= plural_name %>.<%= singular_name %>_created')<% else -%>'<%= class_name %> was successfully created.'<% end -%>
49
+
50
+ format.html { redirect_to(<%= file_name %>_url(@<%= file_name %>.id)) }
51
+ format.xml { render :xml => @<%= file_name %>, :status => :created, :location => @<%= file_name %> }
52
+ else
53
+ format.html { render :action => "new" }
54
+ format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
55
+ end
56
+ end
57
+ end
58
+
59
+ # PUT /<%= table_name %>/1
60
+ # PUT /<%= table_name %>/1.xml
61
+ def update
62
+ @<%= file_name %> = <%= class_name %>.get!(params[:id])
63
+
64
+ respond_to do |format|
65
+ if @<%= file_name %>.update(params[:<%= file_name %>])
66
+ flash[:notice] = <% if options[:i18n] -%>t('<%= plural_name %>.<%= singular_name %>_updated')<% else -%>'<%= class_name %> was successfully updated.'<% end -%>
67
+
68
+ format.html { redirect_to(<%= file_name %>_url(@<%= file_name %>.id)) }
69
+ format.xml { head :ok }
70
+ else
71
+ format.html { render :action => "edit" }
72
+ format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
73
+ end
74
+ end
75
+ end
76
+
77
+ # DELETE /<%= table_name %>/1
78
+ # DELETE /<%= table_name %>/1.xml
79
+ def destroy
80
+ @<%= file_name %> = <%= class_name %>.get(params[:id])
81
+ @<%= file_name %>.destroy if @<%= file_name %>
82
+
83
+ respond_to do |format|
84
+ flash[:notice] = <% if options[:i18n] -%>t('<%= plural_name %>.<%= singular_name %>_deleted')<% else -%>'<%= class_name %> was successfully deleted.'<% end -%>
85
+
86
+ format.html { redirect_to(<%= table_name %>_url) }
87
+ format.xml { head :ok }
88
+ end
89
+ end
90
+ end