styx 0.0.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/README.md +158 -0
- data/app/assets/javascripts/styx.forms.js.coffee +27 -0
- data/app/assets/javascripts/styx.js.coffee +22 -0
- data/app/views/styx/_initializer.html.haml +9 -0
- data/init.rb +1 -0
- data/lib/styx.rb +8 -0
- data/lib/styx/engine.rb +4 -0
- data/lib/styx/forms.rb +33 -0
- data/lib/styx/helpers.rb +32 -0
- data/lib/styx/initializer.rb +27 -0
- data/styx.gemspec +14 -0
- metadata +57 -0
data/README.md
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
Styx
|
2
|
+
========
|
3
|
+
|
4
|
+
Bridge between Server (Rails) side and Client (JS) side divided into several modules:
|
5
|
+
|
6
|
+
* **Helpers**: set of helpers to support all other modules.
|
7
|
+
* **Initializer**: organizes JS into bootstrap classes and allows you to pass data from controller/view.
|
8
|
+
* **Forms**: remote validaton engine.
|
9
|
+
|
10
|
+
|
11
|
+
Installation
|
12
|
+
------------
|
13
|
+
|
14
|
+
$ gem install styx
|
15
|
+
|
16
|
+
|
17
|
+
Basic Usage
|
18
|
+
------------
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
# app/controllers/foos_controller.rb
|
22
|
+
class FoosController < ApplicationController
|
23
|
+
include Styx::Initializer
|
24
|
+
include Styx::Forms
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
Include modules to ApplicationController if you want to use it everywhere.
|
29
|
+
|
30
|
+
|
31
|
+
Initializer
|
32
|
+
------------
|
33
|
+
|
34
|
+
In common each controller in Rails comes with *app/assets/javascripts/controller_name.js.coffee*.
|
35
|
+
Styx.Initializer allows you to separately define bootstrap logic for each Rails action and pass
|
36
|
+
some data from server right in.
|
37
|
+
|
38
|
+
To enable initializers bootstrap, add *styx_initialize* line to your layout:
|
39
|
+
|
40
|
+
```erb
|
41
|
+
<head>
|
42
|
+
<title>Rails Application</title>
|
43
|
+
<%= stylesheet_link_tag "application" %>
|
44
|
+
<%= javascript_include_tag "application" %>
|
45
|
+
<%= styx_initialize %>
|
46
|
+
<%= csrf_meta_tags %>
|
47
|
+
```
|
48
|
+
|
49
|
+
Imagine you have controller *Foos* and therefore *app/assets/javascripts/foos.js.coffee* file.
|
50
|
+
|
51
|
+
```coffee-script
|
52
|
+
@Styx.Initializers.Foos =
|
53
|
+
initialize: ->
|
54
|
+
console.log 'This will be called in foos#ANY action after <head> was parsed'
|
55
|
+
|
56
|
+
index: (data) ->
|
57
|
+
console.log 'This will be called in foos#index action after <head> was parsed'
|
58
|
+
|
59
|
+
show: (data) ->
|
60
|
+
$ ->
|
61
|
+
console.log 'This will be called in foos#show action after the page was loaded'
|
62
|
+
```
|
63
|
+
|
64
|
+
Note that any method besides common *initialize* has the *data* parameter. To pass some data to your
|
65
|
+
initializers you can use *styx_initialize_with* helper in your controller or views. Like that:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# app/controllers/foos_controller.rb
|
69
|
+
class FoosController < ApplicationController
|
70
|
+
def index
|
71
|
+
styx_initialize_with :some => 'data', :and => {:even => 'more data'}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# app/views/foos/index.html.erb
|
76
|
+
<%- styx_initialize_with :enabled => true %>
|
77
|
+
```
|
78
|
+
|
79
|
+
As the result *Styx.Initializers.Foos->index* will be called with data equal to
|
80
|
+
|
81
|
+
{some: data, and: {even: 'mode data'}, enabled: true}
|
82
|
+
|
83
|
+
|
84
|
+
Forms
|
85
|
+
------------
|
86
|
+
|
87
|
+
Forms assist *form_for @foo, :remote => true* to automate server response and UJS callbacks.
|
88
|
+
|
89
|
+
If everything went smooth you can respond with URL for redirect or with JSON for your callback.
|
90
|
+
If validation failed appropriate form fields will be wraped with native
|
91
|
+
|
92
|
+
<div class="field_with_errors">
|
93
|
+
|
94
|
+
### Client side
|
95
|
+
|
96
|
+
```erb
|
97
|
+
# app/views/foos/new.html.erb
|
98
|
+
<%= form_for @foo, :remote => true, :html => {:id => 'foo_form'} do |f| %>
|
99
|
+
<%= f.text_field :f.title %>
|
100
|
+
<% end %>
|
101
|
+
```
|
102
|
+
|
103
|
+
```javascript
|
104
|
+
// Light case
|
105
|
+
Forms.attach('#foo_form')
|
106
|
+
|
107
|
+
|
108
|
+
// Heavy case
|
109
|
+
success_callback = function(data) {} // Form validated and stored. Data is what you pass from server.
|
110
|
+
error_callback = function() {} // Form wasn't validated
|
111
|
+
|
112
|
+
Forms.attach('#foo_form', success_callback, error_callback)
|
113
|
+
```
|
114
|
+
|
115
|
+
Note that if success_callback was not given but server responded with some data, Styx.Forms will try
|
116
|
+
to evaluate it as URL and will try to redirect to it.
|
117
|
+
|
118
|
+
Javascript part goes best with Styx.Initializers.
|
119
|
+
|
120
|
+
### Server side
|
121
|
+
|
122
|
+
In common you just want to store your form as model. Styx.Forms come with predefined helper for this:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
# app/controllers/foos_controller.rb
|
126
|
+
def create
|
127
|
+
@entity = Foo.new(params[:foo])
|
128
|
+
response = foos_url # Return URL or anything for your custom callback
|
129
|
+
|
130
|
+
styx_form_store_and_respond(@foo, response) do
|
131
|
+
# this will be called after (and if) @foo was validated and saved
|
132
|
+
end
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
*response* parameter can either be passed as lambda{|x|}.
|
137
|
+
|
138
|
+
### What if form was invalid?
|
139
|
+
|
140
|
+
First of all, *success_callback* and server-side block won't be called. *response* won't be return to JS.
|
141
|
+
Validation errors for @entity will be returned instead. All invalid form fields will be wraped with
|
142
|
+
|
143
|
+
<div class="field_with_errors">
|
144
|
+
|
145
|
+
### Server side without models
|
146
|
+
|
147
|
+
To work without models (i.e. to serve login form) you can use two helpers
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
styx_form_respond_success(data)
|
151
|
+
```
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
styx_form_respond_failure(entity_name, fields) # fields = {'field_name' => 'error message'}
|
155
|
+
```
|
156
|
+
|
157
|
+
To choose which fields have to be marked as invalid JS part will concatenate entity_name + field _name. So if
|
158
|
+
you don't have entity, simply pass empty string as the first arg.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
@Styx.Forms =
|
2
|
+
validate: (element, success_action=false, error_action=false, substitutions={}) ->
|
3
|
+
$(element).live 'ajax:success', (event, result, status, xhr) ->
|
4
|
+
$(element).find('.field_with_errors').children().unwrap()
|
5
|
+
|
6
|
+
unless success_action
|
7
|
+
Styx.URL.go xhr.responseText, true
|
8
|
+
else
|
9
|
+
success_action.call(this, xhr.responseText)
|
10
|
+
|
11
|
+
$(element).live 'ajax:error', (evt, xhr, status, error) ->
|
12
|
+
$(element).find('.field_with_errors').children().unwrap()
|
13
|
+
error_action.call(this) if error_action
|
14
|
+
|
15
|
+
errors = jQuery.parseJSON xhr.responseText
|
16
|
+
|
17
|
+
console.log errors if console?
|
18
|
+
|
19
|
+
for field, notifications of errors.messages
|
20
|
+
field = substitutions[field] if substitutions[field]?
|
21
|
+
input = $(element).find("##{errors.entity}_#{field}")
|
22
|
+
|
23
|
+
# Support for Chosen jQuery plugin
|
24
|
+
if input.is('.chzn-done')
|
25
|
+
input = $(element).find("##{errors.entity}_#{field}_chzn")
|
26
|
+
|
27
|
+
input.wrap("<div class='field_with_errors' />")
|
@@ -0,0 +1,22 @@
|
|
1
|
+
@Styx = {
|
2
|
+
Initializers: {}
|
3
|
+
}
|
4
|
+
|
5
|
+
@Styx.URL =
|
6
|
+
go: (url, force=false) ->
|
7
|
+
# 'Force' required if you want to reload same page with another anchor
|
8
|
+
url = this.build(url, "reloadthispagepls=#{Math.random()}") if force
|
9
|
+
window.location.href = url
|
10
|
+
|
11
|
+
build: (url, params) ->
|
12
|
+
hash = url.match(/\#.*$/)
|
13
|
+
hash = if hash then hash[0] else false
|
14
|
+
|
15
|
+
url = url.replace(hash, '') if hash
|
16
|
+
url = url + "?" if url.indexOf("?") == -1
|
17
|
+
|
18
|
+
url = "#{url}&#{params}"
|
19
|
+
|
20
|
+
url = url + hash if hash
|
21
|
+
|
22
|
+
return url
|
@@ -0,0 +1,9 @@
|
|
1
|
+
:javascript
|
2
|
+
if (Styx.Initializers.#{klass} && Styx.Initializers.#{klass}.initialize)
|
3
|
+
{
|
4
|
+
Styx.Initializers.#{klass}.initialize(#{data.to_json})
|
5
|
+
}
|
6
|
+
if (Styx.Initializers.#{klass} && Styx.Initializers.#{klass}.#{method})
|
7
|
+
{
|
8
|
+
Styx.Initializers.#{klass}.#{method}(#{data.to_json})
|
9
|
+
}
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'styx'
|
data/lib/styx.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'styx/engine'
|
2
|
+
require 'styx/helpers'
|
3
|
+
require 'styx/forms'
|
4
|
+
require 'styx/initializer'
|
5
|
+
|
6
|
+
ActionController::Base.send :include, Styx::Helpers
|
7
|
+
# ActionController::Base.send :include, Styx::Forms
|
8
|
+
# ActionController::Base.send :include, Styx::Initializer
|
data/lib/styx/engine.rb
ADDED
data/lib/styx/forms.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Styx
|
2
|
+
module Forms
|
3
|
+
def self.included base
|
4
|
+
base.send(:include, InstanceMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
def styx_form_store_and_respond(entity, data=nil, &block)
|
9
|
+
response.content_type = Mime::TEXT
|
10
|
+
|
11
|
+
if entity.save
|
12
|
+
styx_form_respond_success(data, entity, &block)
|
13
|
+
else
|
14
|
+
styx_form_respond_failure(entity.class.name, entity.errors.messages)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def styx_form_respond_failure(entity, errors)
|
19
|
+
response.content_type = Mime::TEXT
|
20
|
+
|
21
|
+
errors = Hash[*errors.map {|x| [x, nil]}.flatten] if errors.is_a?(Array)
|
22
|
+
render :text => {:entity => entity.to_s.underscore.gsub('/', '_'), :messages => errors}.to_json, :status => :unprocessable_entity
|
23
|
+
end
|
24
|
+
|
25
|
+
def styx_form_respond_success(data, entity=nil, &block)
|
26
|
+
response.content_type = Mime::TEXT
|
27
|
+
|
28
|
+
block.call(entity) if block_given?
|
29
|
+
render :text => (data.is_a?(Proc) ? data.call(entity) : data)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/styx/helpers.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Styx
|
2
|
+
module Helpers
|
3
|
+
def self.included base
|
4
|
+
base.send(:include, InstanceMethods)
|
5
|
+
base.class_eval do
|
6
|
+
helper_method :this_page?, :this_namespace?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
def this_page?(mask)
|
12
|
+
mask = mask.split('#')
|
13
|
+
|
14
|
+
c = mask[0]
|
15
|
+
a = mask[1]
|
16
|
+
|
17
|
+
flag = true
|
18
|
+
|
19
|
+
flag = false if !c.blank? && c != controller_path
|
20
|
+
flag = false if !a.blank? && a != action_name
|
21
|
+
|
22
|
+
flag
|
23
|
+
end
|
24
|
+
|
25
|
+
def this_namespace?(namespace)
|
26
|
+
current = controller_path.split('/').first
|
27
|
+
|
28
|
+
return namespace == current
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Styx
|
2
|
+
module Initializer
|
3
|
+
def self.included base
|
4
|
+
base.send(:include, InstanceMethods)
|
5
|
+
base.class_eval do
|
6
|
+
helper_method :styx_initialize, :styx_initialize_with
|
7
|
+
before_filter { @styx_initialize_with = {} }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
def styx_initialize_with(data)
|
13
|
+
@styx_initialize_with.merge! data
|
14
|
+
end
|
15
|
+
|
16
|
+
def styx_initialize()
|
17
|
+
result = render_to_string :partial => 'styx/initializer', :locals => {
|
18
|
+
:klass => controller_path.gsub('/', '_').camelize,
|
19
|
+
:method => action_name,
|
20
|
+
:data => @styx_initialize_with
|
21
|
+
}
|
22
|
+
|
23
|
+
result.html_safe
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/styx.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
SPEC = Gem::Specification.new do |s|
|
2
|
+
s.name = "styx"
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.summary = "Set of helpers to maintain bridge between Server (Rails) side and Client (JS) side"
|
6
|
+
s.email = "boris@roundlake.ru"
|
7
|
+
s.homepage = "http://github.com/roundlake/styx"
|
8
|
+
s.description = s.summary
|
9
|
+
s.authors = ['Boris Staal']
|
10
|
+
|
11
|
+
s.has_rdoc = false # disable rdoc generation until we've got more
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.require_paths = ["lib"]
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: styx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Boris Staal
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-22 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Set of helpers to maintain bridge between Server (Rails) side and Client
|
15
|
+
(JS) side
|
16
|
+
email: boris@roundlake.ru
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- README.md
|
22
|
+
- app/assets/javascripts/styx.forms.js.coffee
|
23
|
+
- app/assets/javascripts/styx.js.coffee
|
24
|
+
- app/views/styx/_initializer.html.haml
|
25
|
+
- init.rb
|
26
|
+
- lib/styx.rb
|
27
|
+
- lib/styx/engine.rb
|
28
|
+
- lib/styx/forms.rb
|
29
|
+
- lib/styx/helpers.rb
|
30
|
+
- lib/styx/initializer.rb
|
31
|
+
- styx.gemspec
|
32
|
+
homepage: http://github.com/roundlake/styx
|
33
|
+
licenses: []
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.8.10
|
53
|
+
signing_key:
|
54
|
+
specification_version: 3
|
55
|
+
summary: Set of helpers to maintain bridge between Server (Rails) side and Client
|
56
|
+
(JS) side
|
57
|
+
test_files: []
|