sequent-sinatra 0.1.0 → 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 +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
|