fortitude 0.9.5-java → 0.9.6-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +11 -0
- data/CONTRIBUTORS.md +4 -0
- data/fortitude.gemspec +1 -1
- data/lib/fortitude/rails/helpers.rb +20 -1
- data/lib/fortitude/rails/railtie.rb +2 -0
- data/lib/fortitude/rails/yielded_object_outputter.rb +3 -0
- data/lib/fortitude/version.rb +1 -1
- data/lib/fortitude/widget/integration.rb +15 -1
- data/lib/rails/generators/fortitude/base_view/base_view_generator.rb +13 -0
- data/lib/rails/generators/fortitude/base_view/templates/views_base.rb +230 -0
- data/lib/rails/generators/fortitude/controller/controller_generator.rb +18 -0
- data/lib/rails/generators/fortitude/controller/templates/view.html.rb +6 -0
- data/lib/rails/generators/fortitude/controller/templates/views_base.rb +230 -0
- data/lib/rails/generators/fortitude/mailer/mailer_generator.rb +26 -0
- data/lib/rails/generators/fortitude/mailer/templates/layout.html.rb +9 -0
- data/lib/rails/generators/fortitude/mailer/templates/view.html.rb +12 -0
- data/lib/rails/generators/fortitude/scaffold/scaffold_generator.rb +29 -0
- data/lib/rails/generators/fortitude/scaffold/templates/edit.html.rb +13 -0
- data/lib/rails/generators/fortitude/scaffold/templates/form.html.rb +44 -0
- data/lib/rails/generators/fortitude/scaffold/templates/index.html.rb +45 -0
- data/lib/rails/generators/fortitude/scaffold/templates/new.html.rb +11 -0
- data/lib/rails/generators/fortitude/scaffold/templates/show.html.rb +18 -0
- data/spec/rails/complex_helpers_system_spec.rb +6 -0
- data/spec/rails/data_passing_system_spec.rb +4 -0
- data/spec/rails/generators_system_spec.rb +166 -0
- data/spec/rails/templates/complex_helpers_system_spec/app/controllers/carryover_controller.rb +11 -0
- data/spec/rails/templates/complex_helpers_system_spec/app/views/carryover/show.html.rb +9 -0
- data/spec/rails/templates/complex_helpers_system_spec/app/views/complex_helpers_system_spec/form_for_test.rb +2 -0
- data/spec/rails/templates/complex_helpers_system_spec/config/routes.rb +6 -0
- data/spec/rails/templates/data_passing_system_spec/app/controllers/data_passing_system_spec_controller.rb +5 -0
- data/spec/rails/templates/data_passing_system_spec/app/views/data_passing_system_spec/nil_data_widget.rb +8 -0
- data/spec/rails/templates/generators_system_spec/config/environments/development.rb +39 -0
- metadata +30 -4
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rails/generators/erb/mailer/mailer_generator'
|
2
|
+
|
3
|
+
module Fortitude
|
4
|
+
module Generators
|
5
|
+
class MailerGenerator < ::Erb::Generators::MailerGenerator
|
6
|
+
source_root File.expand_path("../templates", __FILE__)
|
7
|
+
|
8
|
+
def create_view_base
|
9
|
+
generate "fortitude:base_view"
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
def handler
|
14
|
+
:rb
|
15
|
+
end
|
16
|
+
|
17
|
+
def formats
|
18
|
+
[:html]
|
19
|
+
end
|
20
|
+
|
21
|
+
def format
|
22
|
+
:html
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%
|
2
|
+
our_class_name = class_name.camelize
|
3
|
+
our_class_name += "Mailer" if @path =~ %r{_mailer/}
|
4
|
+
-%>
|
5
|
+
class Views::<%= our_class_name %>::<%= @action.camelize %> < Views::Base
|
6
|
+
needs :greeting
|
7
|
+
|
8
|
+
def content
|
9
|
+
h1 "<%= class_name %>#<%= @action %>"
|
10
|
+
p "#{greeting}, find me in <%= @path %>"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rails/generators/erb/scaffold/scaffold_generator'
|
2
|
+
|
3
|
+
module Fortitude
|
4
|
+
module Generators
|
5
|
+
class ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
6
|
+
source_root File.join(File.dirname(__FILE__), 'templates')
|
7
|
+
|
8
|
+
def copy_view_files
|
9
|
+
available_views.each do |view|
|
10
|
+
filename = filename_with_extensions(view)
|
11
|
+
template "#{view}.html.rb", File.join("app/views", controller_file_path, filename)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_view_base
|
16
|
+
generate "fortitude:base_view"
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
def available_views
|
21
|
+
%w(index new show edit form)
|
22
|
+
end
|
23
|
+
|
24
|
+
def handler
|
25
|
+
:rb
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Views::<%= plural_table_name.camelize %>::Edit < Views::Base
|
2
|
+
needs :<%= singular_table_name %>
|
3
|
+
|
4
|
+
def content
|
5
|
+
h1 "Editing <%= singular_table_name.titleize %>"
|
6
|
+
|
7
|
+
widget Views::<%= plural_table_name.camelize %>::Form, :<%= singular_table_name %> => <%= singular_table_name %>
|
8
|
+
|
9
|
+
link_to 'Show', <%= singular_table_name %>
|
10
|
+
text " | "
|
11
|
+
link_to 'Back', <%= index_helper %>_path
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Views::<%= plural_table_name.camelize %>::Form < Views::Base
|
2
|
+
needs :<%= singular_table_name %>
|
3
|
+
|
4
|
+
def content
|
5
|
+
form_for(<%= singular_table_name %>) do |f|
|
6
|
+
if <%= singular_table_name %>.errors.any?
|
7
|
+
div(:id => :error_explanation) {
|
8
|
+
h2 {
|
9
|
+
text pluralize(<%= singular_table_name %>.errors.count, "error")
|
10
|
+
text " prohibited this <%= singular_table_name %> from being saved:"
|
11
|
+
}
|
12
|
+
|
13
|
+
ul {
|
14
|
+
<%= singular_table_name %>.errors.full_messages.each do |message|
|
15
|
+
li message
|
16
|
+
end
|
17
|
+
}
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
<% attributes.each do |attribute| -%>
|
22
|
+
<% if attribute.respond_to?(:password_digest?) && attribute.password_digest? -%>
|
23
|
+
div(:class => :field) {
|
24
|
+
f.label :password
|
25
|
+
f.password_field :password
|
26
|
+
}
|
27
|
+
|
28
|
+
div(:class => :field) {
|
29
|
+
f.label :password_confirmation
|
30
|
+
f.password_field :password_confirmation
|
31
|
+
}
|
32
|
+
<% else -%>
|
33
|
+
<% name = if attribute.respond_to?(:column_name) then attribute.column_name else attribute.name end -%>
|
34
|
+
div(:class => :field) {
|
35
|
+
f.label :<%= name %>
|
36
|
+
f.<%= attribute.field_type %> :<%= name %>
|
37
|
+
}
|
38
|
+
<% end -%>
|
39
|
+
<% end -%>
|
40
|
+
|
41
|
+
div(:class => :actions) { f.submit }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class Views::<%= plural_table_name.camelize %>::Index < Views::Base
|
2
|
+
needs :<%= plural_table_name %>, :notice => nil
|
3
|
+
|
4
|
+
def content
|
5
|
+
p notice, :id => :notice
|
6
|
+
|
7
|
+
h1 "<%= plural_table_name.titleize %>"
|
8
|
+
|
9
|
+
table {
|
10
|
+
thead {
|
11
|
+
tr {
|
12
|
+
<% attributes.reject { |a| a.respond_to?(:password_digest?) && a.password_digest? }.each do |attribute| -%>
|
13
|
+
th "<%= attribute.human_name %>"
|
14
|
+
<% end -%>
|
15
|
+
th
|
16
|
+
th
|
17
|
+
th
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
tbody {
|
22
|
+
<%= plural_table_name %>.each do |<%= singular_table_name %>|
|
23
|
+
tr {
|
24
|
+
<% attributes.reject { |a| a.respond_to?(:password_digest?) && a.password_digest? }.each do |attribute| -%>
|
25
|
+
td <%= singular_table_name %>.<%= attribute.name %>
|
26
|
+
<% end -%>
|
27
|
+
td {
|
28
|
+
link_to 'Show', <%= singular_table_name %>
|
29
|
+
}
|
30
|
+
td {
|
31
|
+
link_to 'Edit', edit_<%= singular_table_name %>_path(<%= singular_table_name %>)
|
32
|
+
}
|
33
|
+
td {
|
34
|
+
link_to 'Destroy', <%= singular_table_name %>, :method => :delete, :data => { :confirm => 'Are you sure?' }
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
br
|
42
|
+
|
43
|
+
link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_table_name %>_path
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Views::<%= plural_table_name.camelize %>::New < Views::Base
|
2
|
+
needs :<%= singular_table_name %> => nil
|
3
|
+
|
4
|
+
def content
|
5
|
+
h1 "New <%= singular_table_name.titleize %>"
|
6
|
+
|
7
|
+
widget Views::<%= plural_table_name.camelize %>::Form, :<%= singular_table_name %> => <%= singular_table_name %>
|
8
|
+
|
9
|
+
link_to 'Back', <%= index_helper %>_path
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Views::<%= plural_table_name.camelize %>::Show < Views::Base
|
2
|
+
needs :<%= singular_table_name %>, :notice => nil
|
3
|
+
|
4
|
+
def content
|
5
|
+
p notice, :id => :notice
|
6
|
+
|
7
|
+
<% attributes.reject { |a| a.respond_to?(:password_digest?) && a.password_digest? }.each do |attribute| -%>
|
8
|
+
p {
|
9
|
+
strong "<%= attribute.human_name %>:"
|
10
|
+
text <%= singular_table_name %>.<%= attribute.name %>
|
11
|
+
}
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
link_to "Edit", edit_<%= singular_table_name %>_path(<%= singular_table_name %>)
|
15
|
+
text " | "
|
16
|
+
link_to 'Back', <%= index_helper %>_path
|
17
|
+
end
|
18
|
+
end
|
@@ -6,6 +6,7 @@ describe "Rails complex helper support", :type => :rails do
|
|
6
6
|
%r{OUTSIDE_BEFORE\s*<form.*action=\"/complex_helpers_system_spec/form_for_test\".*
|
7
7
|
INSIDE_BEFORE\s*
|
8
8
|
FIRST:\s*<input.*person_first_name.*/>\s*
|
9
|
+
MIDDLE:\s*<input.*person_middle_name.*/>\s*
|
9
10
|
LAST:\s*<input.*person_last_name.*/>\s*
|
10
11
|
INSIDE_AFTER\s*
|
11
12
|
</form>\s*
|
@@ -67,6 +68,11 @@ describe "Rails complex helper support", :type => :rails do
|
|
67
68
|
</label>}mix)
|
68
69
|
end
|
69
70
|
|
71
|
+
it "should allow implicitly carrying through things like IDs from one request to another" do
|
72
|
+
id = rand(1_000_000)
|
73
|
+
expect(rails_server.get("/carryover/#{id}")).to match(%r{Edit:\s*.*/carryover/#{id}/edit})
|
74
|
+
end
|
75
|
+
|
70
76
|
it "should cache based on a name properly" do
|
71
77
|
expect_match("cache_test?a=a1&b=b1",
|
72
78
|
/before_cache\(a1,b1\).*inside_cache\(a1,b1\).*after_cache\(a1,b1\)/mi)
|
@@ -21,6 +21,10 @@ describe "Rails data-passing support", :type => :rails do
|
|
21
21
|
expect_actionview_exception('omitted_variable', 'Fortitude::Errors::MissingNeed', /bar/)
|
22
22
|
end
|
23
23
|
|
24
|
+
it "should not give you an error just because a variable is set to nil" do
|
25
|
+
expect_match("nil_data_widget", /foo is: "the_foo"/, /bar is: nil/)
|
26
|
+
end
|
27
|
+
|
24
28
|
it "should not propagate un-needed variables" do
|
25
29
|
expect_match("extra_variables", /foo method call: the_foo/, /foo instance var: nil/,
|
26
30
|
/bar method call: NoMethodError/, /bar instance var: nil/,
|
@@ -0,0 +1,166 @@
|
|
1
|
+
describe "Rails generator support", :type => :rails do
|
2
|
+
# We use development mode so that we don't have to bounce the Rails server every time we
|
3
|
+
# generate something new.
|
4
|
+
uses_rails_with_template :generators_system_spec, :rails_env => :development
|
5
|
+
|
6
|
+
def views_base_path
|
7
|
+
@views_base_path ||= File.join(rails_server.rails_root, 'app', 'views', 'base.rb')
|
8
|
+
end
|
9
|
+
|
10
|
+
def clean_views_base!
|
11
|
+
File.delete(views_base_path) if File.exist?(views_base_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def ensure_views_base_is_correct!
|
15
|
+
expect(File.exist?(views_base_path)).to be_truthy
|
16
|
+
|
17
|
+
contents = File.read(views_base_path)
|
18
|
+
expect(contents).to match(/Views::Base\s*<\s*Fortitude::Widget\s*\n/)
|
19
|
+
expect(contents).to match(/doctype\s+:html5/)
|
20
|
+
end
|
21
|
+
|
22
|
+
def generate!(what)
|
23
|
+
rails_server.run_command_in_rails_root!("rails generate #{what}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def ensure_file_matches!(subpath, regexp)
|
27
|
+
path = File.join(rails_server.rails_root, subpath)
|
28
|
+
expect(File.exist?(path)).to be_truthy
|
29
|
+
|
30
|
+
contents = File.read(path)
|
31
|
+
expect(contents).to match(regexp)
|
32
|
+
end
|
33
|
+
|
34
|
+
def ensure_action_matches!(subpath, regexp)
|
35
|
+
response = rails_server.get(subpath)
|
36
|
+
expect(response).to match(regexp)
|
37
|
+
response
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "base view generation" do
|
41
|
+
it "should be able to generate a Views::Base file" do
|
42
|
+
clean_views_base!
|
43
|
+
generate!("fortitude:base_view")
|
44
|
+
ensure_views_base_is_correct!
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "controller generation" do
|
49
|
+
it "should be able to generate a controller action that creates a Fortitude view" do
|
50
|
+
generate!("controller gen_con1 act_ion1")
|
51
|
+
ensure_file_matches!('app/views/gen_con1/act_ion1.html.rb', /Views::GenCon1::ActIon1\s*<\s*Views::Base/)
|
52
|
+
ensure_action_matches!('gen_con1/act_ion1', %r{<h1>\s*GenCon1#act_ion1\s*</h1>\s*<p>\s*Find me in app/views/gen_con1/act_ion1.html.rb\s*</p>}mi)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should generate a Views::Base file" do
|
56
|
+
clean_views_base!
|
57
|
+
generate!("controller gencon2 action2")
|
58
|
+
ensure_views_base_is_correct!
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should not overwrite an existing Views::Base file" do
|
62
|
+
prior_contents = "class Views::Base < Fortitude::Widget\n doctype :html5\n def something\n end\nend"
|
63
|
+
File.open(views_base_path, 'w') { |f| f.puts prior_contents }
|
64
|
+
|
65
|
+
generate!("controller gencon3 action3")
|
66
|
+
|
67
|
+
expect(File.exist?(views_base_path)).to be_truthy
|
68
|
+
expect(File.read(views_base_path).strip).to eq(prior_contents.strip)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should allow switching back to ERb if desired" do
|
72
|
+
generate!("controller gen_con4 act_ion1 -e erb")
|
73
|
+
expect(File.exist?(File.join(rails_server.rails_root, 'app/views/gen_con4/act_ion1.html.rb'))).to be_falsey
|
74
|
+
expect(File.exist?(File.join(rails_server.rails_root, 'app/views/gen_con4/act_ion1.html.erb'))).to be_truthy
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "mailer generation" do
|
79
|
+
def mailer_path_suffix
|
80
|
+
if rails_server.actual_rails_version =~ /^[34]\./
|
81
|
+
""
|
82
|
+
else
|
83
|
+
"_mailer"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def mailer_class_suffix
|
88
|
+
if rails_server.actual_rails_version =~ /^[34]\./
|
89
|
+
""
|
90
|
+
else
|
91
|
+
"Mailer"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should be able to generate a mailer that creates a Fortitude view and layout" do
|
96
|
+
generate!("mailer gen1 act_ion1")
|
97
|
+
ensure_file_matches!("app/views/gen1#{mailer_path_suffix}/act_ion1.html.rb", /Views::Gen1#{mailer_class_suffix}::ActIon1\s*<\s*Views::Base/)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should generate a Views::Base file" do
|
101
|
+
clean_views_base!
|
102
|
+
generate!("mailer gen1 act_ion1")
|
103
|
+
ensure_views_base_is_correct!
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should not overwrite an existing Views::Base file" do
|
107
|
+
prior_contents = "class Views::Base < Fortitude::Widget\n doctype :html5\n def something\n end\nend"
|
108
|
+
File.open(views_base_path, 'w') { |f| f.puts prior_contents }
|
109
|
+
|
110
|
+
generate!("mailer gen1 act_ion1")
|
111
|
+
|
112
|
+
expect(File.exist?(views_base_path)).to be_truthy
|
113
|
+
expect(File.read(views_base_path).strip).to eq(prior_contents.strip)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "scaffold generation" do
|
118
|
+
it "should be able to generate a scaffold" do
|
119
|
+
generate!("scaffold MyModel foo:string bar:integer")
|
120
|
+
|
121
|
+
# We need to disable CSRF protection, since we're not using a session
|
122
|
+
application_controller = File.join(rails_server.rails_root, 'app', 'controllers', 'application_controller.rb')
|
123
|
+
application_controller_contents = File.read(application_controller)
|
124
|
+
if (! application_controller_contents.gsub!(/^\s*protect_from_forgery.*$/, "protect_from_forgery :with => :null_session"))
|
125
|
+
application_controller_contents.gsub!(/^end\Z/, " protect_from_forgery :with => :null_session\nend\n")
|
126
|
+
end
|
127
|
+
File.open(application_controller, 'w') { |f| f.puts application_controller_contents }
|
128
|
+
|
129
|
+
# Need this to create the table (which will be in SQLite by default, which is easy), or else
|
130
|
+
# the controller actions will fail since there will be no such table.
|
131
|
+
rails_server.run_command_in_rails_root!("rake db:migrate")
|
132
|
+
|
133
|
+
ensure_file_matches!('app/views/my_models/index.html.rb', %r{class Views::MyModels::Index < Views::Base})
|
134
|
+
ensure_file_matches!('app/views/my_models/show.html.rb', %r{class Views::MyModels::Show < Views::Base})
|
135
|
+
ensure_file_matches!('app/views/my_models/edit.html.rb', %r{class Views::MyModels::Edit < Views::Base})
|
136
|
+
ensure_file_matches!('app/views/my_models/new.html.rb', %r{class Views::MyModels::New < Views::Base})
|
137
|
+
ensure_file_matches!('app/views/my_models/form.html.rb', %r{class Views::MyModels::Form < Views::Base})
|
138
|
+
|
139
|
+
# Ruby 1.8.7 and Rails 3.0.x seems to have issues unless we do this, sadly...
|
140
|
+
rails_server.stop!
|
141
|
+
rails_server.start!
|
142
|
+
|
143
|
+
# This won't check that the views all have the right HTML in them (that's nearly impossible without
|
144
|
+
# just duplicating exactly what they're supposed to contain, right here), but it will check that they
|
145
|
+
# compile and produce some kind of HTML output.
|
146
|
+
ensure_action_matches!('my_models', %r{<h1>\s*My Models\s*</h1>}m)
|
147
|
+
new_html = ensure_action_matches!('my_models/new', %r{<form.*action=["']/my_models["']}m)
|
148
|
+
|
149
|
+
# Now, we try to create one
|
150
|
+
response = rails_server.post('my_models', :post_variables => {
|
151
|
+
'my_model[foo]' => 'foo1', 'my_model[bar]' => 23456, :commit => 'Create My model' },
|
152
|
+
:ignore_status_code => true)
|
153
|
+
|
154
|
+
new_url = if (300..399).include?(Integer(response.code))
|
155
|
+
response['Location']
|
156
|
+
else
|
157
|
+
raise "Response didn't seem to give us a redirect: #{response.code.inspect} (from #{response.inspect})"
|
158
|
+
end
|
159
|
+
path = URI.parse(new_url).path
|
160
|
+
|
161
|
+
ensure_action_matches!(path, %r{foo1.*23456}m)
|
162
|
+
ensure_action_matches!("#{path}/edit", %r{Editing.*foo1.*23456}m)
|
163
|
+
ensure_action_matches!("my_models", %r{<h1>\s*My Models\s*</h1>.*foo1.*23456}m)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|