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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3a73084ee9f260f29469a257639ec887e5c7a537
4
- data.tar.gz: 85aa9e6af284495f7d33f8153460b8c43d8c1b3f
3
+ metadata.gz: c6370a605d3032c7a3703e6b3d0ab82d4ac39f7c
4
+ data.tar.gz: 9d78a48b9878443e3b88b1c2f3b4f9b54acad5dc
5
5
  SHA512:
6
- metadata.gz: bb42453351dffb2645e22763510c9833b535a0348b7d41d3894aa7d941ead955dfd5cdd3154c5d4412a28be88cf24c3e3c3e3baceaf495a23c312ed13d13c2ca
7
- data.tar.gz: fe7c9d65de1bae9b9ae48ee604acdf83774b0e5e4b74faf7f4985e7e59ab931155dbe5875526dbd67351ec5a82dd3d055f2d6d5c89c68b1ec2f5ecfb5dde47d8
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,6 @@
1
+ require_relative 'form_helpers'
2
+ require_relative 'tag_helper'
3
+ require_relative 'fieldset'
4
+ require_relative 'form'
5
+ require_relative 'simple_command_service_helpers'
6
+ require_relative 'app'
@@ -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
@@ -0,0 +1,3 @@
1
+ module SequentSinatra
2
+ VERSION='0.1.1'
3
+ end
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.0
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