form_object 0.0.1 → 0.1.1
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/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +45 -1
- data/Rakefile +1 -1
- data/TODO +6 -3
- data/lib/form_object.rb +12 -2
- data/lib/form_object/base.rb +4 -3
- data/lib/form_object/base/collection.rb +33 -0
- data/lib/form_object/base/form_builder.rb +29 -0
- data/lib/form_object/base/mapping_information.rb +14 -0
- data/lib/form_object/dsl.rb +12 -0
- data/lib/form_object/dsl/class_methods.rb +25 -0
- data/lib/form_object/dsl/instance_methods.rb +18 -0
- data/lib/form_object/integrations.rb +24 -20
- data/lib/form_object/integrations/active_model.rb +19 -2
- data/lib/form_object/integrations/active_model/versions.rb +11 -0
- data/lib/form_object/integrations/active_record.rb +14 -2
- data/lib/form_object/integrations/active_record/versions.rb +15 -0
- data/lib/form_object/integrations/base.rb +69 -71
- data/lib/form_object/store.rb +32 -0
- data/lib/form_object/utils.rb +5 -0
- data/lib/form_object/utils/string_converter.rb +27 -0
- data/lib/form_object/version.rb +1 -1
- data/test/lib/form_object_test.rb +14 -2
- data/test/lib/form_relation_test.rb +16 -1
- data/test/lib/integrations/active_model_test.rb +16 -0
- data/test/lib/integrations/active_record_test.rb +39 -0
- data/test/lib/integrations/base_test.rb +2 -9
- data/test/lib/integrations_test.rb +20 -0
- data/test/lib/store_test.rb +36 -0
- data/test/support/active_record.rb +26 -0
- data/test/test_helper.rb +1 -0
- metadata +27 -9
- data/test/lib/forms_collection_test.rb +0 -11
- data/test/support/model.rb +0 -0
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/{LICENSE.txt → LICENSE}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -21,7 +21,51 @@ Or install it yourself as:
|
|
21
21
|
|
22
22
|
## Usage
|
23
23
|
|
24
|
-
|
24
|
+
We have a model
|
25
|
+
|
26
|
+
``` ruby
|
27
|
+
class User < ActiveRecord::Base
|
28
|
+
end
|
29
|
+
|
30
|
+
# attributes => {email: "test@example.com", name: "name"}
|
31
|
+
```
|
32
|
+
|
33
|
+
Define forms:
|
34
|
+
|
35
|
+
``` ruby
|
36
|
+
# For base auth
|
37
|
+
class BaseAuthForm < FormObject::Base
|
38
|
+
map_model User, as: :base_auth
|
39
|
+
attribute :email, String # => map form attribute to model attribute
|
40
|
+
|
41
|
+
validates :email, presence: true # => validate email in form ONLY!
|
42
|
+
end
|
43
|
+
|
44
|
+
# For any other auth
|
45
|
+
class TwitterAuthForm < FormObject::Base
|
46
|
+
map_model User # name => twitter_auth (name will be generated
|
47
|
+
# automatically from class name)
|
48
|
+
# There is nothing to validate
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
In any place:
|
53
|
+
|
54
|
+
``` ruby
|
55
|
+
@user = User.find(params[:id])
|
56
|
+
@form = @user.form( :base_auth ) # This retrive BaseAuthForm instance
|
57
|
+
# with attributes from model
|
58
|
+
@form.assign_attributes(params[:user]) # assign attributes from hash
|
59
|
+
|
60
|
+
if @form.valid?
|
61
|
+
@form.persist_model # TODO: maybe other method name?
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
## Can I help you?
|
66
|
+
|
67
|
+
Discuss the existing features and offer new features you can
|
68
|
+
[here](https://groups.google.com/d/forum/formobject "FormObject").
|
25
69
|
|
26
70
|
## Contributing
|
27
71
|
|
data/Rakefile
CHANGED
data/TODO
CHANGED
@@ -2,14 +2,17 @@ Features list
|
|
2
2
|
|
3
3
|
* Features
|
4
4
|
- Model:
|
5
|
-
|
6
|
-
|
5
|
+
+ Get the FormObject instance with filled attributes
|
6
|
+
+ Forms collection for retrive named form
|
7
7
|
- FormObject:
|
8
8
|
- Get the model with filled attributes
|
9
9
|
- Create builder for markup (form_for, simple_form_for, etc...)
|
10
10
|
|
11
11
|
* Integrations
|
12
|
-
|
12
|
+
+/- ActiveModel
|
13
|
+
+/- ActiveRecord
|
13
14
|
- Mongoid
|
14
15
|
- DataMapper 1.x
|
15
16
|
- DataMapper 2.x
|
17
|
+
- Validations
|
18
|
+
- Move validations in the appropriate integration
|
data/lib/form_object.rb
CHANGED
@@ -3,7 +3,17 @@ require 'virtus'
|
|
3
3
|
require 'active_model'
|
4
4
|
|
5
5
|
module FormObject
|
6
|
-
|
7
|
-
|
6
|
+
|
7
|
+
class ModelUndefinedError < RuntimeError
|
8
|
+
def initialize( form )
|
9
|
+
super "Model not defined for #{form.inspect}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
autoload :Utils, 'form_object/utils'
|
14
|
+
autoload :Integrations, 'form_object/integrations'
|
15
|
+
autoload :Base, 'form_object/base'
|
16
|
+
autoload :Store, 'form_object/store'
|
17
|
+
autoload :Dsl, 'form_object/dsl'
|
8
18
|
# Your code goes here...
|
9
19
|
end
|
data/lib/form_object/base.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
module FormObject
|
2
2
|
class Base
|
3
|
+
autoload :Collection, 'form_object/base/collection'
|
4
|
+
autoload :MappingInformation, 'form_object/base/mapping_information'
|
5
|
+
autoload :FormBuilder, 'form_object/base/form_builder'
|
3
6
|
include Virtus
|
4
7
|
|
5
8
|
extend ActiveModel::Naming
|
9
|
+
include Dsl
|
6
10
|
include ActiveModel::Conversion
|
7
11
|
include ActiveModel::Validations
|
8
12
|
|
9
13
|
# Forms are never themselves persisted
|
10
14
|
def persisted?; false; end
|
11
15
|
|
12
|
-
def model
|
13
|
-
nil
|
14
|
-
end
|
15
16
|
end
|
16
17
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module FormObject
|
2
|
+
|
3
|
+
class MappingInformationNotFound < RuntimeError
|
4
|
+
def initialize( critery )
|
5
|
+
super "#{critery.inspect} not found"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Base::Collection
|
10
|
+
attr_reader :model, :form_classes
|
11
|
+
|
12
|
+
def initialize( model )
|
13
|
+
@model = model
|
14
|
+
@form_classes = find_form_classes
|
15
|
+
end
|
16
|
+
|
17
|
+
def []( name )
|
18
|
+
build_form_instance(name)
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def find_form_classes
|
24
|
+
FormObject::Store.instance.find(model: @model.class).inject({}){|c, i| c[i.name] = i; c}
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_form_instance( name )
|
28
|
+
mapping_information = @form_classes[name]
|
29
|
+
raise MappingInformationNotFound.new(mapping_information) if mapping_information.nil?
|
30
|
+
FormObject::Base::FormBuilder.new(mapping_information, @model).build
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module FormObject
|
2
|
+
class Base::FormBuilder
|
3
|
+
attr_reader :mapping_information, :model
|
4
|
+
|
5
|
+
def initialize( mapping_information, model )
|
6
|
+
@mapping_information, @model = mapping_information, model
|
7
|
+
end
|
8
|
+
|
9
|
+
def build
|
10
|
+
form_instance
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def form_instance
|
16
|
+
@form_instance ||= assign_model_attributes(empty_form)
|
17
|
+
end
|
18
|
+
|
19
|
+
def empty_form
|
20
|
+
@mapping_information.form.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def assign_model_attributes( form_instance )
|
24
|
+
form_instance.assign_model( @model )
|
25
|
+
form_instance
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module FormObject
|
2
|
+
module Dsl
|
3
|
+
autoload :ClassMethods, 'form_object/dsl/class_methods'
|
4
|
+
autoload :InstanceMethods, 'form_object/dsl/instance_methods'
|
5
|
+
|
6
|
+
def self.included(receiver) #:nodoc:
|
7
|
+
receiver.extend ClassMethods
|
8
|
+
receiver.send :include, InstanceMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module FormObject
|
2
|
+
module Dsl
|
3
|
+
module ClassMethods
|
4
|
+
|
5
|
+
def map_model( model_class, options = {} )
|
6
|
+
store.map_for_model( self, model_class, options )
|
7
|
+
end
|
8
|
+
|
9
|
+
def form_name
|
10
|
+
FormObject::Utils::StringConverter.form_name(self.name).to_sym
|
11
|
+
end
|
12
|
+
|
13
|
+
def model
|
14
|
+
store.find(form: self).first.try(:model)
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def store
|
20
|
+
FormObject::Store.instance
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module FormObject
|
2
|
+
module Dsl
|
3
|
+
module InstanceMethods
|
4
|
+
|
5
|
+
def model
|
6
|
+
raise ModelUndefinedError.new(self) unless @model
|
7
|
+
@model.assign_form_object_attributes(self)
|
8
|
+
@model
|
9
|
+
end
|
10
|
+
|
11
|
+
def assign_model( model_instance )
|
12
|
+
@model = model_instance
|
13
|
+
self.attributes = @model.form_object_attributes
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,11 +1,10 @@
|
|
1
1
|
require 'form_object/integrations/base'
|
2
|
-
Dir[
|
2
|
+
Dir[File.join(File.dirname(__FILE__), "integrations", "*.rb")].sort.each do |path|
|
3
3
|
require "form_object/integrations/#{File.basename(path)}"
|
4
4
|
end
|
5
5
|
|
6
6
|
module FormObject
|
7
|
-
|
8
|
-
class IntegrationNotFound < StandardError
|
7
|
+
class InvalidIntegration < RuntimeError
|
9
8
|
def initialize( name )
|
10
9
|
super "#{name.inspect} is invalid integration"
|
11
10
|
end
|
@@ -13,31 +12,36 @@ module FormObject
|
|
13
12
|
|
14
13
|
module Integrations
|
15
14
|
|
16
|
-
#
|
17
|
-
# ActiveModel must be last always
|
18
|
-
# == Example
|
15
|
+
# Find integrations for for selected class
|
19
16
|
#
|
20
|
-
#
|
21
|
-
#
|
17
|
+
# == Examples:
|
18
|
+
# class User
|
19
|
+
# end
|
22
20
|
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
# class ActiveRecordUser < ActiveRecord::Base
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# FormObject::Integrations.match(User) # => nil
|
25
|
+
# FormObject::Integrations.match(ActiveRecordUser) # => FormObject::Integrations::ActiveRecord
|
26
|
+
def self.match( klass )
|
27
|
+
all.detect {|integration| integration.matches?(klass)}
|
28
28
|
end
|
29
29
|
|
30
30
|
# Find integration by name
|
31
|
-
#
|
32
|
-
# == Examples
|
33
|
-
# FormObject::Integrations.find(:active_record) # => FormObject::Integrations::ActiveRecord
|
34
31
|
#
|
35
|
-
|
36
|
-
|
32
|
+
# == Examples:
|
33
|
+
#
|
34
|
+
# FormObject::Integrations.find_by_name(:active_record) # => FormObject::Integrations::ActiveRecord
|
35
|
+
def self.find_by_name( name )
|
36
|
+
all.detect {|integration| integration.integration_name == name} || raise( InvalidIntegration.new(name) )
|
37
37
|
end
|
38
38
|
|
39
|
-
def self.
|
40
|
-
|
39
|
+
def self.all
|
40
|
+
# ActiveModel should be last item
|
41
|
+
constants = self.constants.map {|c| c.to_s}
|
42
|
+
.select {|c| c != 'ActiveModel'}
|
43
|
+
.sort << 'ActiveModel'
|
44
|
+
constants.map {|c| const_get(c)}
|
41
45
|
end
|
42
46
|
end
|
43
47
|
end
|
@@ -1,12 +1,29 @@
|
|
1
1
|
module FormObject
|
2
2
|
module Integrations
|
3
3
|
module ActiveModel
|
4
|
+
|
5
|
+
def self.included( base ) #:nodoc:
|
6
|
+
base.versions.unshift(*versions)
|
7
|
+
end
|
8
|
+
|
4
9
|
include Base
|
10
|
+
extend ClassMethods
|
11
|
+
require 'form_object/integrations/active_model/versions'
|
12
|
+
|
13
|
+
@defaults = {}
|
5
14
|
|
6
|
-
def self.
|
7
|
-
%w
|
15
|
+
def self.maching_ancestors
|
16
|
+
%w{ActiveModel ActiveModel::Observing ActiveModel::Validations}
|
8
17
|
end
|
9
18
|
|
19
|
+
def assign_form_object_attributes( form )
|
20
|
+
self.assign_attributes( form.attributes )
|
21
|
+
end
|
22
|
+
|
23
|
+
def form_object_attributes
|
24
|
+
self.attributes
|
25
|
+
end
|
26
|
+
|
10
27
|
end
|
11
28
|
end
|
12
29
|
end
|
@@ -1,10 +1,22 @@
|
|
1
|
+
require 'form_object/integrations/active_model'
|
2
|
+
|
1
3
|
module FormObject
|
2
4
|
module Integrations
|
3
5
|
module ActiveRecord
|
4
|
-
include Base
|
5
6
|
|
7
|
+
include Base
|
8
|
+
include ActiveModel
|
9
|
+
require 'form_object/integrations/active_record/versions'
|
10
|
+
|
11
|
+
@defaults = {}
|
12
|
+
|
13
|
+
def self.extended( base ) #:nodoc:
|
14
|
+
require 'active_record/version'
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
6
18
|
def self.matching_ancestors
|
7
|
-
%w
|
19
|
+
%w{ActiveRecord::Base}
|
8
20
|
end
|
9
21
|
|
10
22
|
end
|
@@ -1,110 +1,108 @@
|
|
1
1
|
module FormObject
|
2
2
|
module Integrations
|
3
3
|
module Base
|
4
|
+
|
5
|
+
# DSL methods for integrations
|
4
6
|
module ClassMethods
|
5
|
-
# The default
|
6
|
-
|
7
|
-
|
8
|
-
# FormsCollection for this model
|
9
|
-
#
|
10
|
-
# == Example
|
11
|
-
#
|
12
|
-
# class BaseForm < FormObject::Base
|
13
|
-
# model User
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# class TwitterForm < FormObject::Base
|
17
|
-
# model User, as: :twitter
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# @user = User.new
|
21
|
-
# @base_form = @user.forms[:base] # => instance of BaseForm
|
22
|
-
# @twitter_form = @iser.forms[:twitter] # => instance of TwitterForm
|
23
|
-
#
|
24
|
-
# Forms must have names. If the form name is not specified, it is taken
|
25
|
-
# from class name.
|
26
|
-
def forms
|
27
|
-
nil
|
28
|
-
end
|
7
|
+
# The default optons for integration
|
8
|
+
attr_accessor :defaults
|
29
9
|
|
30
|
-
# The name of
|
10
|
+
# The name of integration
|
31
11
|
def integration_name
|
32
12
|
@integration_name ||= begin
|
33
|
-
|
34
|
-
name.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
35
|
-
name.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
36
|
-
name.downcase!
|
37
|
-
name.to_sym
|
13
|
+
FormObject::Utils::StringConverter.integration_name(self.name).to_sym
|
38
14
|
end
|
39
15
|
end
|
40
|
-
|
41
|
-
#
|
42
|
-
#
|
43
|
-
|
44
|
-
def available?
|
16
|
+
|
17
|
+
# Integration avaliable only if the ORM that integration is for
|
18
|
+
# currently defined
|
19
|
+
def avaliable?
|
45
20
|
matching_ancestors.any? && Object.const_defined?(matching_ancestors[0].split('::')[0])
|
46
21
|
end
|
47
|
-
|
48
|
-
# The list of ancestor names that cause this integration to
|
22
|
+
|
23
|
+
# The list of ancestor names that cause this integration to
|
24
|
+
# matched.
|
49
25
|
def matching_ancestors
|
50
26
|
[]
|
51
27
|
end
|
52
28
|
|
53
|
-
|
54
|
-
|
55
|
-
ancestor_names = klasses.map {|klass| klass.ancestors.map(&:name)}
|
56
|
-
matches_ancestors?(ancestor_names)
|
29
|
+
def matches?( klass )
|
30
|
+
matches_ancestors?(klass.ancestors.map(&:name))
|
57
31
|
end
|
58
32
|
|
59
|
-
|
60
|
-
def matches_ancestors?(ancestors)
|
33
|
+
def matches_ancestors?( ancestors )
|
61
34
|
(ancestors & matching_ancestors).any?
|
62
35
|
end
|
63
36
|
|
64
|
-
# The path to the locale file containing translations for this
|
65
|
-
# integration. This file will only exist for integrations that actually
|
66
|
-
# support i18n.
|
67
|
-
def locale_path
|
68
|
-
path = "#{File.dirname(__FILE__)}/#{integration_name}/locale.rb"
|
69
|
-
path if File.exists?(path)
|
70
|
-
end
|
71
|
-
|
72
|
-
# Extends the given object with any version overrides that are currently
|
73
|
-
# active
|
74
|
-
def extended(base)
|
75
|
-
versions.each do |version|
|
76
|
-
base.extend(version) if version.active?
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# Defined versions
|
81
37
|
def versions
|
82
38
|
@versions ||= []
|
83
39
|
end
|
84
40
|
|
85
|
-
#
|
41
|
+
# Define current version for integration
|
42
|
+
# Can override some methods for different versions
|
86
43
|
#
|
87
|
-
|
88
|
-
|
89
|
-
|
44
|
+
# == Example:
|
45
|
+
#
|
46
|
+
# module FormObject
|
47
|
+
# module Integrations
|
48
|
+
# module DataMapper
|
49
|
+
# version '1.x' do
|
50
|
+
# def persist_model
|
51
|
+
# # model.save
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# version '2.x' do
|
56
|
+
# def persist_model
|
57
|
+
# # DataMapper[model.class].persist(model)
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
def version( name, &blk )
|
65
|
+
versions << mod = Module.new( &blk )
|
90
66
|
mod
|
91
67
|
end
|
92
68
|
|
69
|
+
def assign_model_attributes( form_instance, model_instance )
|
70
|
+
form_instance.attributes = model_instance.attributes
|
71
|
+
end
|
72
|
+
|
73
|
+
# Extend only active versions
|
74
|
+
def extended( base )
|
75
|
+
versions.select(&:active?).each do |version|
|
76
|
+
base.extend(version)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
93
80
|
end
|
94
81
|
|
95
|
-
extend ClassMethods
|
96
|
-
|
97
82
|
module InstanceMethods
|
98
83
|
|
99
|
-
#
|
84
|
+
# Forms hash for current model
|
100
85
|
def forms
|
101
|
-
self
|
86
|
+
@forms ||= FormObject::Base::Collection.new(self)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Get form by given name
|
90
|
+
def form( name )
|
91
|
+
forms[name]
|
92
|
+
end
|
93
|
+
|
94
|
+
def form_object_attributes
|
95
|
+
Hash.new
|
102
96
|
end
|
97
|
+
|
98
|
+
|
103
99
|
end
|
100
|
+
|
101
|
+
extend ClassMethods
|
104
102
|
|
105
|
-
def self.included(receiver)
|
106
|
-
receiver.extend
|
107
|
-
receiver.
|
103
|
+
def self.included(receiver)
|
104
|
+
receiver.class_eval { extend ClassMethods }
|
105
|
+
receiver.class_eval { include InstanceMethods }
|
108
106
|
end
|
109
107
|
end
|
110
108
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module FormObject
|
4
|
+
class Store
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def storage
|
8
|
+
@storage ||= Set.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def map_for_model( form, model, options = {})
|
12
|
+
form_name = retrive_form_name(form, options.delete(:as))
|
13
|
+
storage << FormObject::Base::MappingInformation.new(form, model, form_name, options )
|
14
|
+
include_integration( model )
|
15
|
+
end
|
16
|
+
|
17
|
+
def find(critery = {})
|
18
|
+
storage.select{|mapping_info| mapping_info.match?(critery)}
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def retrive_form_name( form, name )
|
24
|
+
name ||= form.form_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def include_integration( model_class )
|
28
|
+
integration = FormObject::Integrations.match(model_class)
|
29
|
+
model_class.send(:include, integration) unless integration.nil?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module FormObject
|
2
|
+
module Utils
|
3
|
+
module StringConverter
|
4
|
+
|
5
|
+
def self.integration_name( word )
|
6
|
+
name = word.split('::').last
|
7
|
+
underscore(name)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.form_name( word )
|
11
|
+
name = word.split('::').last
|
12
|
+
name.gsub!(/Form/, '')
|
13
|
+
underscore(name).to_sym
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def self.underscore( original_word, options = {} )
|
19
|
+
word = original_word.to_s.dup
|
20
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
21
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
22
|
+
word.downcase!
|
23
|
+
word
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/form_object/version.rb
CHANGED
@@ -3,6 +3,8 @@ require 'test_helper'
|
|
3
3
|
class FormObjectTest < TestCase
|
4
4
|
def setup
|
5
5
|
@form = Filter.new(query: "find me")
|
6
|
+
@base_form = BaseAuthForm.new(email: "test@example.com", name: "test")
|
7
|
+
@twitter_form = TwitterAuthForm.new
|
6
8
|
end
|
7
9
|
|
8
10
|
def test_should_form_not_persisted
|
@@ -15,16 +17,26 @@ class FormObjectTest < TestCase
|
|
15
17
|
|
16
18
|
def test_should_be_valid_form
|
17
19
|
assert @form.valid?
|
20
|
+
assert @base_form.valid?
|
18
21
|
end
|
19
22
|
|
20
23
|
def test_should_be_invalid_with_empty_query
|
21
24
|
@form.query = ""
|
22
|
-
assert
|
25
|
+
assert @form.invalid?
|
23
26
|
end
|
24
27
|
|
25
28
|
def test_should_have_not_nil_created_at_attribute
|
26
|
-
|
29
|
+
assert_kind_of DateTime, @form.created_at
|
27
30
|
assert @form.created_at.present?
|
28
31
|
end
|
29
32
|
|
33
|
+
def test_base_form_have_a_model
|
34
|
+
assert_equal User, @base_form.class.model
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_form_should_have_name
|
38
|
+
assert_equal :base_auth, @base_form.class.form_name
|
39
|
+
assert_equal :twitter_auth, @twitter_form.class.form_name
|
40
|
+
end
|
41
|
+
|
30
42
|
end
|
@@ -2,11 +2,26 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class FormRelationTest < TestCase
|
4
4
|
def setup
|
5
|
+
@attributes = { email: "test@example.com", name: "name" }
|
5
6
|
@form = Filter.new(query: "find me")
|
7
|
+
@model = User.new(@attributes)
|
6
8
|
end
|
7
9
|
|
8
10
|
def test_should_not_form_get_model
|
9
11
|
assert_respond_to @form, :model
|
10
|
-
|
12
|
+
assert_raises FormObject::ModelUndefinedError do
|
13
|
+
@form.model
|
14
|
+
end
|
11
15
|
end
|
16
|
+
|
17
|
+
def test_model_should_have_forms
|
18
|
+
base_auth_form = @model.form( :base_auth )
|
19
|
+
assert @attributes[:email], base_auth_form.email
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_model_hould_not_have_undefined_inForm_field
|
23
|
+
base_auth_form = @model.form( :base_auth )
|
24
|
+
assert !base_auth_form.respond_to?( :name )
|
25
|
+
end
|
26
|
+
|
12
27
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Integrations
|
4
|
+
# Test ActiveModel integration
|
5
|
+
class ActiveModelTest < ::TestCase
|
6
|
+
# Test setup
|
7
|
+
def setup
|
8
|
+
@integration_name = :active_model
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_should_integration_finded_by_name
|
12
|
+
assert_equal FormObject::Integrations::ActiveModel, FormObject::Integrations.find_by_name(@integration_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Integrations
|
4
|
+
# Test ActiveRecord integration
|
5
|
+
class ActiveRecordTest < ::TestCase
|
6
|
+
# Test setup
|
7
|
+
def setup
|
8
|
+
@integration_name = :active_record
|
9
|
+
@user = User.new email: "test@example.com"
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_integration_finded_by_name
|
13
|
+
assert_equal FormObject::Integrations::ActiveRecord, FormObject::Integrations.find_by_name(@integration_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_should_match_active_record_integration
|
17
|
+
assert_equal FormObject::Integrations::ActiveRecord, FormObject::Integrations.match(User)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_have_base_auth_form_instance_for_user_model
|
21
|
+
form = @user.form( :base_auth )
|
22
|
+
assert form, "base_auth form is nil!"
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_form_should_have_attributes_from_model
|
26
|
+
form = @user.form( :base_auth )
|
27
|
+
assert_equal @user.email, form.email
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_should_form_get_model_with_new_attributes
|
31
|
+
form = @user.form( :base_auth )
|
32
|
+
new_user_email = "user@example.com"
|
33
|
+
form.attributes = {email: new_user_email}
|
34
|
+
model = form.model
|
35
|
+
assert_equal new_user_email, model.email
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -1,19 +1,12 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
module Integrations
|
4
|
-
|
5
4
|
class BaseTest < ::TestCase
|
6
|
-
|
7
5
|
def setup
|
8
|
-
superclass = Class.new
|
9
|
-
self.class.const_set('Vehicle', superclass)
|
10
|
-
|
11
|
-
@klass = Class.new(superclass)
|
12
6
|
end
|
13
7
|
|
14
|
-
def
|
15
|
-
assert_nil FormObject::Integrations.match(
|
8
|
+
def test_filter_class_should_not_have_integrations
|
9
|
+
assert_nil FormObject::Integrations.match(Filter)
|
16
10
|
end
|
17
|
-
|
18
11
|
end
|
19
12
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class IntegrationsTest < TestCase
|
4
|
+
def setup
|
5
|
+
@integrations = [
|
6
|
+
FormObject::Integrations::Base,
|
7
|
+
FormObject::Integrations::ActiveModel,
|
8
|
+
FormObject::Integrations::ActiveRecord
|
9
|
+
]
|
10
|
+
@base_form = BaseAuthForm.new(email: "test@example.com", name: "test")
|
11
|
+
@twitter_form = TwitterAuthForm.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_integrations_should_bee
|
15
|
+
FormObject::Integrations.all.each do |integration|
|
16
|
+
assert_includes @integrations, integration
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class StoreTest < TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@repo = FormObject::Store.instance
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_should_have_base_auth_in_collection
|
10
|
+
assert_equal BaseAuthForm, @repo.find(name: :base_auth).first.form
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_have_twitter_in_collection
|
14
|
+
assert_equal TwitterAuthForm, @repo.find(name: :twitter).first.form
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_repo_shold_find_form_for_model
|
18
|
+
critery = {}
|
19
|
+
assert_operator 0, :<, @repo.find(critery).count
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_find_by_model_class
|
23
|
+
assert_equal User, @repo.find(model: User).first.model
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_repo_shold_find_form_for_model_with_critery
|
27
|
+
critery = {name: :base_auth}
|
28
|
+
assert_operator 0, :<, @repo.find(critery).count
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_should_not_find_forms_for_wrong_critery
|
32
|
+
critery = { name: :wrong_name }
|
33
|
+
assert_equal [], @repo.find(critery)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
4
|
+
|
5
|
+
ActiveRecord::Migration.create_table :users do |t|
|
6
|
+
t.string :email
|
7
|
+
t.string :name
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
class User < ActiveRecord::Base
|
12
|
+
# Without form validations.
|
13
|
+
# Only Domain Validations
|
14
|
+
end
|
15
|
+
|
16
|
+
class BaseAuthForm < FormObject::Base
|
17
|
+
map_model User
|
18
|
+
|
19
|
+
attribute :email, String
|
20
|
+
|
21
|
+
validates :email, :presence => true
|
22
|
+
end
|
23
|
+
|
24
|
+
class TwitterAuthForm < FormObject::Base
|
25
|
+
map_model User, :as => :twitter
|
26
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: form_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: virtus
|
@@ -51,25 +51,40 @@ extensions: []
|
|
51
51
|
extra_rdoc_files: []
|
52
52
|
files:
|
53
53
|
- .gitignore
|
54
|
+
- .travis.yml
|
54
55
|
- Gemfile
|
55
|
-
- LICENSE
|
56
|
+
- LICENSE
|
56
57
|
- README.md
|
57
58
|
- Rakefile
|
58
59
|
- TODO
|
59
60
|
- form_object.gemspec
|
60
61
|
- lib/form_object.rb
|
61
62
|
- lib/form_object/base.rb
|
63
|
+
- lib/form_object/base/collection.rb
|
64
|
+
- lib/form_object/base/form_builder.rb
|
65
|
+
- lib/form_object/base/mapping_information.rb
|
66
|
+
- lib/form_object/dsl.rb
|
67
|
+
- lib/form_object/dsl/class_methods.rb
|
68
|
+
- lib/form_object/dsl/instance_methods.rb
|
62
69
|
- lib/form_object/integrations.rb
|
63
70
|
- lib/form_object/integrations/active_model.rb
|
71
|
+
- lib/form_object/integrations/active_model/versions.rb
|
64
72
|
- lib/form_object/integrations/active_record.rb
|
73
|
+
- lib/form_object/integrations/active_record/versions.rb
|
65
74
|
- lib/form_object/integrations/base.rb
|
75
|
+
- lib/form_object/store.rb
|
76
|
+
- lib/form_object/utils.rb
|
77
|
+
- lib/form_object/utils/string_converter.rb
|
66
78
|
- lib/form_object/version.rb
|
67
79
|
- test/lib/form_object_test.rb
|
68
80
|
- test/lib/form_relation_test.rb
|
69
|
-
- test/lib/
|
81
|
+
- test/lib/integrations/active_model_test.rb
|
82
|
+
- test/lib/integrations/active_record_test.rb
|
70
83
|
- test/lib/integrations/base_test.rb
|
84
|
+
- test/lib/integrations_test.rb
|
85
|
+
- test/lib/store_test.rb
|
86
|
+
- test/support/active_record.rb
|
71
87
|
- test/support/filter.rb
|
72
|
-
- test/support/model.rb
|
73
88
|
- test/test_helper.rb
|
74
89
|
homepage:
|
75
90
|
licenses: []
|
@@ -85,7 +100,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
100
|
version: '0'
|
86
101
|
segments:
|
87
102
|
- 0
|
88
|
-
hash:
|
103
|
+
hash: 305297741
|
89
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
105
|
none: false
|
91
106
|
requirements:
|
@@ -94,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
109
|
version: '0'
|
95
110
|
segments:
|
96
111
|
- 0
|
97
|
-
hash:
|
112
|
+
hash: 305297741
|
98
113
|
requirements: []
|
99
114
|
rubyforge_project: form_object
|
100
115
|
rubygems_version: 1.8.24
|
@@ -104,8 +119,11 @@ summary: Form object implementation
|
|
104
119
|
test_files:
|
105
120
|
- test/lib/form_object_test.rb
|
106
121
|
- test/lib/form_relation_test.rb
|
107
|
-
- test/lib/
|
122
|
+
- test/lib/integrations/active_model_test.rb
|
123
|
+
- test/lib/integrations/active_record_test.rb
|
108
124
|
- test/lib/integrations/base_test.rb
|
125
|
+
- test/lib/integrations_test.rb
|
126
|
+
- test/lib/store_test.rb
|
127
|
+
- test/support/active_record.rb
|
109
128
|
- test/support/filter.rb
|
110
|
-
- test/support/model.rb
|
111
129
|
- test/test_helper.rb
|
data/test/support/model.rb
DELETED
File without changes
|