freeform 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Gemfile.lock +1 -1
- data/lib/freeform/builder/builder_mixin.rb +8 -3
- data/lib/freeform/form/nested.rb +8 -8
- data/lib/freeform/form/property.rb +15 -9
- data/lib/freeform/form.rb +62 -12
- data/lib/freeform/version.rb +1 -1
- data/spec/acceptance_spec.rb +105 -4
- data/spec/behavior_spec.rb +48 -0
- data/spec/dummy/app/controllers/projects_controller.rb +8 -2
- data/spec/dummy/app/forms/task_form.rb +3 -2
- data/spec/dummy/app/views/projects/new.html.erb +2 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +27711 -0
- data/spec/javascript_spec.rb +1 -2
- data/vendor/assets/javascripts/jquery_freeform.js +10 -5
- metadata +4 -9
- data/spec/dummy/app/assets/javascripts/prototype.js +0 -6082
- data/spec/dummy/app/assets/javascripts/prototype_events_test.js +0 -20
- data/spec/dummy/app/views/projects/without_intermediate_inputs.html.erb +0 -11
- data/vendor/assets/javascripts/prototype_freeform.js +0 -69
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NmE5OGYzZDc5Mzg0NjRiZmY2ZDQ5MzIyMzFkNmIxNmU4MmY0M2NiMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjBjODM1YzBkNTI4NjY1MGU5YWVlOTRhY2ZlYWM3YWVhNjhlZTIxNA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZDFmMDcwMjc3YjJjOGI0OWY1M2Q1ZjAyOTE2NWM1MGVhNzczZjhmZmM0ZGZj
|
10
|
+
NTEyNzBhZGRiYjEwYWQwNmEyNGQ2MTUxZDE0YWEyOTUzYzE5YTBhM2E4Mjkz
|
11
|
+
ODMyZDQxYzljODQ4YzAzN2Y2OWFjYTQzY2IzNDY0MTUwYWZiMTU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OGYwZjZjNTZkZTAxNDg2YTg2OTRjNjUzNjk0NDE5Y2JmMWQ4Mzk5ZDI0MDFm
|
14
|
+
NGQwMWM3Y2I5MGQ4OThiODUyYzE4OGIyNDllMGQ4NDdjMTI0ODM1ODQ1OTU5
|
15
|
+
ZDFhNGY4YzM4MjgxMjViN2EwZTQxMzk3NzRlYTk3NzBjYzU0ZWM=
|
data/Gemfile.lock
CHANGED
@@ -24,7 +24,6 @@ module FreeForm
|
|
24
24
|
raise ArgumentError, "Invalid association. Make sure that a nested form for #{association.to_s} exists."
|
25
25
|
end
|
26
26
|
|
27
|
-
#FIXME: I need to use the build method for child models
|
28
27
|
model_object = options.delete(:model_object) do
|
29
28
|
object.send("build_#{association.to_s.singularize}")
|
30
29
|
end
|
@@ -68,10 +67,16 @@ module FreeForm
|
|
68
67
|
|
69
68
|
args << (options.delete(:href) || "javascript:void(0)")
|
70
69
|
args << options
|
71
|
-
|
70
|
+
|
71
|
+
destroy = if self.object.send(:marked_for_destruction?)
|
72
|
+
"1"
|
73
|
+
else
|
74
|
+
"0"
|
75
|
+
end
|
76
|
+
hidden_field(:_destroy, :value => destroy) << @template.link_to(*args, &block)
|
72
77
|
end
|
78
|
+
|
73
79
|
def fields_for_with_nested_attributes(association_name, *args)
|
74
|
-
# TODO Test this better
|
75
80
|
block = args.pop || Proc.new { |fields| @template.render(:partial => "#{association_name.to_s.singularize}_fields", :locals => {:f => fields}) }
|
76
81
|
|
77
82
|
options = args.dup.extract_options!
|
data/lib/freeform/form/nested.rb
CHANGED
@@ -3,7 +3,7 @@ module FreeForm
|
|
3
3
|
def self.included(base)
|
4
4
|
base.extend(ClassMethods)
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
module ClassMethods
|
8
8
|
# Nested Forms
|
9
9
|
#------------------------------------------------------------------------
|
@@ -32,21 +32,21 @@ module FreeForm
|
|
32
32
|
def define_nested_model_methods(attribute, form_class, options={})
|
33
33
|
singularized_attribute = attribute.to_s.singularize.to_s
|
34
34
|
|
35
|
-
# Example: form.addresses will return all nested address forms
|
35
|
+
# Example: form.addresses will return all nested address forms
|
36
36
|
define_method(:"#{attribute}") do
|
37
37
|
value = instance_variable_get("@nested_#{attribute}")
|
38
38
|
value ||= []
|
39
39
|
instance_variable_set("@nested_#{attribute}", value)
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
# Example: form.build_addresses (optional custom initializer)
|
43
43
|
define_method(:"build_#{attribute}") do |initializer=nil|
|
44
44
|
# Builder object
|
45
45
|
parent_object = self
|
46
|
-
|
46
|
+
|
47
47
|
# Get correct class
|
48
48
|
form_class = self.class.nested_forms[:"#{attribute}"]
|
49
|
-
|
49
|
+
|
50
50
|
# Default Initializer
|
51
51
|
if options[:default_initializer]
|
52
52
|
initializer ||= instance_eval(&options[:default_initializer])
|
@@ -84,11 +84,11 @@ module FreeForm
|
|
84
84
|
|
85
85
|
# Instance Methods
|
86
86
|
#--------------------------------------------------------------------------
|
87
|
-
|
87
|
+
protected
|
88
88
|
def build_models_from_param_count(attribute, params)
|
89
89
|
# Get the difference between sets of params passed and current form objects
|
90
90
|
num_param_models = params.length
|
91
|
-
num_built_models = self.send(:"#{attribute}").nil? ? 0 : self.send(:"#{attribute}").length
|
91
|
+
num_built_models = self.send(:"#{attribute}").nil? ? 0 : self.send(:"#{attribute}").length
|
92
92
|
additional_models_needed = num_param_models - num_built_models
|
93
93
|
|
94
94
|
# Make up the difference by building new nested form models
|
@@ -97,4 +97,4 @@ module FreeForm
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
100
|
-
end
|
100
|
+
end
|
@@ -19,11 +19,11 @@ module FreeForm
|
|
19
19
|
|
20
20
|
def declared_model(name, opts={})
|
21
21
|
@models ||= []
|
22
|
-
@models << name
|
22
|
+
@models << name
|
23
23
|
attr_accessor name
|
24
24
|
end
|
25
25
|
alias_method :form_model, :declared_model
|
26
|
-
|
26
|
+
|
27
27
|
def declared_models(*names)
|
28
28
|
names.each do |name|
|
29
29
|
declared_model(name)
|
@@ -33,9 +33,9 @@ module FreeForm
|
|
33
33
|
|
34
34
|
def child_model(name, opts={}, &block)
|
35
35
|
@models ||= []
|
36
|
-
@models << name
|
36
|
+
@models << name
|
37
37
|
@child_models ||= []
|
38
|
-
@child_models << name
|
38
|
+
@child_models << name
|
39
39
|
attr_accessor name
|
40
40
|
define_method("initialize_#{name}") do
|
41
41
|
instance_variable_set("@#{name}", instance_eval(&block))
|
@@ -53,8 +53,14 @@ module FreeForm
|
|
53
53
|
# Define _destroy method for marked-for-destruction handling
|
54
54
|
attr_accessor :_destroy
|
55
55
|
define_method(:_destroy=) do |value|
|
56
|
-
false_values
|
57
|
-
|
56
|
+
false_values = [nil, 0 , false, "0", "false"]
|
57
|
+
true_values = [1 , true, "1", "true"]
|
58
|
+
|
59
|
+
#TODO: Test this!!
|
60
|
+
@_destroy = !false_values.include?(value) # Mark initially
|
61
|
+
# if (@_destroy == false) # Can only switch if false
|
62
|
+
# @_destroy = true if true_values.include?(value)
|
63
|
+
# end
|
58
64
|
end
|
59
65
|
alias_method :marked_for_destruction?, :_destroy
|
60
66
|
define_method(:mark_for_destruction) do
|
@@ -108,7 +114,7 @@ module FreeForm
|
|
108
114
|
def params_to_date(year, month, day)
|
109
115
|
day ||= 1 # FIXME: is that really what we want? test.
|
110
116
|
begin # TODO: test fails.
|
111
|
-
return Date.new(year.to_i, month.to_i, day.to_i)
|
117
|
+
return Date.new(year.to_i, month.to_i, day.to_i)
|
112
118
|
rescue ArgumentError => e
|
113
119
|
return nil
|
114
120
|
end
|
@@ -128,7 +134,7 @@ module FreeForm
|
|
128
134
|
|
129
135
|
private
|
130
136
|
def assign_attribute(attribute, value)
|
131
|
-
self.send :"#{attribute}=", value unless ignore?(attribute, value)
|
137
|
+
self.send :"#{attribute}=", value unless ignore?(attribute, value)
|
132
138
|
end
|
133
139
|
|
134
140
|
def ignore?(attribute, value)
|
@@ -136,4 +142,4 @@ module FreeForm
|
|
136
142
|
return (mapping[:ignore_blank] && value.blank?) unless mapping.nil?
|
137
143
|
end
|
138
144
|
end
|
139
|
-
end
|
145
|
+
end
|
data/lib/freeform/form.rb
CHANGED
@@ -26,44 +26,94 @@ module FreeForm
|
|
26
26
|
|
27
27
|
def initialize(h={})
|
28
28
|
h.each {|k,v| send("#{k}=",v)}
|
29
|
-
initialize_child_models
|
30
|
-
end
|
31
|
-
|
29
|
+
initialize_child_models
|
30
|
+
end
|
31
|
+
|
32
|
+
# def save
|
33
|
+
# return false unless valid?
|
34
|
+
|
35
|
+
# self.class.models.each do |form_model|
|
36
|
+
# model = send(form_model)
|
37
|
+
# model.is_a?(Array) ? model.each { |m| m.save } : save_or_destroy(model)
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
|
41
|
+
# def save!
|
42
|
+
# raise FreeForm::FormInvalid, "form invalid." unless valid?
|
43
|
+
|
44
|
+
# self.class.models.each do |form_model|
|
45
|
+
# model = send(form_model)
|
46
|
+
# model.is_a?(Array) ? model.each { |m| m.save! } : save_or_destroy!(model)
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
|
50
|
+
|
32
51
|
def save
|
33
|
-
return false unless valid?
|
52
|
+
return false unless valid? || marked_for_destruction?
|
34
53
|
|
54
|
+
# Loop through nested models first, sending them the save call
|
35
55
|
self.class.models.each do |form_model|
|
36
56
|
model = send(form_model)
|
37
|
-
|
57
|
+
# This is for nested models.
|
58
|
+
if model.is_a?(Array)
|
59
|
+
model.each { |m| m.save }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# puts "Saving... #{self}"
|
64
|
+
|
65
|
+
# After nested models are handled, save or destroy myself.
|
66
|
+
self.class.models.each do |form_model|
|
67
|
+
model = send(form_model)
|
68
|
+
# This is for form models.
|
69
|
+
unless model.is_a?(Array)
|
70
|
+
# puts "Saving model...#{model}"
|
71
|
+
if model.is_a?(Project)
|
72
|
+
# puts "All Tasks = #{Task.all}"
|
73
|
+
# puts "Tasks = #{model.tasks.inspect}"
|
74
|
+
end
|
75
|
+
if marked_for_destruction?
|
76
|
+
# puts "destroying model...#{model}"
|
77
|
+
model.destroy
|
78
|
+
else
|
79
|
+
model.save
|
80
|
+
end
|
81
|
+
end
|
38
82
|
end
|
39
83
|
end
|
40
|
-
|
84
|
+
|
41
85
|
def save!
|
42
86
|
raise FreeForm::FormInvalid, "form invalid." unless valid?
|
43
87
|
|
88
|
+
# Destroy all marked-for-destruction models
|
89
|
+
|
44
90
|
self.class.models.each do |form_model|
|
45
91
|
model = send(form_model)
|
46
92
|
model.is_a?(Array) ? model.each { |m| m.save! } : save_or_destroy!(model)
|
47
93
|
end
|
48
|
-
end
|
49
|
-
|
94
|
+
end
|
95
|
+
|
50
96
|
private
|
51
97
|
def initialize_child_models
|
52
98
|
self.class.child_models.each do |c|
|
53
99
|
send("initialize_#{c}")
|
54
|
-
end
|
100
|
+
end
|
55
101
|
end
|
56
102
|
|
57
103
|
def save_or_destroy(model)
|
58
104
|
marked_for_destruction? ? model.destroy : model.save
|
59
105
|
end
|
60
|
-
|
106
|
+
|
61
107
|
def save_or_destroy!(model)
|
62
|
-
marked_for_destruction?
|
108
|
+
if marked_for_destruction?
|
109
|
+
model.destroy
|
110
|
+
else
|
111
|
+
model.save!
|
112
|
+
end
|
63
113
|
end
|
64
114
|
|
65
115
|
def marked_for_destruction?
|
66
116
|
respond_to?(:_destroy) ? _destroy : false
|
67
117
|
end
|
68
118
|
end
|
69
|
-
end
|
119
|
+
end
|
data/lib/freeform/version.rb
CHANGED
data/spec/acceptance_spec.rb
CHANGED
@@ -36,7 +36,7 @@ describe FreeForm::Form do
|
|
36
36
|
has_many :tasks, :class => Module::TaskForm, :default_initializer => :default_task_initializer
|
37
37
|
|
38
38
|
def default_task_initializer
|
39
|
-
{ :task =>
|
39
|
+
{ :task => project.tasks.build }
|
40
40
|
end
|
41
41
|
end
|
42
42
|
# This wrapper just avoids CONST warnings
|
@@ -67,7 +67,7 @@ describe FreeForm::Form do
|
|
67
67
|
|
68
68
|
it "initializes with Task with project parent" do
|
69
69
|
task = form.tasks.first.task
|
70
|
-
task.
|
70
|
+
task.should eq(form.project.tasks.first)
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -229,7 +229,7 @@ describe FreeForm::Form do
|
|
229
229
|
end
|
230
230
|
end
|
231
231
|
|
232
|
-
context "with invalid form, and invalid marked for destruction nested model"
|
232
|
+
context "with invalid form, and invalid marked for destruction nested model" do
|
233
233
|
let(:attributes) do {
|
234
234
|
:company_name => "",
|
235
235
|
:project_name => "rails app",
|
@@ -374,10 +374,111 @@ describe FreeForm::Form do
|
|
374
374
|
end
|
375
375
|
|
376
376
|
it "should raise error on 'save!'" do
|
377
|
-
expect{ form.save
|
377
|
+
expect{ form.save! }.to raise_error(FreeForm::FormInvalid)
|
378
378
|
end
|
379
379
|
end
|
380
380
|
|
381
|
+
context "with invalid attributes, and marked for destruction nested model", :failing => true do
|
382
|
+
let(:attributes) do {
|
383
|
+
:company_name => "dummycorp",
|
384
|
+
:project_name => "",
|
385
|
+
"due_date(1i)" => "2014",
|
386
|
+
"due_date(2i)" => "10",
|
387
|
+
"due_date(3i)" => "30",
|
388
|
+
:tasks_attributes => {
|
389
|
+
"0" => {
|
390
|
+
:name => "task_1",
|
391
|
+
"start_date(1i)" => "2012",
|
392
|
+
"start_date(2i)" => "1",
|
393
|
+
"start_date(3i)" => "2",
|
394
|
+
},
|
395
|
+
"3234322345" => {
|
396
|
+
:name => "task_2",
|
397
|
+
"end_date(1i)" => "2011",
|
398
|
+
"end_date(2i)" => "12",
|
399
|
+
"end_date(3i)" => "15",
|
400
|
+
:_destroy => "1"
|
401
|
+
}
|
402
|
+
} }
|
403
|
+
end
|
404
|
+
|
405
|
+
before(:each) do
|
406
|
+
form.fill(attributes)
|
407
|
+
end
|
408
|
+
|
409
|
+
it "should not be valid" do
|
410
|
+
form.should_not be_valid
|
411
|
+
end
|
412
|
+
|
413
|
+
describe "persisting destroy after failed save" do
|
414
|
+
before(:each) { form.save }
|
415
|
+
|
416
|
+
it "should have the second form still set to _destroy" do
|
417
|
+
form.tasks.second.should be_marked_for_destruction
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
# it "should have valid company and project after save", :failing_1 => true do
|
422
|
+
# form.save
|
423
|
+
# # form.tasks.first.task.destroy
|
424
|
+
# form.company.should be_valid
|
425
|
+
# form.project.valid?
|
426
|
+
# puts "Errors = #{form.project.errors.inspect}"
|
427
|
+
# form.project.should be_valid
|
428
|
+
# end
|
429
|
+
|
430
|
+
# it "should not raise error on 'save!'" do
|
431
|
+
# expect{ form.save! }.to_not raise_error
|
432
|
+
# end
|
433
|
+
end
|
434
|
+
|
435
|
+
context "with invalid, marked for destruction nested model" do
|
436
|
+
let(:attributes) do {
|
437
|
+
:company_name => "dummycorp",
|
438
|
+
:project_name => "railsapp",
|
439
|
+
"due_date(1i)" => "2014",
|
440
|
+
"due_date(2i)" => "10",
|
441
|
+
"due_date(3i)" => "30",
|
442
|
+
:tasks_attributes => {
|
443
|
+
"0" => {
|
444
|
+
:name => "task_1",
|
445
|
+
"start_date(1i)" => "2012",
|
446
|
+
"start_date(2i)" => "1",
|
447
|
+
"start_date(3i)" => "2",
|
448
|
+
},
|
449
|
+
"1" => {
|
450
|
+
:name => "task_2",
|
451
|
+
"end_date(1i)" => "2011",
|
452
|
+
"end_date(2i)" => "12",
|
453
|
+
"end_date(3i)" => "15",
|
454
|
+
:_destroy => "1"
|
455
|
+
}
|
456
|
+
} }
|
457
|
+
end
|
458
|
+
|
459
|
+
before(:each) do
|
460
|
+
form.fill(attributes)
|
461
|
+
end
|
462
|
+
|
463
|
+
it { is pending }
|
464
|
+
# it "should return true on 'save'" do
|
465
|
+
# form.save.should be_true
|
466
|
+
# end
|
467
|
+
|
468
|
+
# it "should have valid company and project after save", :failing_1 => true do
|
469
|
+
# form.save
|
470
|
+
# # form.tasks.first.task.destroy
|
471
|
+
# form.company.should be_valid
|
472
|
+
# form.project.valid?
|
473
|
+
# puts "Errors = #{form.project.errors.inspect}"
|
474
|
+
# form.project.should be_valid
|
475
|
+
# end
|
476
|
+
|
477
|
+
# it "should not raise error on 'save!'" do
|
478
|
+
# expect{ form.save! }.to_not raise_error
|
479
|
+
# end
|
480
|
+
end
|
481
|
+
|
381
482
|
context "with valid attributes" do
|
382
483
|
let(:attributes) do {
|
383
484
|
:company_name => "dummycorp",
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Full Behavior', :js => true do
|
4
|
+
include Capybara::DSL
|
5
|
+
|
6
|
+
[:jquery].each do |js_framework|
|
7
|
+
|
8
|
+
url = case js_framework
|
9
|
+
when :jquery then '/projects/new'
|
10
|
+
end
|
11
|
+
|
12
|
+
context "with #{js_framework}" do
|
13
|
+
context 'adding/removing fields' do
|
14
|
+
it 'adds fields and increments count' do
|
15
|
+
visit url
|
16
|
+
click_link 'Add new task'
|
17
|
+
all("input[id^='project_tasks_attributes_']", visible: true).count.should eq(1)
|
18
|
+
click_link 'Add new task'
|
19
|
+
all("input[id^='project_tasks_attributes_']", visible: true).count.should eq(2)
|
20
|
+
click_link 'Add new task'
|
21
|
+
all("input[id^='project_tasks_attributes_']", visible: true).count.should eq(3)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'removes fields' do
|
25
|
+
visit url
|
26
|
+
click_link 'Add new task'
|
27
|
+
all("input[id^='project_tasks_attributes_']", visible: true).count.should eq(1)
|
28
|
+
click_link 'Remove'
|
29
|
+
all("input[id^='project_tasks_attributes_']", visible: true).count.should eq(0)
|
30
|
+
click_link 'Add new task'
|
31
|
+
all("input[id^='project_tasks_attributes_']", visible: true).count.should eq(1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'after application submission' do
|
36
|
+
it 'emits general remove event' do
|
37
|
+
visit url
|
38
|
+
click_link 'Add new task'
|
39
|
+
all("input[id^='project_tasks_attributes_']", visible: true).count.should eq(1)
|
40
|
+
click_link 'Remove'
|
41
|
+
all("input[id^='project_tasks_attributes_']", visible: true).count.should eq(0)
|
42
|
+
click_button 'Submit'
|
43
|
+
page.should have_selector(:xpath, "//input[@id='project_tasks_attributes_0__destroy' and @value='1']", visible: false)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -3,9 +3,15 @@ class ProjectsController < ApplicationController
|
|
3
3
|
@project = Project.new
|
4
4
|
@form = project_form(@project)
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
|
+
def create
|
8
|
+
@project = Project.new
|
9
|
+
@form = project_form(@project).fill(params[:project])
|
10
|
+
render :action => :new
|
11
|
+
end
|
12
|
+
|
7
13
|
private
|
8
14
|
def project_form(project)
|
9
15
|
ProjectForm.new(:project => project)
|
10
|
-
end
|
16
|
+
end
|
11
17
|
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
class TaskForm < FreeForm::Form
|
2
2
|
form_models :task
|
3
|
-
property :name, :on => :task
|
3
|
+
property :name, :on => :task
|
4
|
+
allow_destroy_on_save
|
4
5
|
|
5
6
|
has_many :milestones, :class => MilestoneForm, :default_initializer => :milestone_initializer
|
6
7
|
|
7
8
|
def milestone_initializer
|
8
9
|
{ :milestone => Milestone.new }
|
9
10
|
end
|
10
|
-
end
|
11
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= freeform_for @form do |f| -%>
|
1
|
+
<%= freeform_for @form, :url => projects_path, :method => :post do |f| -%>
|
2
2
|
<%= f.text_field :name %>
|
3
3
|
<%= f.fields_for :tasks do |tf| -%>
|
4
4
|
<%= tf.text_field :name %>
|
@@ -10,4 +10,5 @@
|
|
10
10
|
<%= tf.link_to_remove 'Remove' %>
|
11
11
|
<% end -%>
|
12
12
|
<%= f.link_to_add 'Add new task', :tasks %>
|
13
|
+
<%= f.submit "Submit" %>
|
13
14
|
<% end -%>
|
data/spec/dummy/db/test.sqlite3
CHANGED
Binary file
|