fieldable_form 0.0.1 → 0.0.2
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.
- data/README.md +20 -13
- data/app/models/concerns/fieldable_form/{validations.rb → entry_validations.rb} +2 -2
- data/app/models/fieldable_form/base_form.rb +1 -1
- data/app/models/fieldable_form/check_box.rb +1 -1
- data/app/models/fieldable_form/drop_down.rb +1 -2
- data/app/models/fieldable_form/{abstract_field.rb → field.rb} +4 -6
- data/app/models/fieldable_form/text_field.rb +1 -2
- data/lib/fieldable_form/version.rb +1 -1
- data/lib/fieldable_form.rb +0 -2
- data/lib/generators/fieldable_form/bootstrap/USAGE +2 -5
- data/lib/generators/fieldable_form/bootstrap/bootstrap_generator.rb +0 -4
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +14 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +65 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +31 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +10 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/schema.rb +37 -0
- data/spec/dummy/log/development.log +17287 -0
- data/spec/dummy/log/test.log +2468 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/tmp/cache/assets/C89/C50/sprockets%2F0128245f453fc07495ce96d03ce83828 +0 -0
- data/spec/dummy/tmp/cache/assets/C8C/B80/sprockets%2F371bf96e99717688ed7313a0c53f4212 +0 -0
- data/spec/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
- data/spec/dummy/tmp/cache/assets/CE9/3B0/sprockets%2F4d76f2472a6585a82f20e528f66db37a +0 -0
- data/spec/dummy/tmp/cache/assets/CF0/1D0/sprockets%2F6fc757c2c8329244ca95d6909865bbc2 +0 -0
- data/spec/dummy/tmp/cache/assets/CF2/0B0/sprockets%2Fe7792e92129f4163b674c8eaa1869ea5 +0 -0
- data/spec/dummy/tmp/cache/assets/CFD/D40/sprockets%2Fbc10d0bbc521453356f2dc93fe962214 +0 -0
- data/spec/dummy/tmp/cache/assets/D04/AC0/sprockets%2F2cfb8bc0234d8d34a40b22e3160975f9 +0 -0
- data/spec/dummy/tmp/cache/assets/D0B/680/sprockets%2F15f117f5457e916bf0ed4373d0d54b1d +0 -0
- data/spec/dummy/tmp/cache/assets/D1A/6F0/sprockets%2Ff80b49ee1524c6a5e2039099e8e4a7e4 +0 -0
- data/spec/dummy/tmp/cache/assets/D2D/AE0/sprockets%2F7b63d98f6f2a590f8a7d3644e73fe567 +0 -0
- data/spec/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/spec/dummy/tmp/cache/assets/D3A/1A0/sprockets%2F375b9bfd0d0c32cc5477bc1f858270c2 +0 -0
- data/spec/dummy/tmp/cache/assets/D3B/7E0/sprockets%2F7dbe843db5a21c088def466f440d4700 +0 -0
- data/spec/dummy/tmp/cache/assets/D3D/CB0/sprockets%2Fdb4457a2344779c33afec132add7d934 +0 -0
- data/spec/dummy/tmp/cache/assets/D46/370/sprockets%2F9648dab31120c94bcc5f568faef56707 +0 -0
- data/spec/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/spec/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/spec/dummy/tmp/cache/assets/D5B/5E0/sprockets%2Fe29a1c35ce4b4650b9a8d1ec621e02b2 +0 -0
- data/spec/dummy/tmp/cache/assets/D60/550/sprockets%2F92d9a323823d13dde272b03caab918dd +0 -0
- data/spec/dummy/tmp/cache/assets/D61/E30/sprockets%2F83ced38963c1bc695c9ec9d8b33999c5 +0 -0
- data/spec/dummy/tmp/cache/assets/D66/AC0/sprockets%2F51e7a5daeb434a9ab4b396ca2537058d +0 -0
- data/spec/dummy/tmp/cache/assets/D99/390/sprockets%2Fbd60ec7ece6de65ae139641d53d1d611 +0 -0
- data/spec/dummy/tmp/cache/assets/D9D/700/sprockets%2F985cf14f35b20f92ba443cfe14d2c6fd +0 -0
- data/spec/dummy/tmp/cache/assets/DA5/DF0/sprockets%2Fc8f2f1b1c1662cb81da8ec752d378ee9 +0 -0
- data/spec/dummy/tmp/cache/assets/DAE/D60/sprockets%2F5ec78a1fb6d4ba97329bb8fca6e79516 +0 -0
- data/spec/dummy/tmp/cache/assets/DC2/830/sprockets%2F269b3baa48e630e7dac3a7c3bb65e1a7 +0 -0
- data/spec/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/spec/dummy/tmp/cache/assets/DEF/0A0/sprockets%2F2c4fe731be11cc181af12efe0ed8d4e3 +0 -0
- data/spec/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/spec/factories.rb +55 -0
- data/spec/spec_helper.rb +52 -0
- data/spec/support/matchers/include_validator.rb +14 -0
- data/spec/unit/models/concerns/fieldable_form/entry_validations_spec.rb +84 -0
- data/spec/unit/models/fieldable_form/drop_down_spec.rb +69 -0
- data/spec/unit/models/fieldable_form/field_spec.rb +41 -0
- data/spec/unit/models/fieldable_form/text_field_spec.rb +89 -0
- metadata +143 -45
- data/db/migrate/20130302181724_create_fieldable_forms.rb +0 -13
- data/lib/generators/fieldable_form/bootstrap/templates/form.rb +0 -2
@@ -0,0 +1,26 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The page you were looking for doesn't exist (404)</title>
|
5
|
+
<style type="text/css">
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
7
|
+
div.dialog {
|
8
|
+
width: 25em;
|
9
|
+
padding: 0 4em;
|
10
|
+
margin: 4em auto 0 auto;
|
11
|
+
border: 1px solid #ccc;
|
12
|
+
border-right-color: #999;
|
13
|
+
border-bottom-color: #999;
|
14
|
+
}
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body>
|
20
|
+
<!-- This file lives in public/404.html -->
|
21
|
+
<div class="dialog">
|
22
|
+
<h1>The page you were looking for doesn't exist.</h1>
|
23
|
+
<p>You may have mistyped the address or the page may have moved.</p>
|
24
|
+
</div>
|
25
|
+
</body>
|
26
|
+
</html>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The change you wanted was rejected (422)</title>
|
5
|
+
<style type="text/css">
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
7
|
+
div.dialog {
|
8
|
+
width: 25em;
|
9
|
+
padding: 0 4em;
|
10
|
+
margin: 4em auto 0 auto;
|
11
|
+
border: 1px solid #ccc;
|
12
|
+
border-right-color: #999;
|
13
|
+
border-bottom-color: #999;
|
14
|
+
}
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body>
|
20
|
+
<!-- This file lives in public/422.html -->
|
21
|
+
<div class="dialog">
|
22
|
+
<h1>The change you wanted was rejected.</h1>
|
23
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
24
|
+
</div>
|
25
|
+
</body>
|
26
|
+
</html>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
5
|
+
<style type="text/css">
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
7
|
+
div.dialog {
|
8
|
+
width: 25em;
|
9
|
+
padding: 0 4em;
|
10
|
+
margin: 4em auto 0 auto;
|
11
|
+
border: 1px solid #ccc;
|
12
|
+
border-right-color: #999;
|
13
|
+
border-bottom-color: #999;
|
14
|
+
}
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body>
|
20
|
+
<!-- This file lives in public/500.html -->
|
21
|
+
<div class="dialog">
|
22
|
+
<h1>We're sorry, but something went wrong.</h1>
|
23
|
+
</div>
|
24
|
+
</body>
|
25
|
+
</html>
|
File without changes
|
@@ -0,0 +1,6 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
3
|
+
|
4
|
+
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
5
|
+
require File.expand_path('../../config/boot', __FILE__)
|
6
|
+
require 'rails/commands'
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/spec/factories.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
def random_options
|
2
|
+
r = ""
|
3
|
+
10.times { r += Faker::Name.first_name + "," }
|
4
|
+
r
|
5
|
+
end
|
6
|
+
|
7
|
+
FactoryGirl.define do
|
8
|
+
factory :base_form, :class => FieldableForm::BaseForm do
|
9
|
+
end
|
10
|
+
|
11
|
+
factory :field, :class => FieldableForm::Field do
|
12
|
+
sequence(:name) { |n| "abstract_field_#{n}" }
|
13
|
+
|
14
|
+
trait :with_form do
|
15
|
+
association :fieldable, :factory => [:base_form]
|
16
|
+
end
|
17
|
+
|
18
|
+
trait :select do
|
19
|
+
field_type 'select'
|
20
|
+
options_for_select { random_options }
|
21
|
+
end
|
22
|
+
|
23
|
+
trait :number_only do
|
24
|
+
number_only true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
factory :text_field, :class => FieldableForm::TextField do
|
29
|
+
sequence(:name) { |n| "text_field_#{n}" }
|
30
|
+
|
31
|
+
trait :required do
|
32
|
+
required '1'
|
33
|
+
end
|
34
|
+
|
35
|
+
trait :number_only do
|
36
|
+
number_only '1'
|
37
|
+
end
|
38
|
+
|
39
|
+
trait :with_form do
|
40
|
+
association :fieldable, :factory => [:base_form]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
factory :drop_down, :class => FieldableForm::DropDown do
|
45
|
+
sequence(:name) { |n| "drop_down_#{n}" }
|
46
|
+
|
47
|
+
trait :required do
|
48
|
+
required '1'
|
49
|
+
end
|
50
|
+
|
51
|
+
trait :include_blank do
|
52
|
+
include_blank '1'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
ENV["RAILS_ENV"] ||= 'test'
|
2
|
+
|
3
|
+
require 'simplecov'
|
4
|
+
|
5
|
+
SimpleCov.start 'rails' do
|
6
|
+
add_group 'Models', 'app/models'
|
7
|
+
add_group 'Validators', 'app/validators'
|
8
|
+
end
|
9
|
+
|
10
|
+
# Load rails
|
11
|
+
require File.expand_path("../dummy/config/environment", __FILE__)
|
12
|
+
|
13
|
+
# Load test related gem
|
14
|
+
require 'rspec/rails'
|
15
|
+
require 'rspec/autorun'
|
16
|
+
require 'factory_girl_rails'
|
17
|
+
require 'faker'
|
18
|
+
|
19
|
+
|
20
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
21
|
+
# in spec/support/ and its subdirectories.
|
22
|
+
Dir[Rails.root.join("#{File.dirname(__FILE__)}/support/**/*.rb")].each { |f| require f }
|
23
|
+
|
24
|
+
RSpec.configure do |config|
|
25
|
+
# ## Mock Framework
|
26
|
+
#
|
27
|
+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
28
|
+
#
|
29
|
+
# config.mock_with :mocha
|
30
|
+
# config.mock_with :flexmock
|
31
|
+
# config.mock_with :rr
|
32
|
+
|
33
|
+
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
34
|
+
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
35
|
+
|
36
|
+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
37
|
+
# examples within a transaction, remove the following line or assign false
|
38
|
+
# instead of true.
|
39
|
+
config.use_transactional_fixtures = true
|
40
|
+
|
41
|
+
# If true, the base class of anonymous controllers will be inferred
|
42
|
+
# automatically. This will be the default behavior in future versions of
|
43
|
+
# rspec-rails.
|
44
|
+
config.infer_base_class_for_anonymous_controllers = false
|
45
|
+
|
46
|
+
# Run specs in random order to surface order dependencies. If you find an
|
47
|
+
# order dependency and want to debug it, you can fix the order by providing
|
48
|
+
# the seed, which is printed after each run.
|
49
|
+
# --seed 1234
|
50
|
+
config.order = "random"
|
51
|
+
config.include FactoryGirl::Syntax::Methods
|
52
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
RSpec::Matchers.define :include_validator do |expected_validator|
|
2
|
+
match do |array_of_validators|
|
3
|
+
array_include_validator?(array_of_validators, expected_validator)
|
4
|
+
end
|
5
|
+
|
6
|
+
def array_include_validator?(array, validator)
|
7
|
+
array.each do |v|
|
8
|
+
return true if v.class == validator.class
|
9
|
+
v.attributes == validator.attributes &&
|
10
|
+
v.options == validator.options
|
11
|
+
end
|
12
|
+
false
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FieldableForm
|
4
|
+
|
5
|
+
class MockModel
|
6
|
+
include ActiveModel::Validations
|
7
|
+
include FieldableForm::EntryValidations
|
8
|
+
|
9
|
+
attr_accessor :form, :values
|
10
|
+
|
11
|
+
def initialize(form, values)
|
12
|
+
@form = form
|
13
|
+
@values = values || {}
|
14
|
+
@errors = ActiveModel::Errors.new(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
validate_fieldable_form_entry :form, :values
|
18
|
+
end
|
19
|
+
|
20
|
+
describe EntryValidations do
|
21
|
+
let(:model) { MockModel.new(form, values) }
|
22
|
+
|
23
|
+
context 'when the form contains required field' do
|
24
|
+
let(:field1) { build_stubbed(:text_field, :required) }
|
25
|
+
let(:form) { stub(:fields => [field1]) }
|
26
|
+
|
27
|
+
context 'and the model does not have that field filled' do
|
28
|
+
let(:values) { { field1.name => '' } }
|
29
|
+
specify { model.should_not be_valid }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'and the model have that field filled' do
|
33
|
+
let(:values) { { field1.name => 'random text' } }
|
34
|
+
specify { model.should be_valid }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when the form contains number only field' do
|
39
|
+
let(:field1) { build_stubbed(:text_field, :number_only) }
|
40
|
+
let(:form) { stub(:fields => [field1]) }
|
41
|
+
|
42
|
+
context "and the model's field contain charactor other than number" do
|
43
|
+
let(:values) { { field1.name => 'some chars 123' } }
|
44
|
+
specify { model.should_not be_valid }
|
45
|
+
end
|
46
|
+
|
47
|
+
context "and the model's field contain only number" do
|
48
|
+
let(:values) { { field1.name => '39387593873' } }
|
49
|
+
specify { model.should be_valid }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when the form have a field that restrict max length' do
|
54
|
+
let(:field1) { build_stubbed(:text_field, :max_length => 5) }
|
55
|
+
let(:form) { stub(:fields => [field1]) }
|
56
|
+
|
57
|
+
context "and the model's field exceed the max length" do
|
58
|
+
let(:values) { { field1.name => 'longer than 5 char' } }
|
59
|
+
specify { model.should_not be_valid }
|
60
|
+
end
|
61
|
+
|
62
|
+
context "and the model's field did not exceed the max length" do
|
63
|
+
let(:values) { { field1.name => '12345' } }
|
64
|
+
specify { model.should be_valid }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when the form have a field that restrict min length' do
|
69
|
+
let(:field1) { build_stubbed(:text_field, :min_length => 3) }
|
70
|
+
let(:form) { stub(:fields => [field1]) }
|
71
|
+
|
72
|
+
context "and the model's field did not reach the min length" do
|
73
|
+
let(:values) { { field1.name => '12' } }
|
74
|
+
specify { model.should_not be_valid }
|
75
|
+
end
|
76
|
+
|
77
|
+
context "and the model's field reached the min length" do
|
78
|
+
let(:values) { { field1.name => '12345' } }
|
79
|
+
specify { model.should be_valid }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module FieldableForm
|
2
|
+
describe DropDown do
|
3
|
+
|
4
|
+
let(:field) { build_stubbed(:drop_down) }
|
5
|
+
subject { field }
|
6
|
+
|
7
|
+
it { should respond_to :required, :include_blank, :items }
|
8
|
+
it { should be_valid }
|
9
|
+
|
10
|
+
describe '#required=' do
|
11
|
+
before { field.required = 'changed' }
|
12
|
+
|
13
|
+
it 'should be captured in the options' do
|
14
|
+
field.options['required'].should eq 'changed'
|
15
|
+
field.required.should eq 'changed'
|
16
|
+
field.options_changed?.should eq true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#include_blank=' do
|
21
|
+
before { field.include_blank = 'changed' }
|
22
|
+
|
23
|
+
it 'should be captured in the options' do
|
24
|
+
field.options['include_blank'].should eq 'changed'
|
25
|
+
field.include_blank.should eq 'changed'
|
26
|
+
field.options_changed?.should eq true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#items=' do
|
31
|
+
before { field.items = 'changed' }
|
32
|
+
|
33
|
+
it 'should be captured in the options' do
|
34
|
+
field.options['items'].should eq 'changed'
|
35
|
+
field.items.should eq 'changed'
|
36
|
+
field.options_changed?.should eq true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#validators' do
|
41
|
+
subject { field.validators }
|
42
|
+
|
43
|
+
context 'when required is set' do
|
44
|
+
before { field.required = '1' }
|
45
|
+
it { should include_validator ActiveModel::Validations::PresenceValidator.new(:attributes => field.name) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#render_options' do
|
50
|
+
subject { field.render_options }
|
51
|
+
|
52
|
+
context 'when include_blank is set' do
|
53
|
+
before do
|
54
|
+
field.include_blank = '1'
|
55
|
+
field.items = 'a,b,c'
|
56
|
+
end
|
57
|
+
it { should eq [field.name, [['a', nil], ['b', 'b'], ['c', 'c']]] }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when include_blank is not set' do
|
61
|
+
before do
|
62
|
+
field.items = 'a,b,c'
|
63
|
+
end
|
64
|
+
it { should eq [field.name, ['a', 'b', 'c']] }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FieldableForm
|
4
|
+
|
5
|
+
class ConcreteField < Field
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Field do
|
9
|
+
|
10
|
+
let(:field) { ConcreteField.new }
|
11
|
+
subject { field }
|
12
|
+
|
13
|
+
describe 'attribtues and associations' do
|
14
|
+
it { should respond_to :name }
|
15
|
+
it { should respond_to :options }
|
16
|
+
it { should respond_to :fieldable }
|
17
|
+
it { should respond_to :type }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '.new' do
|
21
|
+
context 'when type is not supplied' do
|
22
|
+
it 'should raise an exception' do
|
23
|
+
expect { Field.new }.to raise_error(CannotInitializeAbstractClass)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when a type is supplied but is not one of Field's descendants" do
|
28
|
+
it 'should raise an exception' do
|
29
|
+
expect { Field.new(:type => 'invalid') }.to raise_error(CannotInitializeAbstractClass)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when descendant type is given' do
|
34
|
+
it 'should create an instance of that descendant' do
|
35
|
+
Field.new(:type => 'FieldableForm::TextField').should be_instance_of(TextField)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FieldableForm
|
4
|
+
describe TextField do
|
5
|
+
|
6
|
+
let(:field) { build_stubbed(:text_field) }
|
7
|
+
subject { field }
|
8
|
+
|
9
|
+
it { should respond_to :required, :number_only, :min_length, :max_length }
|
10
|
+
it { should be_valid }
|
11
|
+
|
12
|
+
describe 'validations' do
|
13
|
+
context 'when min_length is not a number' do
|
14
|
+
before { field.min_length = 'invalid' }
|
15
|
+
it { should_not be_valid }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when max_length is not a number' do
|
19
|
+
before { field.max_length = 'invalid' }
|
20
|
+
it { should_not be_valid }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#required=' do
|
25
|
+
before { field.required = 'changed' }
|
26
|
+
|
27
|
+
it 'should be captured in the options' do
|
28
|
+
field.options['required'].should eq 'changed'
|
29
|
+
field.required.should eq 'changed'
|
30
|
+
field.options_changed?.should eq true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#number_only=' do
|
35
|
+
before { field.number_only = 'changed' }
|
36
|
+
|
37
|
+
it 'should be captured in the options' do
|
38
|
+
field.options['number_only'].should eq 'changed'
|
39
|
+
field.number_only.should eq 'changed'
|
40
|
+
field.options_changed?.should eq true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#min_length=' do
|
45
|
+
before { field.min_length = 'changed' }
|
46
|
+
|
47
|
+
it 'should be captured in the options' do
|
48
|
+
field.options['min_length'].should eq 'changed'
|
49
|
+
field.min_length.should eq 'changed'
|
50
|
+
field.options_changed?.should eq true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#max_length=' do
|
55
|
+
before { field.max_length = 'changed' }
|
56
|
+
|
57
|
+
it 'should be captured in the options' do
|
58
|
+
field.options['max_length'].should eq 'changed'
|
59
|
+
field.max_length.should eq 'changed'
|
60
|
+
field.options_changed?.should eq true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#validators' do
|
65
|
+
subject { field.validators }
|
66
|
+
|
67
|
+
context 'when required is set' do
|
68
|
+
before { field.required = '1' }
|
69
|
+
it { should include_validator ActiveModel::Validations::PresenceValidator.new(:attributes => field.name) }
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when number_only is set' do
|
73
|
+
before { field.number_only = '1' }
|
74
|
+
it { should include_validator ActiveModel::Validations::NumericalityValidator.new(:attributes => field.name, :only_integer => true) }
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'when min_length is set' do
|
78
|
+
before { field.min_length = (rand(10) + 10).to_s }
|
79
|
+
it { should include_validator ActiveModel::Validations::LengthValidator.new(:attributes => field.name, :minimum => Integer(field.min_length)) }
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when max_length is set' do
|
83
|
+
before { field.max_length = (rand(10) + 10).to_s }
|
84
|
+
it { should include_validator ActiveModel::Validations::LengthValidator.new(:attributes => field.name, :maximum => Integer(field.max_length)) }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|