aerogel-forms 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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +19 -0
- data/Rakefile +1 -0
- data/aerogel-forms.gemspec +25 -0
- data/app/helpers/form_helpers.rb +10 -0
- data/lib/aerogel/forms.rb +13 -0
- data/lib/aerogel/forms/fieldset.rb +20 -0
- data/lib/aerogel/forms/form_builder.rb +74 -0
- data/lib/aerogel/forms/form_button.rb +42 -0
- data/lib/aerogel/forms/form_field.rb +142 -0
- data/lib/aerogel/forms/form_object.rb +152 -0
- data/lib/aerogel/forms/version.rb +5 -0
- data/locales/aerogel-forms/en.yml +19 -0
- data/locales/aerogel-forms/ru.yml +19 -0
- data/views/form_builder/none/button.erb +1 -0
- data/views/form_builder/none/field.erb +7 -0
- data/views/form_builder/none/field_default.erb +1 -0
- data/views/form_builder/none/fieldset.erb +2 -0
- data/views/form_builder/none/form.erb +4 -0
- data/views/form_builder/standard/button.erb +12 -0
- data/views/form_builder/standard/button_cancel.erb +5 -0
- data/views/form_builder/standard/button_danger_submit.erb +1 -0
- data/views/form_builder/standard/button_default.erb +5 -0
- data/views/form_builder/standard/button_select.erb +1 -0
- data/views/form_builder/standard/button_submit.erb +1 -0
- data/views/form_builder/standard/field.erb +21 -0
- data/views/form_builder/standard/field_checkbox.erb +16 -0
- data/views/form_builder/standard/field_default.erb +5 -0
- data/views/form_builder/standard/field_hidden.erb +2 -0
- data/views/form_builder/standard/field_radio_buttons.erb +22 -0
- data/views/form_builder/standard/field_string.erb +5 -0
- data/views/form_builder/standard/field_textarea.erb +5 -0
- data/views/form_builder/standard/fieldset.erb +5 -0
- data/views/form_builder/standard/form.erb +19 -0
- metadata +122 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 188787e829a65986b1c47e0a6f56b268e7ec16ea
|
4
|
+
data.tar.gz: 436382cef67d8319d8682c37aa936fd4727323ff
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9ce138aa3510a5cf2e13bcc6f9647b9325ff1739b0999c7ef8af026ae3fe427d2abfa0d1eebc458c3a36694d034006e354a024cf9aa313c361879f07d065176d
|
7
|
+
data.tar.gz: 364aab258f84ad8bb848be1df772b2efa2a30c32b0af721956217b58594d8c4177f7c34439fc93d8b2157fb2a9b2c7b7086c044cdd4d494def3f79e10f886c36
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Alex Kukushkin
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Aerogel::Module123
|
2
|
+
|
3
|
+
An aerogel module skeleton. Starting point for any generic aerogel module.
|
4
|
+
|
5
|
+
This module template includes all folders an aerogel module can use, but none of them are obligatory. For example, if a module does not have any assets, it is perfectly safe to remove assets/* folders.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
1. Clone repository
|
10
|
+
2. Rename 'module123' to your module name anywhere
|
11
|
+
3. Add code, remove unneeded folders
|
12
|
+
|
13
|
+
In your application's config.ru:
|
14
|
+
```ruby
|
15
|
+
require 'aerogel'
|
16
|
+
require 'aerogel/module123' # ...change to your module name
|
17
|
+
|
18
|
+
run Aerogel::Application.load
|
19
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'aerogel/forms/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "aerogel-forms"
|
8
|
+
spec.version = Aerogel::Forms::VERSION
|
9
|
+
spec.authors = ["Alex Kukushkin"]
|
10
|
+
spec.email = ["alex@kukushk.in"]
|
11
|
+
spec.description = %q{Aerogel form helpers}
|
12
|
+
spec.summary = %q{Aerogel form helpers}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'aerogel-core', "~> 1.4"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'aerogel/core'
|
2
|
+
require "aerogel/forms/version"
|
3
|
+
require 'aerogel/forms/form_object'
|
4
|
+
require 'aerogel/forms/form_button'
|
5
|
+
require 'aerogel/forms/form_field'
|
6
|
+
require 'aerogel/forms/fieldset'
|
7
|
+
require "aerogel/forms/form_builder"
|
8
|
+
|
9
|
+
module Aerogel
|
10
|
+
# Finally, register module's root folder
|
11
|
+
register_path File.join( File.dirname(__FILE__), '..', '..' )
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Aerogel::Forms
|
2
|
+
|
3
|
+
# Fieldset represents a set of fields for a nested form object.
|
4
|
+
#
|
5
|
+
class Fieldset < FormObject
|
6
|
+
|
7
|
+
def wrap( content )
|
8
|
+
erb template( :fieldset ), locals: { fieldset: self, content: content }, layout: false
|
9
|
+
end
|
10
|
+
|
11
|
+
# Hidden field of a nested object
|
12
|
+
#
|
13
|
+
def hidden( name, value = nil )
|
14
|
+
f = data_field name
|
15
|
+
tag :input, type: :hidden, name: f.html_name, value: (value || f.value)
|
16
|
+
end
|
17
|
+
|
18
|
+
end # class Fieldset
|
19
|
+
|
20
|
+
end # module Aerogel::Forms
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Aerogel::Forms
|
2
|
+
|
3
|
+
class FormBuilder < FormObject
|
4
|
+
|
5
|
+
attr_accessor :options, :content
|
6
|
+
|
7
|
+
DEFAULT_OPTIONS = {
|
8
|
+
:style => :standard,
|
9
|
+
:method => :post,
|
10
|
+
:multipart => false,
|
11
|
+
# :action => :default_action,
|
12
|
+
:html_params => {'accept-charset' => 'UTF-8'}
|
13
|
+
}
|
14
|
+
|
15
|
+
|
16
|
+
def initialize( object, options, &block )
|
17
|
+
super( object, nil, nil, options, &block )
|
18
|
+
@hiddens = []
|
19
|
+
@options = DEFAULT_OPTIONS.dup.deep_merge( options )
|
20
|
+
@options[:cancel_url] ||= back
|
21
|
+
hidden csrf_field_name, csrf_token if csrf_protected?
|
22
|
+
hidden :id, object.id if object.respond_to? :id
|
23
|
+
end
|
24
|
+
|
25
|
+
def hidden( name, value )
|
26
|
+
@hiddens << { name: name, value: value }
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Renders button
|
31
|
+
#
|
32
|
+
def button( type = :submit, options = {} )
|
33
|
+
b = FormButton.new self, type, options
|
34
|
+
erb template( :button ), locals: { button: b, type: b.type, options: b.options, form_builder: self }, layout: false
|
35
|
+
end
|
36
|
+
|
37
|
+
# Renders a list of buttons
|
38
|
+
#
|
39
|
+
def buttons( *args )
|
40
|
+
args = [:cancel, :submit] if args.size == 0
|
41
|
+
output = ''
|
42
|
+
args.each do |b|
|
43
|
+
output += button b
|
44
|
+
end
|
45
|
+
output
|
46
|
+
end
|
47
|
+
|
48
|
+
def wrap( content )
|
49
|
+
erb :"form_builder/#{@style}/form", locals: { form: self, content: content }, layout: false
|
50
|
+
# self.instance_exec( self, &STYLES[@style][:form_decorator] )
|
51
|
+
end
|
52
|
+
|
53
|
+
# private
|
54
|
+
|
55
|
+
# Returns a Hash with <form ..> tag attributes.
|
56
|
+
#
|
57
|
+
def html_params
|
58
|
+
attrs = @options[:html_params].dup
|
59
|
+
attrs.merge!({
|
60
|
+
:method => @options[:method],
|
61
|
+
# :action => @options[:action]
|
62
|
+
})
|
63
|
+
attrs[:action] = @options[:action] if @options[:action]
|
64
|
+
attrs[:enctype] = 'multipart/form-data' if @options[:multipart]
|
65
|
+
attrs.map{|n, v| v.nil? ? "#{n}" : "#{n}=\"#{v}\""}.join(" ")
|
66
|
+
end
|
67
|
+
|
68
|
+
def render_hiddens
|
69
|
+
@hiddens.map{|hidden| (input_hidden_tag hidden[:name], hidden[:value])+"\n" }.join()
|
70
|
+
end
|
71
|
+
|
72
|
+
end # class FormBuilder
|
73
|
+
|
74
|
+
end # module Aerogel::Forms
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Aerogel::Forms
|
2
|
+
|
3
|
+
# Button represents a button in a form object.
|
4
|
+
#
|
5
|
+
class FormButton
|
6
|
+
|
7
|
+
attr_accessor :form_object, :type, :label, :options
|
8
|
+
|
9
|
+
# Known options to a field are processed, the rest (unknown options) goes
|
10
|
+
# as html params.
|
11
|
+
KNOWN_OPTIONS = [ :type, :label, :html_params ]
|
12
|
+
|
13
|
+
def initialize( form_object, type, options = {} )
|
14
|
+
default_opts = {}
|
15
|
+
default_opts[:label] = I18n.t "aerogel.forms.buttons.#{type}", default: type.to_s.humanize
|
16
|
+
if String === type || type == :save || type == :create
|
17
|
+
type = :submit
|
18
|
+
elsif type == :cancel
|
19
|
+
default_opts[:url] = form_object.options[:cancel_url]
|
20
|
+
end
|
21
|
+
options = default_opts.deep_merge options
|
22
|
+
|
23
|
+
self.form_object = form_object
|
24
|
+
self.type = type
|
25
|
+
self.options = options
|
26
|
+
end
|
27
|
+
|
28
|
+
def label
|
29
|
+
options[:label]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns a string of html params for the <button ...> tag.
|
33
|
+
#
|
34
|
+
def html_params
|
35
|
+
attrs = @options.except( *KNOWN_OPTIONS )
|
36
|
+
attrs = attrs.deep_merge( @options[:html_params] ) if @options.key? :html_params
|
37
|
+
attrs.to_html_params
|
38
|
+
end
|
39
|
+
|
40
|
+
end # class FormButton
|
41
|
+
|
42
|
+
end # module Aeroge::Forms
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Aerogel::Forms
|
2
|
+
|
3
|
+
# Field represents a field of form object.
|
4
|
+
#
|
5
|
+
class FormField
|
6
|
+
|
7
|
+
attr_accessor :form_object, :data_object, :name, :options
|
8
|
+
|
9
|
+
# Known options to a field are processed, the rest (unknown options) goes
|
10
|
+
# as html params.
|
11
|
+
KNOWN_OPTIONS = [ :as, :label, :value, :default_value, :hint, :required, :style, :html_params ]
|
12
|
+
|
13
|
+
def initialize( form_object, name, options = {} )
|
14
|
+
#unless name.is_a? Symbol
|
15
|
+
# raise ArgumentError.new "Field name should be a Symbol"
|
16
|
+
#end
|
17
|
+
self.form_object = form_object
|
18
|
+
self.data_object = form_object.object
|
19
|
+
self.name = name.to_sym
|
20
|
+
self.options = options
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns true if the field is actually a collection in parent object.
|
24
|
+
#
|
25
|
+
def is_collection?
|
26
|
+
data_object.send( name ).is_a? Array
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns input field type as a Symbol.
|
30
|
+
#
|
31
|
+
def type
|
32
|
+
return @type if @type
|
33
|
+
@type = options[:as]
|
34
|
+
if data_object.respond_to? :fields
|
35
|
+
@type ||= data_object.fields[name.to_s].type.name.parameterize.to_sym rescue nil
|
36
|
+
end
|
37
|
+
@type ||= :string
|
38
|
+
@type
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns input field label.
|
42
|
+
#
|
43
|
+
def label
|
44
|
+
return @label if @label
|
45
|
+
@label = options[:label]
|
46
|
+
@label ||= data_object.fields[name.to_s].label if data_object.respond_to?( :fields ) && data_object.fields[name.to_s]
|
47
|
+
@label ||= data_object.class.human_attribute_name( name.to_s, default: '' ) if data_object.class.respond_to?( :human_attribute_name )
|
48
|
+
@label = nil if @label == ''
|
49
|
+
@label ||= I18n.t "aerogel.forms.attributes.#{name}", default: name.to_s.humanize
|
50
|
+
@label
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns input field hint — a piece of short explanation rendered beside the field.
|
54
|
+
#
|
55
|
+
def hint
|
56
|
+
return @hint if @hint
|
57
|
+
@hint = options[:hint]
|
58
|
+
@hint = data_object.fields[name.to_s].hint if data_object.respond_to?( :fields ) && data_object.fields[name.to_s].respond_to?( :hint )
|
59
|
+
@hint
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns placeholder for the field, defaulting to label.
|
63
|
+
#
|
64
|
+
def placeholder
|
65
|
+
options[:placeholder] || label
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns field value.
|
69
|
+
#
|
70
|
+
def value
|
71
|
+
# return nil unless data_object.respond_to? :fields
|
72
|
+
return options[:value] if options[:value]
|
73
|
+
data_object.send name rescue default_value
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns field default value.
|
77
|
+
#
|
78
|
+
def default_value
|
79
|
+
return options[:default_value] if options[:default_value]
|
80
|
+
case type
|
81
|
+
when :checkbox
|
82
|
+
1
|
83
|
+
else
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns Rack-parseable form field name.
|
89
|
+
#
|
90
|
+
def html_name( use_name = nil )
|
91
|
+
prefix = form_object.field_prefix
|
92
|
+
use_name ||= name
|
93
|
+
prefix.nil? ? use_name.to_s : "#{prefix}[#{use_name}]"
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns unique css id for the field.
|
97
|
+
#
|
98
|
+
def css_id
|
99
|
+
html_name.parameterize+"-#{form_object.id}"
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns a string of html params for the <input ...> tag.
|
103
|
+
#
|
104
|
+
def html_params
|
105
|
+
attrs = @options.except( *KNOWN_OPTIONS )
|
106
|
+
attrs = attrs.deep_merge( @options[:html_params] ) if @options.key? :html_params
|
107
|
+
attrs.map{|n, v| v.nil? ? "#{n}" : "#{n}=\"#{v}\""}.join(" ")
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns list of error messages for the field.
|
111
|
+
#
|
112
|
+
def errors
|
113
|
+
data_object.errors.get name
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns true if the field is valid.
|
117
|
+
#
|
118
|
+
def valid?
|
119
|
+
form_object.valid? || errors.nil?
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns true if the field is invalid
|
123
|
+
#
|
124
|
+
def invalid?
|
125
|
+
not valid?
|
126
|
+
end
|
127
|
+
|
128
|
+
# Returns true if the field is required.
|
129
|
+
#
|
130
|
+
def required?
|
131
|
+
return options[:required] if !options[:required].nil?
|
132
|
+
if data_object.class.respond_to? :validators_on
|
133
|
+
vv = data_object.class.validators_on( name ).map(&:class)
|
134
|
+
vv.include?( Mongoid::Validations::PresenceValidator )
|
135
|
+
else
|
136
|
+
false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end # class Field
|
141
|
+
|
142
|
+
end # module Aerogel::Forms
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module Aerogel::Forms
|
2
|
+
|
3
|
+
# FormObject represents a model object associated with current form context.
|
4
|
+
# It provides access to model object fields and helper methods to form proper html.
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# form for: objectA <- FormObject
|
8
|
+
# nested form for: objectB <- FormObject
|
9
|
+
# list of nested form for collection: objectC1, objectC2..., objecCN
|
10
|
+
#
|
11
|
+
class FormObject < Aerogel::Render::BlockHelper
|
12
|
+
|
13
|
+
attr_accessor :object, :parent, :relation, :options, :style, :field_prefix
|
14
|
+
|
15
|
+
RESERVED_FIELDS = ['id', '_id']
|
16
|
+
|
17
|
+
DEFAULT_OPTIONS = {
|
18
|
+
:style => :standard
|
19
|
+
}
|
20
|
+
|
21
|
+
def initialize( object, parent = nil, relation = nil, options = {}, &block )
|
22
|
+
super( &block )
|
23
|
+
self.object = object
|
24
|
+
self.parent = parent
|
25
|
+
self.relation = relation
|
26
|
+
default_options = DEFAULT_OPTIONS.dup
|
27
|
+
default_options[:style] = parent.style unless parent.nil?
|
28
|
+
@options = default_options.deep_merge( options )
|
29
|
+
@style = @options[:style].to_sym
|
30
|
+
@first_input = nil
|
31
|
+
@field_prefix = options[:field_prefix] || make_field_prefix
|
32
|
+
end
|
33
|
+
|
34
|
+
def field( name, options = {} ) # -> Field
|
35
|
+
f = data_field name, options
|
36
|
+
unless @first_input || options.key?( :readonly )
|
37
|
+
@first_input = f
|
38
|
+
f.options[:autofocus] = nil
|
39
|
+
end
|
40
|
+
erb template( :field, f.options ), locals: { field: f, form_builder: self }, layout: false
|
41
|
+
end
|
42
|
+
|
43
|
+
# Renders fields listed in the arguments.
|
44
|
+
#
|
45
|
+
def fields( *args )
|
46
|
+
args = object.attribute_names - RESERVED_FIELDS if args.size == 0
|
47
|
+
output = ''
|
48
|
+
args.each do |f|
|
49
|
+
output += field f
|
50
|
+
end
|
51
|
+
output
|
52
|
+
end
|
53
|
+
|
54
|
+
def fieldset( name_or_object, opts = {}, &block )
|
55
|
+
# TODO: if name.nil?
|
56
|
+
if name_or_object.is_a? Symbol
|
57
|
+
name = name_or_object
|
58
|
+
if data_field( name ).is_collection?
|
59
|
+
i = 0
|
60
|
+
object.send( name ).each do |o|
|
61
|
+
Fieldset.new( o, self, name, opts.merge( object_index: o.id ), &block ).render
|
62
|
+
i += 1
|
63
|
+
end
|
64
|
+
else
|
65
|
+
o = object.send( name )
|
66
|
+
opts[:object_index] ||= o.id
|
67
|
+
Fieldset.new( object.send( name ), self, name, opts, &block ).render
|
68
|
+
end
|
69
|
+
else
|
70
|
+
# create new fieldset for given object with no parent
|
71
|
+
o = name_or_object
|
72
|
+
opts[:object_index] ||= o.id
|
73
|
+
Fieldset.new( name_or_object, opts[:parent] || self, opts[:name], opts, &block ).render
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns data object name.
|
78
|
+
# If the object name is not explicitly specified, it is inferred from
|
79
|
+
# the model name.
|
80
|
+
#
|
81
|
+
def object_name
|
82
|
+
return @object_name if @object_name
|
83
|
+
if @options[:object_name]
|
84
|
+
@object_name = @options[:object_name]
|
85
|
+
elsif object.respond_to? :model_name
|
86
|
+
@object_name = object.model_name.singular
|
87
|
+
else
|
88
|
+
@object_name = nil
|
89
|
+
end
|
90
|
+
@object_name
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns true if current form object is the root.
|
94
|
+
#
|
95
|
+
def root_object?
|
96
|
+
parent.nil?
|
97
|
+
end
|
98
|
+
|
99
|
+
def data_field( name, options = {} )
|
100
|
+
FormField.new self, name, options
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns data object id, degrading to self.object_id
|
104
|
+
#
|
105
|
+
def id
|
106
|
+
object.send(:id) rescue self.object_id
|
107
|
+
end
|
108
|
+
|
109
|
+
# Returns true if the object contains no errors.
|
110
|
+
#
|
111
|
+
def valid?
|
112
|
+
# object.send(:valid?) rescue true # if valid? not supported
|
113
|
+
!object.respond_to?(:errors) || object.errors.nil? || object.errors.size == 0
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns true if the object is not valid, i.e. contains errors.
|
117
|
+
#
|
118
|
+
def invalid?
|
119
|
+
not valid?
|
120
|
+
end
|
121
|
+
|
122
|
+
def template( name, opts = {} )
|
123
|
+
style = opts[:style] || @style
|
124
|
+
"form_builder/#{style}/#{name}".to_sym
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
# Generates field prefix for object fields.
|
131
|
+
#
|
132
|
+
def make_field_prefix
|
133
|
+
if root_object?
|
134
|
+
# root
|
135
|
+
object_name
|
136
|
+
elsif parent.data_field( relation ).is_collection?
|
137
|
+
# 1 - N, accepts nested attributes
|
138
|
+
if parent.object.respond_to? :"#{relation}_attributes="
|
139
|
+
parent.field_prefix+"[#{relation}_attributes][#{options[:object_index]}]"
|
140
|
+
else
|
141
|
+
parent.field_prefix+"[#{relation}][#{options[:object_index]}]"
|
142
|
+
end
|
143
|
+
else
|
144
|
+
# 1 - 1
|
145
|
+
parent.field_prefix+"[#{relation}][]"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
end # class FormObject
|
151
|
+
|
152
|
+
end # module Aerogel::Forms
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
en:
|
3
|
+
aerogel:
|
4
|
+
forms:
|
5
|
+
required: Required
|
6
|
+
|
7
|
+
buttons:
|
8
|
+
"ok": OK
|
9
|
+
cancel: Cancel
|
10
|
+
submit: Submit
|
11
|
+
save: Save changes
|
12
|
+
create: Create
|
13
|
+
close: Close
|
14
|
+
select: Select
|
15
|
+
|
16
|
+
attributes:
|
17
|
+
email: Email
|
18
|
+
password: Password
|
19
|
+
password_confirmation: Password confirmation
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
ru:
|
3
|
+
aerogel:
|
4
|
+
forms:
|
5
|
+
required: Обязательное поле
|
6
|
+
|
7
|
+
buttons:
|
8
|
+
"ok": OK
|
9
|
+
cancel: Отменить
|
10
|
+
submit: Отправить
|
11
|
+
save: Сохранить изменения
|
12
|
+
create: Создать
|
13
|
+
close: Закрыть
|
14
|
+
select: Выбрать
|
15
|
+
|
16
|
+
attributes:
|
17
|
+
email: Email
|
18
|
+
password: Пароль
|
19
|
+
password_confirmation: Подтверждение пароля
|
@@ -0,0 +1 @@
|
|
1
|
+
<button type="<%= type %>"><%= type %></button>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<%=
|
2
|
+
begin
|
3
|
+
erb form_builder.template( "field_#{field.type}" ), locals: { field: field, form_builder: form_builder }, layout: false
|
4
|
+
rescue Errno::ENOENT
|
5
|
+
erb form_builder.template( :field_default ), locals: { field: field, form_builder: form_builder }, layout: false
|
6
|
+
end
|
7
|
+
%>
|
@@ -0,0 +1 @@
|
|
1
|
+
<input id="<%= field.css_id %>" type="<%= field.type %>" name="<%= field.html_name %>" value="<%= h field.value %>" <%= field.required? ? 'required' : '' %> <%= field.html_params %> />
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%=
|
2
|
+
begin
|
3
|
+
erb form_builder.template( "button_#{type}" ), locals: {
|
4
|
+
button: button, type: type, options: options, form_builder: form_builder
|
5
|
+
}, layout: false
|
6
|
+
rescue Errno::ENOENT
|
7
|
+
erb form_builder.template( :button_default ), locals: {
|
8
|
+
button: button, type: type, options: options, form_builder: form_builder
|
9
|
+
}, layout: false
|
10
|
+
end
|
11
|
+
%>
|
12
|
+
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<% if button.options[:url].present? %>
|
2
|
+
<%= link_to button.options[:url], button.label, type: "cancel", class: "btn btn-default" %>
|
3
|
+
<% else %>
|
4
|
+
<button type="<%= button.type %>" class="btn btn-default" <%= button.html_params %> ><%= button.label %></button>
|
5
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<button type="submit" class="btn btn-danger" <%= button.html_params %> ><%= button.label %></button>
|
@@ -0,0 +1 @@
|
|
1
|
+
<button type="<%= type %>" class="btn btn-primary" <%= button.html_params %> ><%= button.label %></button>
|
@@ -0,0 +1 @@
|
|
1
|
+
<button type="<%= type %>" class="btn btn-primary" <%= button.html_params %> ><%= button.label %></button>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<% unless field.type.to_sym == :hidden -%>
|
2
|
+
<div class="form-group field <%= 'has-error' if field.invalid? %>">
|
3
|
+
<% end -%>
|
4
|
+
<%=
|
5
|
+
begin
|
6
|
+
erb form_builder.template( "field_#{field.type}", field.options ), locals: { field: field }, layout: false
|
7
|
+
rescue Errno::ENOENT
|
8
|
+
erb form_builder.template( :field_default, field.options ), locals: { field: field }, layout: false
|
9
|
+
end
|
10
|
+
%>
|
11
|
+
<% if field.hint %>
|
12
|
+
<span class="help-block"><%= field.hint %></span>
|
13
|
+
<% end %>
|
14
|
+
<% if field.invalid? %>
|
15
|
+
<span class="help-block field-errors">
|
16
|
+
<%= field.errors.join(', ') %>
|
17
|
+
</span>
|
18
|
+
<% end %>
|
19
|
+
<% unless field.type.to_sym == :hidden -%>
|
20
|
+
</div>
|
21
|
+
<% end -%>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<div class="checkbox">
|
2
|
+
<label for="<%= field.css_id %>">
|
3
|
+
<!-- input id="<%= field.css_id %>-hidden" type="hidden" name="<%= field.html_name %>"
|
4
|
+
value="<%= field.options[:false_value] ? h(field.options[:false_value]) : '' %>"
|
5
|
+
/ -->
|
6
|
+
|
7
|
+
<input id="<%= field.css_id %>" type="checkbox" name="<%= field.html_name %>"
|
8
|
+
value="<%= field.options[:true_value] ? h(field.options[:true_value]) : 'true' %>"
|
9
|
+
<%= field.value ? 'checked' : '' %>
|
10
|
+
<%= field.html_params %>
|
11
|
+
/>
|
12
|
+
|
13
|
+
<%= field.label -%>
|
14
|
+
</label>
|
15
|
+
|
16
|
+
</div>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<label for="<%= field.css_id %>"><%= field.label -%>
|
2
|
+
<% if field.required? -%> <abbr class="required" title="<%= t 'aerogel.forms.required' %>">*</abbr>
|
3
|
+
<% end -%>
|
4
|
+
</label>
|
5
|
+
<input id="<%= field.css_id %>" type="<%= field.type %>" name="<%= field.html_name %>" value="<%= h field.value %>" <%= field.required? ? 'required' : '' %> <%= field.html_params %> class="form-control" />
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<label for="<%= field.css_id %>"><%= field.label -%>
|
2
|
+
<% if field.required? -%> <abbr class="required" title="<%= t 'aerogel.forms.required' %>">*</abbr>
|
3
|
+
<% end -%>
|
4
|
+
</label>
|
5
|
+
|
6
|
+
<div class="input-group">
|
7
|
+
<div class="btn-group" data-toggle="buttons">
|
8
|
+
<% unless field.required? %>
|
9
|
+
<label class="btn btn-default <%= field.value.blank? ? 'active' : '' %>">
|
10
|
+
<input type="radio" class="form-control" name="<%= field.html_name %>" id="<%= field.css_id %>-11"
|
11
|
+
value <%= field.value.blank? ? 'checked=""' : '' %>>
|
12
|
+
<%= icon 'fa-times' %>
|
13
|
+
</label>
|
14
|
+
<% end %>
|
15
|
+
<% field.options[:values].each_with_index do |value, i| %>
|
16
|
+
<label class="btn btn-default <%= value.to_s == field.value.to_s ? 'active' : '' %>" >
|
17
|
+
<input type="radio" class="form-control" name="<%= field.html_name %>" id="<%= field.css_id %>-11" value="<%= h value %>" <%= value.to_s == field.value.to_s ? 'checked=""' : '' %>>
|
18
|
+
<%= field.options[:labels].present? ? h( field.options[:labels][i] ) : h( value ) %>
|
19
|
+
</label>
|
20
|
+
<% end %>
|
21
|
+
</div>
|
22
|
+
</div>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<label for="<%= field.css_id %>"><%= field.label -%>
|
2
|
+
<% if field.required? -%> <abbr class="required" title="<%= t 'aerogel.forms.required' %>">*</abbr>
|
3
|
+
<% end -%>
|
4
|
+
</label>
|
5
|
+
<input id="<%= field.css_id %>" type="text" name="<%= field.html_name %>" value="<%= h field.value %>" <%= field.required? ? 'required' : '' %> <%= field.html_params %> class="form-control" />
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<label for="<%= field.css_id %>"><%= field.label -%>
|
2
|
+
<% if field.required? -%> <abbr class="required" title="<%= t 'aerogel.forms.required' %>">*</abbr>
|
3
|
+
<% end -%>
|
4
|
+
</label>
|
5
|
+
<textarea id="<%= field.css_id %>" name="<%= field.html_name %>" <%= field.required? ? 'required' : '' %> <%= field.html_params %> class="form-control"><%= h field.value %></textarea>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<div class="form <%= 'form-with-errors' if form.invalid? %>">
|
2
|
+
<form <%= form.html_params %> role="form">
|
3
|
+
<% if form.invalid? && form.object.errors && form.object.errors[:base].size > 0 -%>
|
4
|
+
<div class="alert alert-danger">
|
5
|
+
<% if form.object.errors[:base].size == 1 %>
|
6
|
+
<%= form.object.errors[:base].first %>
|
7
|
+
<% elsif form.object.errors[:base].size > 1 %>
|
8
|
+
<ul>
|
9
|
+
<% form.object.errors[:base].each do |error_message| %>
|
10
|
+
<li><%= error_message %>
|
11
|
+
<% end %>
|
12
|
+
</ul>
|
13
|
+
<% end %>
|
14
|
+
</div>
|
15
|
+
<% end -%>
|
16
|
+
<%= form.render_hiddens %>
|
17
|
+
<%= content %>
|
18
|
+
</form>
|
19
|
+
</div>
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aerogel-forms
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alex Kukushkin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aerogel-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Aerogel form helpers
|
56
|
+
email:
|
57
|
+
- alex@kukushk.in
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- aerogel-forms.gemspec
|
68
|
+
- app/helpers/form_helpers.rb
|
69
|
+
- lib/aerogel/forms.rb
|
70
|
+
- lib/aerogel/forms/fieldset.rb
|
71
|
+
- lib/aerogel/forms/form_builder.rb
|
72
|
+
- lib/aerogel/forms/form_button.rb
|
73
|
+
- lib/aerogel/forms/form_field.rb
|
74
|
+
- lib/aerogel/forms/form_object.rb
|
75
|
+
- lib/aerogel/forms/version.rb
|
76
|
+
- locales/aerogel-forms/en.yml
|
77
|
+
- locales/aerogel-forms/ru.yml
|
78
|
+
- views/form_builder/none/button.erb
|
79
|
+
- views/form_builder/none/field.erb
|
80
|
+
- views/form_builder/none/field_default.erb
|
81
|
+
- views/form_builder/none/fieldset.erb
|
82
|
+
- views/form_builder/none/form.erb
|
83
|
+
- views/form_builder/standard/button.erb
|
84
|
+
- views/form_builder/standard/button_cancel.erb
|
85
|
+
- views/form_builder/standard/button_danger_submit.erb
|
86
|
+
- views/form_builder/standard/button_default.erb
|
87
|
+
- views/form_builder/standard/button_select.erb
|
88
|
+
- views/form_builder/standard/button_submit.erb
|
89
|
+
- views/form_builder/standard/field.erb
|
90
|
+
- views/form_builder/standard/field_checkbox.erb
|
91
|
+
- views/form_builder/standard/field_default.erb
|
92
|
+
- views/form_builder/standard/field_hidden.erb
|
93
|
+
- views/form_builder/standard/field_radio_buttons.erb
|
94
|
+
- views/form_builder/standard/field_string.erb
|
95
|
+
- views/form_builder/standard/field_textarea.erb
|
96
|
+
- views/form_builder/standard/fieldset.erb
|
97
|
+
- views/form_builder/standard/form.erb
|
98
|
+
homepage: ''
|
99
|
+
licenses:
|
100
|
+
- MIT
|
101
|
+
metadata: {}
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements: []
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 2.2.2
|
119
|
+
signing_key:
|
120
|
+
specification_version: 4
|
121
|
+
summary: Aerogel form helpers
|
122
|
+
test_files: []
|