ixtlan 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +64 -0
- data/README.txt +86 -0
- data/Rakefile +38 -0
- data/generators/ixtlan_datamapper_model/ixtlan_datamapper_model_generator.rb +20 -0
- data/generators/ixtlan_datamapper_model/templates/model.rb +17 -0
- data/generators/ixtlan_datamapper_rspec_model/ixtlan_datamapper_rspec_model_generator.rb +20 -0
- data/generators/ixtlan_datamapper_rspec_model/templates/model_spec.rb +58 -0
- data/generators/ixtlan_datamapper_rspec_scaffold/ixtlan_datamapper_rspec_scaffold_generator.rb +37 -0
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/controller.rb +99 -0
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/controller_spec.rb +206 -0
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/guard.rb +8 -0
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/i18n.rb +11 -0
- data/lib/dm-serializer/common.rb +28 -0
- data/lib/dm-serializer/to_xml.rb +99 -0
- data/lib/dm-serializer/xml_serializers/libxml.rb +42 -0
- data/lib/dm-serializer/xml_serializers/nokogiri.rb +36 -0
- data/lib/dm-serializer/xml_serializers/rexml.rb +30 -0
- data/lib/dm-serializer/xml_serializers.rb +17 -0
- data/lib/dm-serializer.rb +1 -0
- data/lib/ixtlan/audit_config.rb +35 -0
- data/lib/ixtlan/cms_script.rb +29 -0
- data/lib/ixtlan/controllers/texts_controller.rb +65 -0
- data/lib/ixtlan/digest.rb +15 -0
- data/lib/ixtlan/error_notifier/error_notification.rhtml +1 -0
- data/lib/ixtlan/guard.rb +125 -0
- data/lib/ixtlan/logger_config.rb +65 -0
- data/lib/ixtlan/models/authentication.rb +30 -0
- data/lib/ixtlan/models/configuration.rb +74 -0
- data/lib/ixtlan/models/configuration_locale.rb +19 -0
- data/lib/ixtlan/models/group.rb +69 -0
- data/lib/ixtlan/models/group_locale_user.rb +22 -0
- data/lib/ixtlan/models/group_user.rb +39 -0
- data/lib/ixtlan/models/locale.rb +37 -0
- data/lib/ixtlan/models/permission.rb +29 -0
- data/lib/ixtlan/models/phrase.rb +71 -0
- data/lib/ixtlan/models/role.rb +35 -0
- data/lib/ixtlan/models/text.rb +140 -0
- data/lib/ixtlan/models/translation.rb +40 -0
- data/lib/ixtlan/models/user.rb +112 -0
- data/lib/ixtlan/models/word.rb +12 -0
- data/lib/ixtlan/models.rb +13 -0
- data/lib/ixtlan/modified_by.rb +80 -0
- data/lib/ixtlan/monkey_patches.rb +38 -0
- data/lib/ixtlan/optimistic_persistence.rb +20 -0
- data/lib/ixtlan/optimistic_persistence_module.rb +22 -0
- data/lib/ixtlan/optimistic_persistence_validation.rb +21 -0
- data/lib/ixtlan/passwords.rb +19 -0
- data/lib/ixtlan/rails/audit.rb +22 -0
- data/lib/ixtlan/rails/error_handling.rb +130 -0
- data/lib/ixtlan/rails/guard.rb +11 -0
- data/lib/ixtlan/rails/session_timeout.rb +93 -0
- data/lib/ixtlan/rails/timestamps_modified_by_filter.rb +33 -0
- data/lib/ixtlan/rails/unrestful_authentication.rb +137 -0
- data/lib/ixtlan/rolling_file.rb +61 -0
- data/lib/ixtlan/session.rb +18 -0
- data/lib/ixtlan/user_logger.rb +49 -0
- data/lib/ixtlan/version.rb +3 -0
- data/lib/ixtlan.rb +2 -0
- data/lib/models.rb +14 -0
- data/spec/authentication_spec.rb +30 -0
- data/spec/guard_spec.rb +125 -0
- data/spec/guards/samples.rb +12 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +170 -0
- metadata +210 -0
data/Manifest.txt
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
generators/ixtlan_datamapper_model/ixtlan_datamapper_model_generator.rb
|
2
|
+
generators/ixtlan_datamapper_model/templates/model.rb
|
3
|
+
generators/ixtlan_datamapper_rspec_model/ixtlan_datamapper_rspec_model_generator.rb
|
4
|
+
generators/ixtlan_datamapper_rspec_model/templates/model_spec.rb
|
5
|
+
generators/ixtlan_datamapper_rspec_scaffold/ixtlan_datamapper_rspec_scaffold_generator.rb
|
6
|
+
generators/ixtlan_datamapper_rspec_scaffold/templates/controller.rb
|
7
|
+
generators/ixtlan_datamapper_rspec_scaffold/templates/controller_spec.rb
|
8
|
+
generators/ixtlan_datamapper_rspec_scaffold/templates/guard.rb
|
9
|
+
generators/ixtlan_datamapper_rspec_scaffold/templates/i18n.rb
|
10
|
+
lib/models.rb
|
11
|
+
lib/ixtlan.rb
|
12
|
+
lib/dm-serializer.rb
|
13
|
+
lib/dm-serializer/xml_serializers/libxml.rb
|
14
|
+
lib/dm-serializer/xml_serializers/nokogiri.rb
|
15
|
+
lib/dm-serializer/xml_serializers/rexml.rb
|
16
|
+
lib/dm-serializer/common.rb
|
17
|
+
lib/dm-serializer/xml_serializers.rb
|
18
|
+
lib/dm-serializer/to_xml.rb
|
19
|
+
lib/ixtlan/models/group_locale_user.rb
|
20
|
+
lib/ixtlan/models/role.rb
|
21
|
+
lib/ixtlan/models/phrase.rb
|
22
|
+
lib/ixtlan/models/translation.rb
|
23
|
+
lib/ixtlan/models/user.rb
|
24
|
+
lib/ixtlan/models/permission.rb
|
25
|
+
lib/ixtlan/models/locale.rb
|
26
|
+
lib/ixtlan/models/configuration_locale.rb
|
27
|
+
lib/ixtlan/models/word.rb
|
28
|
+
lib/ixtlan/models/configuration.rb
|
29
|
+
lib/ixtlan/models/authentication.rb
|
30
|
+
lib/ixtlan/models/text.rb
|
31
|
+
lib/ixtlan/models/group_user.rb
|
32
|
+
lib/ixtlan/models/group.rb
|
33
|
+
lib/ixtlan/rolling_file.rb
|
34
|
+
lib/ixtlan/cms_script.rb
|
35
|
+
lib/ixtlan/logger_config.rb
|
36
|
+
lib/ixtlan/models.rb
|
37
|
+
lib/ixtlan/audit_config.rb
|
38
|
+
lib/ixtlan/session.rb
|
39
|
+
lib/ixtlan/optimistic_persistence.rb
|
40
|
+
lib/ixtlan/monkey_patches.rb
|
41
|
+
lib/ixtlan/modified_by.rb
|
42
|
+
lib/ixtlan/optimistic_persistence_module.rb
|
43
|
+
lib/ixtlan/optimistic_persistence_validation.rb
|
44
|
+
lib/ixtlan/error_notifier/error_notification.rhtml
|
45
|
+
lib/ixtlan/controllers/texts_controller.rb
|
46
|
+
lib/ixtlan/guard.rb
|
47
|
+
lib/ixtlan/rails/audit.rb
|
48
|
+
lib/ixtlan/rails/error_handling.rb
|
49
|
+
lib/ixtlan/rails/unrestful_authentication.rb
|
50
|
+
lib/ixtlan/rails/session_timeout.rb
|
51
|
+
lib/ixtlan/rails/timestamps_modified_by_filter.rb
|
52
|
+
lib/ixtlan/rails/guard.rb
|
53
|
+
lib/ixtlan/passwords.rb
|
54
|
+
lib/ixtlan/digest.rb
|
55
|
+
lib/ixtlan/version.rb
|
56
|
+
lib/ixtlan/user_logger.rb
|
57
|
+
Manifest.txt
|
58
|
+
Rakefile
|
59
|
+
README.txt
|
60
|
+
spec/authentication_spec.rb
|
61
|
+
spec/guard_spec.rb
|
62
|
+
spec/guards/samples.rb
|
63
|
+
spec/spec_helper.rb
|
64
|
+
spec/spec.opts
|
data/README.txt
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
= ixtlan core
|
2
|
+
|
3
|
+
* http://github.com/mkristian/ixtlan-core
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
this is set of rails and datamapper plugins for setting up a little more advanced rails application then the default rails generator does. the focus is on security and privacy as well a complete restful xml support.
|
8
|
+
|
9
|
+
=== features
|
10
|
+
|
11
|
+
* usermanagement: user, group, locale
|
12
|
+
|
13
|
+
* authentication: session based authentication for both html as well restful xml
|
14
|
+
|
15
|
+
* authorization: each controller/action pair has a set of allowed roles
|
16
|
+
|
17
|
+
* privacy: configurable duration for logfiles carrying user specific data. error logs are dumped (complete environment including user specific data as well) and the file location is sent as notification
|
18
|
+
|
19
|
+
* session idle timeout: configurable server side session idle timeout
|
20
|
+
|
21
|
+
* audit: a simple log file which documents the action of a user - one action per line
|
22
|
+
|
23
|
+
* optimistic transaction: through an exception on modification of stale resources
|
24
|
+
|
25
|
+
* easy add modified_by attributes to a resource and ensure the user gets set before saving such a resource
|
26
|
+
|
27
|
+
* logger configuration tries to unify logging
|
28
|
+
|
29
|
+
* basic scaffold like html interface for user,group,locale
|
30
|
+
|
31
|
+
* rails template setting up such an application - works for both ruby as well jruby
|
32
|
+
|
33
|
+
* http cache headers so that no data gets save on any proxy or filesystem (as long the user is logged in)
|
34
|
+
|
35
|
+
* global config: extra configuration file which can carry the all the production passwords and can be left out from the (public) version control system: config/preinitializer.rb for rails and config/global.yml
|
36
|
+
|
37
|
+
=== TODOs
|
38
|
+
|
39
|
+
* session timeout on html pages so the browser displays the login page after timetout (little modification of the layout.html.erb)
|
40
|
+
|
41
|
+
* user, group, locale to work also with ldap
|
42
|
+
|
43
|
+
* html interface for configuration, user profile
|
44
|
+
|
45
|
+
* setup database specific logger for data_objects - each driver has its own logger
|
46
|
+
|
47
|
+
* maintanance mode: allow only users who belong to the superuser group
|
48
|
+
|
49
|
+
* change the db config to have #{RAILS_ROOT} in front of relative filenames to work inside an servlet engine (ixtlan_rails_templates.rb)
|
50
|
+
|
51
|
+
* locale binding to user/group
|
52
|
+
|
53
|
+
== user management and authorization
|
54
|
+
|
55
|
+
each user can belong to one or more groups, each user/group pair can belong to one or more locales. this part can be configured by an admin by changing resource relationships.
|
56
|
+
|
57
|
+
=== authorization
|
58
|
+
|
59
|
+
each controller/action pair has a set of allowed roles. authorization is granted if on of roles match with one of the groups of the current user (logged in user). this is done by a before filter in rails: guard. the user interface can introspect the guard to allow the user only the actions which s/he actually can be performe. in case some actions needs to verify the locale binding a specialized before filter needs to be implemented.
|
60
|
+
|
61
|
+
the roles are currently hardcoded in app/guards/XYZ_guard.rb - one guard for each controller.
|
62
|
+
|
63
|
+
== LICENSE:
|
64
|
+
|
65
|
+
(The MIT License)
|
66
|
+
|
67
|
+
Copyright (c) 2009 Kristian Meier
|
68
|
+
|
69
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
70
|
+
a copy of this software and associated documentation files (the
|
71
|
+
'Software'), to deal in the Software without restriction, including
|
72
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
73
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
74
|
+
permit persons to whom the Software is furnished to do so, subject to
|
75
|
+
the following conditions:
|
76
|
+
|
77
|
+
The above copyright notice and this permission notice shall be
|
78
|
+
included in all copies or substantial portions of the Software.
|
79
|
+
|
80
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
81
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
82
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
83
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
84
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
85
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
86
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/ixtlan/version.rb'
|
6
|
+
|
7
|
+
require 'spec'
|
8
|
+
require 'spec/rake/spectask'
|
9
|
+
require 'pathname'
|
10
|
+
require 'yard'
|
11
|
+
|
12
|
+
Hoe.spec('ixtlan') do |p|
|
13
|
+
p.developer('mkristian', 'm.kristian@web.de')
|
14
|
+
p.extra_deps = [['dm-core', '~>0.10.1'], ['dm-validations', '~>0.10.1'], ['dm-timestamps', '~>0.10.1'], ['dm-migrations', '~>0.10.1'], ['slf4r', '~>0.2.0'], ['datamapper4rails', '~>0.3.2'],['rack-datamapper', '~>0.2.5'], ['logging', '~>1.2.3']]
|
15
|
+
p.rspec_options << '--options' << 'spec/spec.opts'
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Install the package as a gem.'
|
19
|
+
task :install => [:clean, :package] do
|
20
|
+
gem = Dir['pkg/*.gem'].first
|
21
|
+
sh "gem install --local #{gem} --no-ri --no-rdoc"
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'generate rails using all generators and run the specs'
|
25
|
+
task :integration_tests => [:spec, :install] do
|
26
|
+
require 'datamapper4rails/integration_test'
|
27
|
+
Datamapper4Rails::IntegrationTest.new do |t|
|
28
|
+
t.directory = 'temp'
|
29
|
+
t.rails_template = 'ixtlan_rails_templates.rb'
|
30
|
+
t.generate "ixtlan_datamapper_model name name:string"
|
31
|
+
t.generate "ixtlan_datamapper_rspec_model domain name:string"
|
32
|
+
t.generate "ixtlan_datamapper_rspec_scaffold word name:string"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
YARD::Rake::YardocTask.new
|
37
|
+
|
38
|
+
# vim: syntax=Ruby
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rails_generator/generators/components/model/model_generator'
|
2
|
+
require 'active_record'
|
3
|
+
require 'datamapper4rails/overlay'
|
4
|
+
|
5
|
+
class IxtlanDatamapperModelGenerator < DatamapperModelGenerator
|
6
|
+
|
7
|
+
def manifest
|
8
|
+
overlay_dirs.add_generator("datamapper_model")
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_options!(opt)
|
13
|
+
opt.separator ''
|
14
|
+
opt.separator 'Options:'
|
15
|
+
opt.on("--skip-timestamps",
|
16
|
+
"Don't add timestamps for this model") { |v| options[:skip_timestamps] = v }
|
17
|
+
opt.on("--skip-modified-by",
|
18
|
+
"Don't add modified_by references for this model") { |v| options[:skip_modified_by] = v }
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class <%= class_name %>
|
2
|
+
include DataMapper::Resource
|
3
|
+
|
4
|
+
property :id, Serial
|
5
|
+
<% Array(attributes).each do |attribute| -%>
|
6
|
+
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 -%>
|
7
|
+
|
8
|
+
<% end -%>
|
9
|
+
<% unless options[:skip_timestamps] -%>
|
10
|
+
timestamps :at
|
11
|
+
<% end -%>
|
12
|
+
|
13
|
+
<% unless options[:skip_modified_by] -%>
|
14
|
+
modified_by "Ixtlan::Models::User"
|
15
|
+
<% end -%>
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rails_generator/generators/components/model/model_generator'
|
2
|
+
require 'active_record'
|
3
|
+
require 'datamapper4rails/overlay'
|
4
|
+
|
5
|
+
class IxtlanDatamapperRspecModelGenerator < DatamapperRspecModelGenerator
|
6
|
+
|
7
|
+
def manifest
|
8
|
+
overlay_dirs.add_generator("ixtlan_datamapper_model")
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_options!(opt)
|
13
|
+
opt.separator ''
|
14
|
+
opt.separator 'Options:'
|
15
|
+
opt.on("--skip-timestamps",
|
16
|
+
"Don't add timestamps for this model") { |v| options[:skip_timestamps] = v }
|
17
|
+
opt.on("--skip-modified-by",
|
18
|
+
"Don't add modified_by references for this model") { |v| options[:skip_modified_by] = v }
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper')
|
2
|
+
|
3
|
+
describe <%= class_name %> do
|
4
|
+
before(:each) do
|
5
|
+
<% unless options[:skip_modified_by] -%>
|
6
|
+
user = Ixtlan::Models::User.first
|
7
|
+
unless user
|
8
|
+
user = Ixtlan::Models::User.new(:login => 'root', :email => 'root@exmple.com', :name => 'Superuser', :language => 'en', :id => 1, :created_at => DateTime.now, :updated_at => DateTime.now)
|
9
|
+
user.created_by_id = 1
|
10
|
+
user.updated_by_id = 1
|
11
|
+
user.save!
|
12
|
+
end
|
13
|
+
<% end -%>
|
14
|
+
@valid_attributes = {
|
15
|
+
<% unless options[:skip_modified_by] -%>
|
16
|
+
:current_user => user,
|
17
|
+
<% end -%>
|
18
|
+
<% attributes.each_with_index do |attribute, attribute_index| -%>
|
19
|
+
:<%= attribute.name %> => <%= attribute.default_value %><%= attribute_index == attributes.length - 1 ? '' : ','%>
|
20
|
+
<% end -%>
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should create a new instance given valid attributes" do
|
25
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes)
|
26
|
+
<%= singular_name %>.valid?.should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
<% attributes.each do |attribute| -%>
|
30
|
+
it "should require <%= attribute.name %>" do
|
31
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => nil))
|
32
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
33
|
+
end
|
34
|
+
|
35
|
+
<% if [:string, :text, :slug].member? attribute.type -%>
|
36
|
+
it 'should not match <%= attribute.name %>' do
|
37
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "<script" ))
|
38
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
39
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "sc'ript" ))
|
40
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
41
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "scr&ipt" ))
|
42
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
43
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => 'scr"ipt' ))
|
44
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
45
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "script>" ))
|
46
|
+
<%= singular_name %>.errors.on(:<%= attribute.name %>).should_not == nil
|
47
|
+
end
|
48
|
+
|
49
|
+
<% elsif [:integer, :big_decimal, :float].member? attribute.type %>
|
50
|
+
it "should be numerical <%= attribute.name %>" do
|
51
|
+
<%= singular_name %> = <%= class_name %>.create(@valid_attributes.merge(:<%= attribute.name %> => "none-numberic" ))
|
52
|
+
<%= singular_name %>.<%= attribute.name %>.to_i.should == 0
|
53
|
+
<%= singular_name %>.errors.size.should == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
<% end -%>
|
57
|
+
<% end -%>
|
58
|
+
end
|
data/generators/ixtlan_datamapper_rspec_scaffold/ixtlan_datamapper_rspec_scaffold_generator.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'datamapper4rails/overlay'
|
2
|
+
require 'datamapper4rails/rspec_default_values'
|
3
|
+
|
4
|
+
class IxtlanDatamapperRspecScaffoldGenerator < DatamapperRspecScaffoldGenerator
|
5
|
+
|
6
|
+
def manifest
|
7
|
+
overlay_dirs.add_generator("ixtlan_datamapper_model")
|
8
|
+
overlay_dirs.add_generator("ixtlan_datamapper_rspec_model")
|
9
|
+
overlay_dirs.add_generator("datamapper_rspec_scaffold")
|
10
|
+
|
11
|
+
m = super
|
12
|
+
|
13
|
+
unless options[:skip_guard]
|
14
|
+
m.directory(File.join('app/guards', controller_class_path))
|
15
|
+
m.template 'guard.rb', File.join('app/guards', controller_class_path, "#{table_name}_guard.rb")
|
16
|
+
end
|
17
|
+
|
18
|
+
if options[:i18n]
|
19
|
+
m.directory(File.join('config/locales', controller_class_path))
|
20
|
+
m.template 'i18n.rb', File.join('config/locales', controller_class_path, "#{table_name}.yml")
|
21
|
+
end
|
22
|
+
|
23
|
+
m
|
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
|
+
opt.on("--skip-modified-by",
|
31
|
+
"Don't add modified_by references for this model") { |v| options[:skip_modified_by] = v }
|
32
|
+
opt.on("--skip-guard",
|
33
|
+
"Don't add guards for the actions on this model") { |v| options[:add_guard] = v }
|
34
|
+
opt.on("--i18n",
|
35
|
+
"Use i18n keys instead of text") { |v| options[:i18n] = v }
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,99 @@
|
|
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
|
+
<% unless options[:skip_modified_by] -%>
|
46
|
+
@<%= file_name %>.current_user = current_user
|
47
|
+
<% end -%>
|
48
|
+
|
49
|
+
respond_to do |format|
|
50
|
+
if @<%= file_name %>.save
|
51
|
+
flash[:notice] = <% if options[:i18n] -%>t('<%= plural_name %>.<%= singular_name %>_created')<% else -%>'<%= class_name %> was successfully created.'<% end -%>
|
52
|
+
|
53
|
+
format.html { redirect_to(<%= file_name %>_url(@<%= file_name %>.id)) }
|
54
|
+
format.xml { render :xml => @<%= file_name %>, :status => :created, :location => <%= file_name %>_url(@<%= file_name %>.id) + ".xml" }
|
55
|
+
else
|
56
|
+
format.html { render :action => "new" }
|
57
|
+
format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# PUT /<%= table_name %>/1
|
63
|
+
# PUT /<%= table_name %>/1.xml
|
64
|
+
def update
|
65
|
+
@<%= file_name %> = <%= class_name %>.get!(params[:id])
|
66
|
+
<% unless options[:skip_modified_by] -%>
|
67
|
+
@<%= file_name %>.current_user = current_user
|
68
|
+
<% end -%>
|
69
|
+
|
70
|
+
respond_to do |format|
|
71
|
+
if @<%= file_name %>.update(params[:<%= file_name %>]) or not @<%= file_name %>.dirty?
|
72
|
+
flash[:notice] = <% if options[:i18n] -%>t('<%= plural_name %>.<%= singular_name %>_updated')<% else -%>'<%= class_name %> was successfully updated.'<% end -%>
|
73
|
+
|
74
|
+
format.html { redirect_to(<%= file_name %>_url(@<%= file_name %>.id)) }
|
75
|
+
format.xml { render :xml => @<%= file_name %> }
|
76
|
+
else
|
77
|
+
format.html { render :action => "edit" }
|
78
|
+
format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# DELETE /<%= table_name %>/1
|
84
|
+
# DELETE /<%= table_name %>/1.xml
|
85
|
+
def destroy
|
86
|
+
@<%= file_name %> = <%= class_name %>.get(params[:id])
|
87
|
+
<% unless options[:skip_modified_by] -%>
|
88
|
+
@<%= file_name %>.current_user = current_user
|
89
|
+
<% end -%>
|
90
|
+
@<%= file_name %>.destroy if @<%= file_name %>
|
91
|
+
|
92
|
+
respond_to do |format|
|
93
|
+
flash[:notice] = <% if options[:i18n] -%>t('<%= plural_name %>.<%= singular_name %>_deleted')<% else -%>'<%= class_name %> was successfully deleted.'<% end -%>
|
94
|
+
|
95
|
+
format.html { redirect_to(<%= table_name %>_url) }
|
96
|
+
format.xml { head :ok }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,206 @@
|
|
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
|
+
def mock_array(*args)
|
10
|
+
a = args
|
11
|
+
def a.model
|
12
|
+
<%= class_name %>
|
13
|
+
end
|
14
|
+
a
|
15
|
+
end
|
16
|
+
|
17
|
+
def mock_arguments(merge = {})
|
18
|
+
args = merge
|
19
|
+
<% unless options[:skip_modified_by] -%>
|
20
|
+
args.merge!(:current_user= => nil)
|
21
|
+
<% end -%>
|
22
|
+
<% unless options[:skip_audit] -%>
|
23
|
+
args.merge!(:model => <%= class_name %>, :key => 12)
|
24
|
+
<% end -%>
|
25
|
+
args
|
26
|
+
end
|
27
|
+
|
28
|
+
<% unless options[:skip_guard] -%>
|
29
|
+
before(:each) do
|
30
|
+
user = Ixtlan::Models::User.new(:id => 1, :login => 'root')
|
31
|
+
def user.groups
|
32
|
+
[Ixtlan::Models::Group.new(:name => "root")]
|
33
|
+
end
|
34
|
+
controller.send(:current_user=, user)
|
35
|
+
mock_configuration = mock_model(Ixtlan::Models::Configuration,{})
|
36
|
+
Ixtlan::Models::Configuration.should_receive(:instance).any_number_of_times.and_return(mock_configuration)
|
37
|
+
mock_configuration.should_receive(:session_idle_timeout).any_number_of_times.and_return(1)
|
38
|
+
end
|
39
|
+
<% end -%>
|
40
|
+
|
41
|
+
describe "GET index" do
|
42
|
+
|
43
|
+
it "exposes all <%= table_name %> as @<%= table_name %>" do
|
44
|
+
<%= class_name %>.should_receive(:all).and_return(mock_array(mock_<%= file_name %>))
|
45
|
+
get :index
|
46
|
+
assigns[:<%= table_name %>].should == mock_array(mock_<%= file_name %>)
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "with mime type of xml" do
|
50
|
+
|
51
|
+
it "renders all <%= table_name.pluralize %> as xml" do
|
52
|
+
<%= class_name %>.should_receive(:all).and_return(<%= file_name.pluralize %> = mock_array("Array of <%= class_name.pluralize %>"))
|
53
|
+
<%= file_name.pluralize %>.should_receive(:to_xml).and_return("generated XML")
|
54
|
+
get :index, :format => 'xml'
|
55
|
+
response.body.should == "generated XML"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "GET show" do
|
63
|
+
|
64
|
+
it "exposes the requested <%= file_name %> as @<%= file_name %>" do
|
65
|
+
<%= class_name %>.should_receive(:get!).with("37").and_return(mock_<%= file_name %>(mock_arguments))
|
66
|
+
get :show, :id => "37"
|
67
|
+
assigns[:<%= file_name %>].should equal(mock_<%= file_name %>)
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "with mime type of xml" do
|
71
|
+
|
72
|
+
it "renders the requested <%= file_name %> as xml" do
|
73
|
+
<%= class_name %>.should_receive(:get!).with("37").and_return(mock_<%= file_name %>(mock_arguments))
|
74
|
+
mock_<%= file_name %>.should_receive(:to_xml).and_return("generated XML")
|
75
|
+
get :show, :id => "37", :format => 'xml'
|
76
|
+
response.body.should == "generated XML"
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "GET new" do
|
84
|
+
|
85
|
+
it "exposes a new <%= file_name %> as @<%= file_name %>" do
|
86
|
+
<%= class_name %>.should_receive(:new).and_return(mock_<%= file_name %>(mock_arguments))
|
87
|
+
get :new
|
88
|
+
assigns[:<%= file_name %>].should equal(mock_<%= file_name %>)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "GET edit" do
|
94
|
+
|
95
|
+
it "exposes the requested <%= file_name %> as @<%= file_name %>" do
|
96
|
+
<%= class_name %>.should_receive(:get!).with("37").and_return(mock_<%= file_name %>(mock_arguments))
|
97
|
+
get :edit, :id => "37"
|
98
|
+
assigns[:<%= file_name %>].should equal(mock_<%= file_name %>)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "POST create" do
|
104
|
+
|
105
|
+
describe "with valid params" do
|
106
|
+
|
107
|
+
it "exposes a newly created <%= file_name %> as @<%= file_name %>" do
|
108
|
+
<%= class_name %>.should_receive(:new).with({'these' => 'params'}).and_return(mock_<%= file_name %>(mock_arguments(:save => true)))
|
109
|
+
post :create, :<%= file_name %> => {:these => 'params'}
|
110
|
+
assigns(:<%= file_name %>).should equal(mock_<%= file_name %>)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "redirects to the created <%= file_name %>" do
|
114
|
+
<%= class_name %>.stub!(:new).and_return(mock_<%= file_name %>(mock_arguments(:save => true)))
|
115
|
+
post :create, :<%= file_name %> => {}
|
116
|
+
response.should redirect_to(<%= table_name.singularize %>_url(mock_<%= file_name %>))
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "with invalid params" do
|
122
|
+
|
123
|
+
it "exposes a newly created but unsaved <%= file_name %> as @<%= file_name %>" do
|
124
|
+
<%= class_name %>.stub!(:new).with({'these' => 'params'}).and_return(mock_<%= file_name %>(mock_arguments(:save => false)))
|
125
|
+
post :create, :<%= file_name %> => {:these => 'params'}
|
126
|
+
assigns(:<%= file_name %>).should equal(mock_<%= file_name %>)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "re-renders the 'new' template" do
|
130
|
+
<%= class_name %>.stub!(:new).and_return(mock_<%= file_name %>(mock_arguments(:save => false)))
|
131
|
+
post :create, :<%= file_name %> => {}
|
132
|
+
response.should render_template('new')
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "PUT udpate" do
|
140
|
+
|
141
|
+
describe "with valid params" do
|
142
|
+
|
143
|
+
it "updates the requested <%= file_name %>" do
|
144
|
+
<%= class_name %>.should_receive(:get!).with("37").and_return(mock_<%= file_name %>(mock_arguments))
|
145
|
+
mock_<%= file_name %>.should_receive(:update).with({'these' => 'params'})
|
146
|
+
mock_<%= file_name %>.should_receive(:dirty?)
|
147
|
+
put :update, :id => "37", :<%= file_name %> => {:these => 'params'}
|
148
|
+
end
|
149
|
+
|
150
|
+
it "exposes the requested <%= file_name %> as @<%= file_name %>" do
|
151
|
+
<%= class_name %>.stub!(:get!).and_return(mock_<%= file_name %>(mock_arguments(:update => true)))
|
152
|
+
put :update, :id => "1"
|
153
|
+
assigns(:<%= file_name %>).should equal(mock_<%= file_name %>)
|
154
|
+
end
|
155
|
+
|
156
|
+
it "redirects to the <%= file_name %>" do
|
157
|
+
<%= class_name %>.stub!(:get!).and_return(mock_<%= file_name %>(mock_arguments(:update => true)))
|
158
|
+
put :update, :id => "1"
|
159
|
+
response.should redirect_to(<%= table_name.singularize %>_url(mock_<%= file_name %>))
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "with invalid params" do
|
165
|
+
|
166
|
+
it "updates the requested <%= file_name %>" do
|
167
|
+
<%= class_name %>.should_receive(:get!).with("37").and_return(mock_<%= file_name %>(mock_arguments))
|
168
|
+
mock_<%= file_name %>.should_receive(:update).with({'these' => 'params'})
|
169
|
+
mock_<%= file_name %>.should_receive(:dirty?)
|
170
|
+
put :update, :id => "37", :<%= file_name %> => {:these => 'params'}
|
171
|
+
end
|
172
|
+
|
173
|
+
it "exposes the <%= file_name %> as @<%= file_name %>" do
|
174
|
+
<%= class_name %>.stub!(:get!).and_return(mock_<%= file_name %>(mock_arguments(:update => false)))
|
175
|
+
mock_<%= file_name %>.should_receive(:dirty?)
|
176
|
+
put :update, :id => "1"
|
177
|
+
assigns(:<%= file_name %>).should equal(mock_<%= file_name %>)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "re-renders the 'edit' template" do
|
181
|
+
<%= class_name %>.stub!(:get!).and_return(mock_<%= file_name %>(mock_arguments(:update => false, :dirty? => true)))
|
182
|
+
put :update, :id => "1"
|
183
|
+
response.should render_template('edit')
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "DELETE destroy" do
|
191
|
+
|
192
|
+
it "destroys the requested <%= file_name %>" do
|
193
|
+
<%= class_name %>.should_receive(:get).with("37").and_return(mock_<%= file_name %>(mock_arguments))
|
194
|
+
mock_<%= file_name %>.should_receive(:destroy)
|
195
|
+
delete :destroy, :id => "37"
|
196
|
+
end
|
197
|
+
|
198
|
+
it "redirects to the <%= table_name %> list" do
|
199
|
+
<%= class_name %>.should_receive(:get).with("1").and_return(mock_<%= file_name %>(mock_arguments(:destroy => true)))
|
200
|
+
delete :destroy, :id => "1"
|
201
|
+
response.should redirect_to(<%= table_name %>_url)
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
en:
|
2
|
+
<%= plural_name %>:
|
3
|
+
<%= singular_name %>_created: <%= class_name %> was successfully created.
|
4
|
+
<%= singular_name %>_updated: <%= class_name %> was successfully updated.
|
5
|
+
<%= singular_name %>_deleted: <%= class_name %> was successfully deleted.
|
6
|
+
new_<%= singular_name %>: new <%= singular_name %>
|
7
|
+
<%= singular_name %>: <%= singular_name %>
|
8
|
+
list: <%= singular_name %>list
|
9
|
+
<% for attribute in attributes -%>
|
10
|
+
<%= attribute.column.name %>: <%= attribute.column.human_name %>
|
11
|
+
<% end -%>
|