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.
@@ -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: []