sequent-sinatra 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sequent-sinatra/app.rb +35 -0
- data/lib/sequent-sinatra/fieldset.rb +37 -0
- data/lib/sequent-sinatra/form.rb +77 -0
- data/lib/sequent-sinatra/form_helpers.rb +30 -0
- data/lib/sequent-sinatra/sequent-sinatra.rb +6 -0
- data/lib/sequent-sinatra/simple_command_service_helpers.rb +23 -0
- data/lib/sequent-sinatra/tag_helper.rb +155 -0
- data/lib/version.rb +3 -0
- metadata +9 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6370a605d3032c7a3703e6b3d0ab82d4ac39f7c
|
4
|
+
data.tar.gz: 9d78a48b9878443e3b88b1c2f3b4f9b54acad5dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27aa83a9d1ed558bb83b046ceb4c6164bde37ea756bb980af508260dae753f69e5f61e96a2a1e0b847dd702f09977c57b5f08e89dfcf3241cffcf686508d8769
|
7
|
+
data.tar.gz: d46569e2c082c724ca22a55d28b35875d0efc3551257e071ca64ef75d1245ec3b55b72177d580b5173e258e0b58afa6a8f8e5807713b9f41ab315cbeec2946dc
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
module Sequent
|
3
|
+
module Web
|
4
|
+
module Sinatra
|
5
|
+
# Allows for easy integration with Sinatra apps.
|
6
|
+
# Provides:
|
7
|
+
#
|
8
|
+
# +Sequent::Core::Helpers::UuidHelper+
|
9
|
+
# +FormHelpers+
|
10
|
+
# +SimpleCommandServiceHelpers+
|
11
|
+
#
|
12
|
+
# The +sequent_config_dir+ allows you to specify the directory containing the
|
13
|
+
# 'initializers/sequent' file that initializes the +EventStore+ and +CommandService+ for your webapp.
|
14
|
+
#
|
15
|
+
# class MySinatraApp < Sinatra::Base
|
16
|
+
# set :sequent_config_dir, root
|
17
|
+
# register Sequent::Web::Sinatra::App
|
18
|
+
# end
|
19
|
+
module App
|
20
|
+
def self.registered(app)
|
21
|
+
app.helpers Sequent::Core::Helpers::UuidHelper
|
22
|
+
app.helpers Sequent::Web::Sinatra::FormHelpers
|
23
|
+
app.helpers Sequent::Web::Sinatra::SimpleCommandServiceHelpers
|
24
|
+
|
25
|
+
app.before do
|
26
|
+
require File.join(app.sequent_config_dir || app.root, 'initializers/sequent')
|
27
|
+
@command_service = Sequent::Core::CommandService.instance
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
Sinatra.register Sequent::Web::Sinatra::App
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative 'tag_helper'
|
2
|
+
require_relative 'fieldset'
|
3
|
+
|
4
|
+
module Sequent
|
5
|
+
module Web
|
6
|
+
module Sinatra
|
7
|
+
class Fieldset
|
8
|
+
include Sequent::Web::Sinatra::TagHelper
|
9
|
+
|
10
|
+
attr_reader :path, :parent
|
11
|
+
|
12
|
+
def initialize(parent, path, params, errors, options = {})
|
13
|
+
raise "params are empty while creating new fieldset path #{path}" unless params
|
14
|
+
@values = params.has_key?(path) ? (params[path] || {}) : {}
|
15
|
+
@parent = parent
|
16
|
+
@path = path.to_s.gsub(/\W+/, '')
|
17
|
+
@errors = errors
|
18
|
+
@options = options
|
19
|
+
end
|
20
|
+
|
21
|
+
def nested(name)
|
22
|
+
yield Fieldset.new(self, name, @values, @errors, @options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method, *args, &block)
|
26
|
+
@parent.send(method, *args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def path_for(field_name)
|
30
|
+
css_id @path, field_name
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require_relative 'tag_helper'
|
2
|
+
require_relative 'fieldset'
|
3
|
+
|
4
|
+
module Sequent
|
5
|
+
module Web
|
6
|
+
module Sinatra
|
7
|
+
class Form
|
8
|
+
include TagHelper
|
9
|
+
|
10
|
+
def initialize(context, for_object, action, method=:get, options = {})
|
11
|
+
@context = context
|
12
|
+
@values = params
|
13
|
+
@errors = @context.instance_variable_get("@errors")
|
14
|
+
@for_object = for_object
|
15
|
+
@action = action
|
16
|
+
@method = method
|
17
|
+
@options = options
|
18
|
+
end
|
19
|
+
|
20
|
+
def path_for(field_name)
|
21
|
+
css_id field_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(method, *args, &block)
|
25
|
+
@context.send(method, *args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def render(&block)
|
29
|
+
method_input = ''
|
30
|
+
if @method.is_a? Symbol
|
31
|
+
case @method.to_s.downcase
|
32
|
+
when 'delete', 'update'
|
33
|
+
method_input = %Q(<input type="hidden" name="_method" value="#{@method}" />)
|
34
|
+
@method = :post
|
35
|
+
when 'create'
|
36
|
+
@method = :post
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
inner_html = capture_erb(self, &block)
|
41
|
+
out = tag(:form, nil, {:action => @action, :method => @method.to_s.upcase}.merge(@options)) + method_input + csrf_tag
|
42
|
+
out << inner_html
|
43
|
+
out << '</form>'
|
44
|
+
buf = @context.instance_variable_get("@_out_buf")
|
45
|
+
buf << out
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
def fieldset(obj_name, options = {}, &block)
|
50
|
+
raise ArgumentError, "Missing block to fieldset()" unless block_given?
|
51
|
+
raise "can not create a fieldset without a form backing object" unless @for_object
|
52
|
+
params.merge!(params.nil? ? {obj_name.to_s => @for_object.as_params} : params.merge({obj_name.to_s => @for_object.as_params}))
|
53
|
+
yield Fieldset.new(@context, obj_name, HashWithIndifferentAccess.new(params), @errors, options)
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
private
|
58
|
+
def capture_erb(*args, &block)
|
59
|
+
erb_with_output_buffer { block_given? && block.call(*args) }
|
60
|
+
end
|
61
|
+
|
62
|
+
def erb_with_output_buffer(buf = '')
|
63
|
+
old_buffer = @context.instance_variable_get("@_out_buf")
|
64
|
+
@context.instance_variable_set "@_out_buf", buf
|
65
|
+
yield
|
66
|
+
@context.instance_variable_get("@_out_buf")
|
67
|
+
ensure
|
68
|
+
@context.instance_variable_set "@_out_buf", old_buffer
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'form'
|
2
|
+
require 'rack/csrf'
|
3
|
+
|
4
|
+
module Sequent
|
5
|
+
module Web
|
6
|
+
module Sinatra
|
7
|
+
module FormHelpers
|
8
|
+
def html_form(action, method=:get, options={}, &block)
|
9
|
+
html_form_for nil, action, method, options, &block
|
10
|
+
end
|
11
|
+
|
12
|
+
def html_form_for(for_object, action, method=:get, options={}, &block)
|
13
|
+
raise "Given object of class #{for_object.class} does not respond to :as_params. Are you including Sequent::Core::Helpers::ParamSupport?" if (for_object and !for_object.respond_to? :as_params)
|
14
|
+
form = Form.new(self, for_object, action, method, options.merge(role: "form"))
|
15
|
+
form.render(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def h(text)
|
19
|
+
Rack::Utils.escape_html(text)
|
20
|
+
end
|
21
|
+
|
22
|
+
def csrf_tag
|
23
|
+
raise "You must enable sessions to use FormHelpers" unless env
|
24
|
+
Rack::Csrf.csrf_tag(env)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Sequent
|
2
|
+
module Web
|
3
|
+
module Sinatra
|
4
|
+
module SimpleCommandServiceHelpers
|
5
|
+
#
|
6
|
+
# execute a single command. Since it is default for most cases a CommandNotValid exception is handled in this method.
|
7
|
+
#
|
8
|
+
# Example usage:
|
9
|
+
#
|
10
|
+
# post '/foo' do
|
11
|
+
# @command = FooCommand.from_params(params)
|
12
|
+
# execute_command(@command, :erb_name)
|
13
|
+
# end
|
14
|
+
def execute_command(command)
|
15
|
+
@command_service.execute_commands(command)
|
16
|
+
yield if block_given?
|
17
|
+
rescue Sequent::Core::CommandNotValid => e
|
18
|
+
yield e.errors_with_command_prefix if block_given?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module Sequent
|
2
|
+
module Web
|
3
|
+
module Sinatra
|
4
|
+
module TagHelper
|
5
|
+
def raw_checkbox(field, options={})
|
6
|
+
id = css_id(@path, field)
|
7
|
+
value = param_or_default(field, options[:value]) || id
|
8
|
+
values = [value].compact
|
9
|
+
single_tag :input, options.merge(
|
10
|
+
:type => "checkbox", :id => id,
|
11
|
+
:name => calculate_name(field),
|
12
|
+
:value => value, checked: (values.include?(@values[field.to_s])) ? "checked" : nil
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def raw_input(field, options={})
|
17
|
+
raw_field(field, "text", options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def raw_password(field, options={})
|
21
|
+
raw_field(field, "password", options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def raw_textarea(field, options={})
|
25
|
+
value = param_or_default(field, options[:value])
|
26
|
+
|
27
|
+
with_closing_tag :textarea, value, {rows: "3"}.merge(options.merge(
|
28
|
+
:id => css_id(@path, field),
|
29
|
+
:name => calculate_name(field)
|
30
|
+
))
|
31
|
+
end
|
32
|
+
|
33
|
+
def raw_hidden(field, options={})
|
34
|
+
raw_field(field, "hidden", options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def raw_select(field, values, options={})
|
38
|
+
value = param_or_default(field, options[:value])
|
39
|
+
content = ""
|
40
|
+
Array(values).each do |val|
|
41
|
+
id, text = id_and_text_from_value(val)
|
42
|
+
option_values = {value: id}
|
43
|
+
option_values.merge!(selected: "selected") if (id == value)
|
44
|
+
option_values.merge!(disabled: "disabled") if options[:disable].try(:include?, id)
|
45
|
+
content << tag(:option, text, option_values)
|
46
|
+
end
|
47
|
+
tag :select, content, options.merge(:id => css_id(@path, field), :name => calculate_name(field))
|
48
|
+
end
|
49
|
+
|
50
|
+
def calculate_name(field)
|
51
|
+
reverse_names = tree_in_names(field)
|
52
|
+
"#{reverse_names.first}#{reverse_names[1..-1].map { |n| "[#{n}]" }.join}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def full_path(field)
|
56
|
+
tree_in_names(field).join('_')
|
57
|
+
end
|
58
|
+
|
59
|
+
alias_method :calculate_id, :full_path
|
60
|
+
|
61
|
+
def tree_in_names(field)
|
62
|
+
if respond_to? :path
|
63
|
+
names = [field, path]
|
64
|
+
parent = @parent
|
65
|
+
while parent.is_a? Fieldset
|
66
|
+
names << parent.path
|
67
|
+
parent = parent.parent
|
68
|
+
end
|
69
|
+
names.reverse
|
70
|
+
else
|
71
|
+
[field]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def param_or_default(field, default)
|
76
|
+
@values.nil? ? default : @values.has_key?(field.to_s) ? @values[field.to_s] || default : default
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def id_and_text_from_value(val)
|
81
|
+
if val.is_a? Array
|
82
|
+
[val[0], val[1]]
|
83
|
+
else
|
84
|
+
[val, val]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def css_id(*things)
|
89
|
+
things.compact.map { |t| t.to_s }.join('_').downcase.gsub(/\W/, '_')
|
90
|
+
end
|
91
|
+
|
92
|
+
def tag(name, content, options={})
|
93
|
+
"<#{name.to_s}" +
|
94
|
+
(options.length > 0 ? " #{hash_to_html_attrs(options)}" : '') +
|
95
|
+
(content.nil? ? '>' : ">#{content}</#{name}>")
|
96
|
+
end
|
97
|
+
|
98
|
+
def single_tag(name, options={})
|
99
|
+
"<#{name.to_s} #{hash_to_html_attrs(options)} />"
|
100
|
+
end
|
101
|
+
|
102
|
+
def with_closing_tag(name, value, options={})
|
103
|
+
%Q{<#{name.to_s} #{hash_to_html_attrs(options)} >#{h value}</#{name.to_s}>}
|
104
|
+
end
|
105
|
+
|
106
|
+
def hash_to_html_attrs(options={})
|
107
|
+
raise %Q{Keys used in options must be a Symbol. Don't use {"class" => "col-md-4"} but use {class: "col-md-4"}} if options.keys.find { |k| not k.kind_of? Symbol }
|
108
|
+
html_attrs = ""
|
109
|
+
options.keys.sort.each do |key|
|
110
|
+
next if options[key].nil? # do not include empty attributes
|
111
|
+
html_attrs << %Q(#{key}="#{h(options[key])}" )
|
112
|
+
end
|
113
|
+
html_attrs.chop
|
114
|
+
end
|
115
|
+
|
116
|
+
def merge_and_append_class_attributes(to_append, options = {})
|
117
|
+
to_append.merge(options) do |key, oldval, newval|
|
118
|
+
key == :class ? "#{oldval} #{newval}" : newval
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def i18n_name(field)
|
123
|
+
if @path
|
124
|
+
"#{@path}.#{field}"
|
125
|
+
else
|
126
|
+
field.to_s
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def has_form_error?(name)
|
131
|
+
@errors.try(:has_key?, name.to_sym)
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
def raw_field(field, field_type, options)
|
136
|
+
value = param_or_default(field, options[:value])
|
137
|
+
if options[:formatter]
|
138
|
+
value = self.send(options[:formatter], value)
|
139
|
+
options.delete(:formatter)
|
140
|
+
end
|
141
|
+
id = options[:id] || css_id(@path, field)
|
142
|
+
single_tag :input, options.merge(
|
143
|
+
:type => field_type,
|
144
|
+
:id => id,
|
145
|
+
:name => calculate_name(field),
|
146
|
+
:value => value
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
data/lib/version.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequent-sinatra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lars Vonk
|
@@ -135,6 +135,14 @@ extensions: []
|
|
135
135
|
extra_rdoc_files: []
|
136
136
|
files:
|
137
137
|
- lib/sequent-sinatra.rb
|
138
|
+
- lib/sequent-sinatra/app.rb
|
139
|
+
- lib/sequent-sinatra/fieldset.rb
|
140
|
+
- lib/sequent-sinatra/form.rb
|
141
|
+
- lib/sequent-sinatra/form_helpers.rb
|
142
|
+
- lib/sequent-sinatra/sequent-sinatra.rb
|
143
|
+
- lib/sequent-sinatra/simple_command_service_helpers.rb
|
144
|
+
- lib/sequent-sinatra/tag_helper.rb
|
145
|
+
- lib/version.rb
|
138
146
|
homepage: https://github.com/zilverline/sequent-sinatra
|
139
147
|
licenses:
|
140
148
|
- MIT
|