fortitude 0.9.5-java → 0.9.6-java
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.
- 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
|