cat_forms 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5867215cad9448070b77390a76a9fe9e1fb390f9
4
- data.tar.gz: 6ebbcb9cfa9ed393b0ea4fb78f2cbe8554a2eadb
3
+ metadata.gz: e41399d5ac4893087435e2e6aa5955d4d3ee284a
4
+ data.tar.gz: b0a5e377693ef76d875bc2b87ce9495fb9e480de
5
5
  SHA512:
6
- metadata.gz: e3707d05035069c357604735aab2cb175df552e7570f550f37f5649865a78b0941443be2cbfb4e3e05ab03eef9053b13c3d1146226d9d00d1dae3f80dedba6d1
7
- data.tar.gz: 7c1efd9159019bde3397587177938c83d53967eb4c20c58a057c152482ea7816e6d8ea5c28687b4374cae9d2904895038c8fcadc73ab6032d4db55c5b198232d
6
+ metadata.gz: 3e721107373b10dfd0557b58b905fd3a6f58420e70ce11c3eace372f325643463b41796092bdc4fa8a86c1c96903dabed26431d0a4c5a5929d109ca0ca512cf7
7
+ data.tar.gz: cd56fde1729f815dbc07bd1e7057f71a81852076f15d188a5e777dbad12a67b2fb1c82e2b43e6c97f91f8bc738975c789b98a821aef49950b3fc9b9616210f8f
@@ -0,0 +1,35 @@
1
+ # encoding: UTF-8
2
+ require 'zlib'
3
+ require 'active_support/hash_with_indifferent_access'
4
+
5
+ # Saves form as cookie as json+gzip
6
+ module CatForms::GzipCookie
7
+ def self.load options={}
8
+ request = options[:request]
9
+ cookie_name = options[:cookie_name].to_s
10
+ result = ActiveSupport::HashWithIndifferentAccess.new
11
+ return result if request.blank?
12
+ cookie = request.cookies[cookie_name]
13
+ return result if cookie.nil? or cookie.empty?
14
+ begin
15
+ result.merge!(ActiveSupport::JSON.decode(Zlib::Inflate.inflate(cookie)).stringify_keys)
16
+ return result
17
+ rescue Zlib::DataError
18
+ return result
19
+ end
20
+ end
21
+
22
+ def self.save options = {}
23
+ attributes = options[:attributes]
24
+ response = options[:response]
25
+ cookie_name = options[:cookie_name]
26
+
27
+ cookie_json = ActiveSupport::JSON.encode(attributes)
28
+ cookie_json = Zlib::Deflate.deflate(cookie_json, Zlib::BEST_COMPRESSION)
29
+ cookie_hash = { value: cookie_json,
30
+ httponly: true,
31
+ }
32
+ response.set_cookie(cookie_name, cookie_hash)
33
+ end
34
+ end
35
+
@@ -0,0 +1,66 @@
1
+ require 'delegate'
2
+
3
+ module ValidationScopes
4
+ def self.included(base) # :nodoc:
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def validation_scope(scope)
10
+ @all_scopes ||= []
11
+ @all_scopes << scope
12
+
13
+ def self.all_scopes
14
+ @all_scopes
15
+ end
16
+
17
+ base_class = self
18
+
19
+ proxy_class = Class.new(DelegateClass(base_class)) do
20
+ include ActiveModel::Validations
21
+
22
+ def initialize(record)
23
+ @base_record = record
24
+ super(record)
25
+ end
26
+
27
+ # Hacks to support dynamic_model helpers
28
+ def to_model
29
+ self
30
+ end
31
+
32
+ # Rails 3 default implementation of model_name blows up for anonymous classes
33
+ class << self; self; end.class_eval do
34
+ define_method(:model_name) do
35
+ base_class.model_name
36
+ end
37
+ end
38
+ end
39
+
40
+ yield proxy_class
41
+
42
+ define_method(scope) do
43
+ send("validation_scope_proxy_for_#{scope}").errors
44
+ end
45
+
46
+ define_method("no_#{scope}?") do
47
+ send("validation_scope_proxy_for_#{scope}").valid?
48
+ end
49
+
50
+ define_method("has_#{scope}?") do
51
+ send("validation_scope_proxy_for_#{scope}").invalid?
52
+ end
53
+
54
+ define_method("init_validation_scope_for_#{scope}") do
55
+ unless instance_variable_defined?("@#{scope}")
56
+ instance_variable_set("@#{scope}", proxy_class.new(self))
57
+ end
58
+ end
59
+
60
+ define_method("validation_scope_proxy_for_#{scope}") do
61
+ send "init_validation_scope_for_#{scope}"
62
+ instance_variable_get("@#{scope}")
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,3 @@
1
+ module CatForms
2
+ VERSION = "0.0.3"
3
+ end
data/lib/cat_forms.rb ADDED
@@ -0,0 +1,254 @@
1
+ # Warning: This code is atrocious.
2
+ #
3
+ # ActiveModel is sorta confusing in Rails 3.2. I think
4
+ # it's improved in 4.0?
5
+ #
6
+ # TODO we should be checking the type of things when saving
7
+
8
+ module CatForms
9
+ require 'active_model'
10
+ require 'virtus'
11
+ require 'active_support/core_ext/class/attribute'
12
+ require 'cat_forms/validation_scopes'
13
+ autoload :GzipCookie, 'cat_forms/gzip_cookie'
14
+
15
+ # TODO not sure thy this is necessary. tests run, but
16
+ # when this is included by rails, i get already defined
17
+ # errors and super class mismatch errors.
18
+ if !defined?(CatForms::Boolean)
19
+ class Boolean < Virtus::Attribute::Boolean
20
+ end
21
+ end
22
+
23
+ module Form
24
+
25
+ def self.included base
26
+ base.send :include, ActiveModel::Validations
27
+ base.send :extend, ActiveModel::Callbacks
28
+ base.send :include, Virtus.model
29
+ base.send :extend, ClassMethods
30
+ base.send :include, InstanceMethods
31
+ base.send :include, ValidationScopes
32
+ base.instance_eval do
33
+ define_model_callbacks :initialize, :save
34
+ class_attribute :_form_name
35
+ end
36
+ end
37
+
38
+ module ClassMethods
39
+ # Overrides how Virtus handles attributes of the wrong type.
40
+ # Ideally virtus would coerce everything to the right type,
41
+ # use the default, or return nil.
42
+ # There's a related discussion here: https://github.com/solnic/virtus/issues/99
43
+ def attribute(name, type, opts = {})
44
+ super(name, type, opts)
45
+ define_method(name) do
46
+ data = super()
47
+ default_value = -> { opts[:default].respond_to?(:call) ? opts[:default].call : opts[:default] }
48
+
49
+ # If they want a BigDecimal or Int, but data is a string, strip
50
+ # the stuff of bad data and try to convert manually.
51
+ if type == BigDecimal or type == Integer
52
+ if data.class == String
53
+ data.gsub!(/[^\d\.]/, '')
54
+ if data.present?
55
+ if type == BigDecimal
56
+ data = BigDecimal.new(data)
57
+ else
58
+ data = Integer(data)
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ #if type.class != Array and !data.is_a?(type) and !data.nil? and (type != CatForms::Boolean and !data.is_a?(Boolean))
65
+ #puts "cat forms expected a #{type} for #{ name }, received #{ data.inspect }"
66
+ #puts caller
67
+ #end
68
+
69
+ if type == CatForms::Boolean and (data == true or data == false)
70
+ return data
71
+ end
72
+
73
+ if type.class == Array
74
+ # Not validating more right now.
75
+ return data
76
+ end
77
+
78
+ if data.is_a?(type)
79
+ # Override for default string
80
+ if type == String and opts.has_key?(:default) and data == ""
81
+ return default_value.call
82
+ else
83
+ return data
84
+ end
85
+ end
86
+
87
+ return default_value.call
88
+ end
89
+ end
90
+
91
+ def form_name name
92
+ name = name.to_s
93
+
94
+ def name.i18n_key
95
+ self
96
+ end
97
+
98
+ def name.human
99
+ self
100
+ end
101
+
102
+ def name.singular
103
+ self
104
+ end
105
+
106
+ def name.plural
107
+ self
108
+ end
109
+
110
+ def name.param_key
111
+ self
112
+ end
113
+
114
+ self.class.instance_eval do
115
+ define_method :model_name do
116
+ name
117
+ end
118
+ end
119
+
120
+ self._form_name = name
121
+ end
122
+
123
+ def model_name
124
+ self._form_name || super
125
+ end
126
+
127
+ def form_attribute name, klass, options={}
128
+ # Setup the default values for each attribute.
129
+ if !options.has_key?(:default)
130
+ options[:default] =
131
+ if klass.kind_of?(Array)
132
+ []
133
+ elsif klass == BigDecimal or klass == Boolean or klass == CatForms::Boolean
134
+ nil
135
+ elsif klass.respond_to?(:new)
136
+ proc { klass.new }
137
+ else
138
+ nil
139
+ end
140
+ end
141
+ attribute name, klass, options
142
+ if options[:validations]
143
+ validates(name, options[:validations])
144
+ end
145
+
146
+ # Define an association_attributes= method
147
+ # Rails's fields_for looks for this.
148
+ if klass.kind_of?(Array)
149
+ define_method "#{name}_attributes=" do |hash|
150
+ hash.each do |_index, opts|
151
+ # If the array is nil, set it to an empty array.
152
+ self.send("#{name}=", []) if self.send(name).nil?
153
+ self.send(name) << klass.first.new(opts)
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ def custom_attribute attribute_name
160
+ class_eval do
161
+ attr_reader attribute_name
162
+ end
163
+ end
164
+
165
+ def validates_associated(*associations)
166
+ validates_each(associations) do |record, _associate_name, value|
167
+ (value.respond_to?(:each) ? value : [value]).each do |rec|
168
+ if rec && !rec.valid?
169
+ rec.errors.each do |key, val|
170
+ record.errors.add(key, val)
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ module InstanceMethods
179
+ # Need to look into all the below methods, not sure if they are
180
+ # correct.
181
+ def persisted?
182
+ false
183
+ end
184
+
185
+ def to_model
186
+ self
187
+ end
188
+
189
+ def to_partial_path
190
+ "some_path" # TODO figure out what's needed here for Rails 3.2
191
+ end
192
+
193
+ def to_param
194
+ nil
195
+ end
196
+
197
+ def to_key
198
+ nil
199
+ end
200
+
201
+ def save
202
+ run_callbacks :save do
203
+ if !valid?
204
+ return false
205
+ end
206
+ end
207
+ self
208
+ end
209
+
210
+ def initialize options = {}
211
+ run_callbacks(:initialize) do
212
+ # can sometimes be a string
213
+ if options.class != Hash
214
+ options = {}
215
+ end
216
+ options[:form] ||= {}
217
+
218
+ # TODO fix
219
+ # This allows setting of custom things
220
+ options.each do |key, value|
221
+ instance_variable_set "@#{key}", value
222
+ end
223
+
224
+ CatForms::GzipCookie.load(storage_options).each do |key, value|
225
+ method = "#{key}="
226
+ if respond_to?(method)
227
+ self.send method, value
228
+ end
229
+ end
230
+
231
+ options[:form].each do |name, value|
232
+ value.strip! if value.respond_to?(:strip)
233
+ self.send "#{name}=", value
234
+ end
235
+
236
+ end
237
+ super
238
+ end
239
+
240
+ def save_to_storage!
241
+ options = storage_options.merge(attributes: attributes)
242
+ CatForms::GzipCookie.save(options)
243
+ end
244
+
245
+ def storage_options
246
+ {
247
+ cookie_name: @cookie_name,
248
+ request: @request,
249
+ response: @response
250
+ }
251
+ end
252
+ end
253
+ end
254
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cat_forms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Van Dyk
@@ -44,7 +44,11 @@ email:
44
44
  executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
- files: []
47
+ files:
48
+ - lib/cat_forms.rb
49
+ - lib/cat_forms/gzip_cookie.rb
50
+ - lib/cat_forms/validation_scopes.rb
51
+ - lib/cat_forms/version.rb
48
52
  homepage: https://github.com/joevandyk/cat_forms
49
53
  licenses: []
50
54
  metadata: {}