styx 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'
@@ -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
@@ -0,0 +1,4 @@
1
+ module Styx #:nodoc:
2
+ class Engine < ::Rails::Engine #:nodoc:
3
+ end
4
+ end
@@ -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
@@ -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
@@ -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: []