cowtech-rails 1.0.0.0
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 +6 -0
- data/app/helpers/cowtech/application_helper.rb +90 -0
- data/app/helpers/cowtech/crud_helper.rb +298 -0
- data/app/helpers/cowtech/format_helper.rb +66 -0
- data/app/helpers/cowtech/validation_helper.rb +26 -0
- data/app/models/e_mail.rb +58 -0
- data/app/models/model_base.rb +43 -0
- data/config/initializers/extensions.rb +41 -0
- data/lib/cowtech.rb +15 -0
- data/lib/engine.rb +10 -0
- data/lib/extensions.rb +283 -0
- data/lib/monkey_patches.rb +71 -0
- data/lib/version.rb +18 -0
- data/rails/init.rb +6 -0
- metadata +78 -0
data/README
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Cowtech
|
8
|
+
module ApplicationHelper
|
9
|
+
def application_info
|
10
|
+
@application_info = YAML.load_file(Rails.root + "config/application_info.yml") unless @application_info
|
11
|
+
@application_info
|
12
|
+
end
|
13
|
+
|
14
|
+
def location_name(action = nil, controller = nil)
|
15
|
+
controller = self.controller_name unless controller
|
16
|
+
action = self.action_name unless action
|
17
|
+
"#{controller}##{action}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def additional_tag(what = :js)
|
21
|
+
if what == :js then
|
22
|
+
javascript_include_tag "specific/#{self.controller_name}.js"
|
23
|
+
elsif what == :css then
|
24
|
+
stylesheet_link_tag "#{self.controller_name}.css"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_data(key = nil, default = "")
|
29
|
+
rv = default
|
30
|
+
|
31
|
+
unless @outputdata.nil? then
|
32
|
+
rv = @outputdata[key] unless @outputdata[key].nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
rv
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_param(key, default = nil)
|
39
|
+
if params[key].blank? then default else params[key] end
|
40
|
+
end
|
41
|
+
|
42
|
+
def _normalize_type(format = nil)
|
43
|
+
if format != nil then
|
44
|
+
request.format = format
|
45
|
+
else
|
46
|
+
request.format = :text if request.format != :json
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def setup_json_response(type = :base)
|
51
|
+
ApplicationController.setup_json_response(type)
|
52
|
+
end
|
53
|
+
|
54
|
+
def custom_respond_with(data, format = nil)
|
55
|
+
return if performed?
|
56
|
+
|
57
|
+
self._normalize_type(format)
|
58
|
+
|
59
|
+
if request.format == :text then
|
60
|
+
render :text => data
|
61
|
+
elsif request.format == :json then
|
62
|
+
render :json => data
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def debug(what, type = :json)
|
67
|
+
msg = ""
|
68
|
+
|
69
|
+
if type == :json then
|
70
|
+
begin
|
71
|
+
msg = JSON.pretty_generate(what)
|
72
|
+
rescue Exception => e
|
73
|
+
msg = what.to_json
|
74
|
+
end
|
75
|
+
else
|
76
|
+
msg = what.inspect
|
77
|
+
end
|
78
|
+
|
79
|
+
rv = ""
|
80
|
+
case type.to_sym
|
81
|
+
when :json
|
82
|
+
rv = render_to_string(:json => msg)
|
83
|
+
else
|
84
|
+
rv = render_to_string(:text => msg)
|
85
|
+
end
|
86
|
+
|
87
|
+
self.response_body = rv
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,298 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Cowtech
|
8
|
+
module CRUDHelper
|
9
|
+
attr_reader :data_bounds
|
10
|
+
attr_reader :record
|
11
|
+
|
12
|
+
def crud_get_data
|
13
|
+
@crud_data ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def crud_get_class(data = nil)
|
17
|
+
data = self.crud_get_data unless data
|
18
|
+
data[:class].constantize
|
19
|
+
end
|
20
|
+
|
21
|
+
def crud_get_records(data)
|
22
|
+
data = self.crud_get_data unless data
|
23
|
+
data[:records]
|
24
|
+
end
|
25
|
+
|
26
|
+
def crud_query_get_params(data = nil)
|
27
|
+
data = self.crud_get_data unless data
|
28
|
+
data[:query_params]
|
29
|
+
end
|
30
|
+
|
31
|
+
def crud_get_sort_order(data = nil)
|
32
|
+
data = self.crud_get_data unless data
|
33
|
+
data[:sort_order]
|
34
|
+
end
|
35
|
+
|
36
|
+
def crud_has_data?(data = nil)
|
37
|
+
data = self.crud_get_data unless data
|
38
|
+
data[:data_bounds].total > 0
|
39
|
+
end
|
40
|
+
|
41
|
+
def crud_get_pager_data(data = nil)
|
42
|
+
data = self.crud_get_data unless data
|
43
|
+
data[:pager_data]
|
44
|
+
end
|
45
|
+
|
46
|
+
def crud_get_form_data(data = nil)
|
47
|
+
# TODO: EH?
|
48
|
+
@record
|
49
|
+
end
|
50
|
+
|
51
|
+
def crud_get_data_bounds(data = nil)
|
52
|
+
data = self.crud_get_data unless data
|
53
|
+
data[:data_bounds]
|
54
|
+
end
|
55
|
+
|
56
|
+
def crud_set_data(data)
|
57
|
+
@crud_data = data
|
58
|
+
end
|
59
|
+
|
60
|
+
def crud_set_class(data, table = "")
|
61
|
+
data = self.crud_get_data unless data
|
62
|
+
data[:class] = table
|
63
|
+
end
|
64
|
+
|
65
|
+
def crud_set_records(data, records = nil)
|
66
|
+
data = self.crud_get_data unless data
|
67
|
+
data[:records] = records
|
68
|
+
end
|
69
|
+
|
70
|
+
def crud_finalize_read(data = nil, records = nil, parameter = :count, per_page = nil)
|
71
|
+
data = self.crud_get_data unless data
|
72
|
+
records = self.crud_get_records(data) unless records
|
73
|
+
self.crud_calculate_data_bounds(data, records, per_page || params[parameter])
|
74
|
+
data[:pager_data] = records.paginate(:page => data[:data_bounds].page, :per_page => data[:data_bounds].per_page, :total_entries => data[:data_bounds].total) if records.respond_to?(:paginate)
|
75
|
+
end
|
76
|
+
|
77
|
+
def crud_query_initialize(data = nil, force = false)
|
78
|
+
data = self.crud_get_data unless data
|
79
|
+
data[:query_expr] = [] if !data[:query_expr] || force
|
80
|
+
data[:query_params] = {} if !data[:query_params] || force
|
81
|
+
data[:query_initialized] = true
|
82
|
+
end
|
83
|
+
|
84
|
+
def crud_query_get(data = nil, query = nil)
|
85
|
+
data = self.crud_get_data unless data
|
86
|
+
self.crud_query_initialize(data) unless data[:query_initialized]
|
87
|
+
query = data[:query_expr] unless query
|
88
|
+
|
89
|
+
query.count.times do |i| query[i] = "(#{query[i]})" end
|
90
|
+
query.join(" AND ")
|
91
|
+
end
|
92
|
+
|
93
|
+
def crud_query_dump(data = nil)
|
94
|
+
data = self.crud_get_data unless data
|
95
|
+
self.crud_query_initialize(data) unless data[:query_initialized]
|
96
|
+
raise Exception.new("QUERY: #{data[:query_expr]}\nPARAMS: #{data[:query_params].to_json}")
|
97
|
+
end
|
98
|
+
|
99
|
+
def crud_query_add_condition(data, expr, params = {})
|
100
|
+
data = self.crud_get_data unless data
|
101
|
+
self.crud_query_initialize(data) unless data[:query_initialized]
|
102
|
+
|
103
|
+
expr = [expr] unless expr.respond_to?(:each)
|
104
|
+
expr.each do |e| data[:query_expr] << e end
|
105
|
+
|
106
|
+
data[:query_params].merge!(params)
|
107
|
+
end
|
108
|
+
|
109
|
+
def crud_query_parse_search(search)
|
110
|
+
search = "(@#{search}@)"
|
111
|
+
search.gsub!(/(\s+(AND|OR|NOT)\s+)/, "@) \\1 (@")
|
112
|
+
|
113
|
+
# SOSTITUIAMO I PARAMETRI
|
114
|
+
i = -1
|
115
|
+
parameters = {}
|
116
|
+
search.gsub!(/@(.+?)@/) do |s|
|
117
|
+
i += 1
|
118
|
+
|
119
|
+
key = "search_parameter_#{i}".to_sym
|
120
|
+
val = $1
|
121
|
+
|
122
|
+
# GESTIAMO I MARCATORI DI INIZIO E FINE RIGA
|
123
|
+
if val =~ /^\^.+\$$/ then
|
124
|
+
val = "#{val.gsub(/^\^(.+)\$$/, "\\1").strip}"
|
125
|
+
elsif val =~ /^\^/ then
|
126
|
+
val = "#{val.gsub(/^\^/, "").strip}%"
|
127
|
+
elsif val =~ /\$$/ then
|
128
|
+
val = "%#{val.gsub(/\$$/, "").strip}"
|
129
|
+
else
|
130
|
+
val = "%#{val.strip}%"
|
131
|
+
end
|
132
|
+
|
133
|
+
parameters[key] = val
|
134
|
+
"@FIELD@ LIKE :#{key}"
|
135
|
+
end
|
136
|
+
|
137
|
+
[search, parameters]
|
138
|
+
end
|
139
|
+
|
140
|
+
def crud_handle_search(data, *fields)
|
141
|
+
data = self.crud_get_data unless data
|
142
|
+
self.crud_handle_extended_search(data, fields)
|
143
|
+
end
|
144
|
+
|
145
|
+
def crud_handle_extended_search(data, fields, externals = nil, args = nil, parameter = :search)
|
146
|
+
data = self.crud_get_data unless data
|
147
|
+
self.crud_query_initialize(data) unless data[:query_initialized]
|
148
|
+
parameter = :search unless parameter
|
149
|
+
|
150
|
+
self.crud_query_add_condition(data, "(#{self.crud_get_class(data).table_name}.eliminato = :eliminato)", {:eliminato => false}) unless data[:skip_eliminato]
|
151
|
+
|
152
|
+
# OTTENIAMO LA QUERY
|
153
|
+
args = params[parameter] unless args
|
154
|
+
|
155
|
+
unless args.blank? then
|
156
|
+
search, parameters = self.crud_query_parse_search(args)
|
157
|
+
|
158
|
+
# COMPONIAMO LA QUERY
|
159
|
+
data[:query_params].merge!(parameters)
|
160
|
+
search_query = []
|
161
|
+
fields.each do |field| search_query << "(#{search.gsub("@FIELD@", field.to_s)})" end
|
162
|
+
|
163
|
+
# ADESSO AGGIUNGIAMO I CAMPI ADDIZIONALI
|
164
|
+
if externals then
|
165
|
+
externals.each do |external|
|
166
|
+
external_query = ""
|
167
|
+
|
168
|
+
unless external[:manual] then
|
169
|
+
external_conds = []
|
170
|
+
external.fetch(:fields, []).each do |external_field| external_conds << "(#{search.gsub("@FIELD@", external_field.to_s)})" end
|
171
|
+
external_field = external.fetch(:external_field, "id")
|
172
|
+
external_query = "(#{external.fetch(:field, "id")} IN (SELECT #{external.fetch(:external_field, "id")} FROM #{external[:table]} WHERE #{external_conds.join(" OR ")}))"
|
173
|
+
else
|
174
|
+
external_conds = []
|
175
|
+
external.fetch(:fields, []).each do |external_field| external_conds << "(#{search.gsub("@FIELD@", external_field.to_s)})" end
|
176
|
+
external_query = external[:query].gsub("@SEARCH@", external_conds.join(" OR "))
|
177
|
+
end
|
178
|
+
|
179
|
+
search_query << external_query
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
self.crud_query_add_condition(data, search_query.join(" OR "))
|
184
|
+
end
|
185
|
+
|
186
|
+
[data[:query_expr], data[:query_params]]
|
187
|
+
end
|
188
|
+
|
189
|
+
def crud_handle_sorting(data, default_sorting, sort_data, sort_expression = "@PLACEHOLDER@, updated_at DESC")
|
190
|
+
data = self.crud_get_data unless data
|
191
|
+
data[:sort_data] = sort_data
|
192
|
+
sort = self.crud_get_sort_param(default_sorting, (sort_data || {}).keys)
|
193
|
+
data[:sort] = "#{sort.what}-#{sort.how.downcase}"
|
194
|
+
data[:sort_order] = sort_expression.gsub("@PLACEHOLDER@", "#{sort.what} #{sort.how}")
|
195
|
+
end
|
196
|
+
|
197
|
+
def crud_form_header(female = false)
|
198
|
+
if self.crud_get_form_data.new_record? then
|
199
|
+
"Crea nuov#{if female then "a" else "o" end}"
|
200
|
+
else
|
201
|
+
"Modifica"
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def crud_form_submit_label
|
206
|
+
if self.crud_get_form_data.new_record? then "Inserisci" else "Modifica" end
|
207
|
+
end
|
208
|
+
|
209
|
+
def crud_get_page_param(key = :page, upperbound = -1)
|
210
|
+
page = params[key]
|
211
|
+
page = if params[key].is_valid_integer? then params[key].to_integer else 1 end
|
212
|
+
page = 1 if page < 1
|
213
|
+
page = upperbound if (upperbound > 0 and page > upperbound)
|
214
|
+
page
|
215
|
+
end
|
216
|
+
|
217
|
+
def crud_get_sort_param(default, valids = [])
|
218
|
+
sort_by = get_param(:sort_by, default)
|
219
|
+
mo = /^(?<what>[a-z0-9_]+)-(?<how>asc|desc)$/i.match(sort_by)
|
220
|
+
mo = /^(?<what>[a-z0-9_]+)-(?<how>asc|desc)$/i.match(default) if !mo || !(valids || []).include?(mo["what"])
|
221
|
+
|
222
|
+
sf = sort_by.split("-")
|
223
|
+
rv = OpenStruct.new({:what => mo["what"], :how => mo["how"].upcase})
|
224
|
+
|
225
|
+
# ADATTIAMO ALCUNI PARAMETRI
|
226
|
+
rv.what = "stato_id" if rv.what == "stato"
|
227
|
+
|
228
|
+
rv
|
229
|
+
end
|
230
|
+
|
231
|
+
def crud_calculate_data_bounds(data, records = nil, per_page = nil)
|
232
|
+
data = self.crud_get_data unless data
|
233
|
+
records = data[:records] unless records
|
234
|
+
bounds = OpenStruct.new({:total => 0, :first => 0, :last => 0, :pages => 0, :page => 1, :per_page => 1})
|
235
|
+
|
236
|
+
if records != nil && records.count > 0 then
|
237
|
+
per_page = (if per_page.is_valid_integer? then per_page else records[0].class.per_page end).to_integer
|
238
|
+
per_page = records.count if per_page < 1
|
239
|
+
bounds.total = records.count
|
240
|
+
bounds.per_page = per_page
|
241
|
+
bounds.pages = (bounds.total.to_f / bounds.per_page).ceil
|
242
|
+
bounds.page = self.crud_get_page_param(:page, bounds.pages)
|
243
|
+
|
244
|
+
base = ((bounds.page - 1) * bounds.per_page)
|
245
|
+
bounds.first = base + 1
|
246
|
+
bounds.last = base + bounds.per_page
|
247
|
+
bounds.last = bounds.total if bounds.last > bounds.total
|
248
|
+
end
|
249
|
+
|
250
|
+
data[:data_bounds] = bounds
|
251
|
+
end
|
252
|
+
|
253
|
+
def crud_update_params
|
254
|
+
# TODO: Come fai a backuppare alcuni elementi?
|
255
|
+
@agenda_update = params[:agenda_update]
|
256
|
+
blacklist = ["controller", "action", "id", "agenda_update"]
|
257
|
+
blacklist << "tipo" if self.class.name != "OrdiniController"
|
258
|
+
session["params-#{self.location_name}"] = (params.delete_if {|k,v| blacklist.include?(k) || params[k].is_a?(Tempfile)})
|
259
|
+
end
|
260
|
+
|
261
|
+
def crud_yesno
|
262
|
+
[OpenStruct.new(:value => true, :label => "Sì"), OpenStruct.new(:value => false, :label => "No")]
|
263
|
+
end
|
264
|
+
|
265
|
+
def crud_end_write_action(additional = nil, absolute = false)
|
266
|
+
redirect_to self.crud_end_write_action_url(additional, absolute)
|
267
|
+
end
|
268
|
+
|
269
|
+
def crud_end_write_action_url(additional = nil, absolute = false)
|
270
|
+
rp = {}
|
271
|
+
|
272
|
+
unless absolute then
|
273
|
+
rp = session["params-#{self.location_name(:index)}"] || {}
|
274
|
+
rp[:action] = :index
|
275
|
+
end
|
276
|
+
|
277
|
+
if additional != nil then
|
278
|
+
additional.each do |k, v| rp[k] = v end
|
279
|
+
end
|
280
|
+
|
281
|
+
url_for(rp)
|
282
|
+
end
|
283
|
+
|
284
|
+
def crud_delete(table, id, only_check = false)
|
285
|
+
record = table.constantize.safe_find(id.to_integer)
|
286
|
+
|
287
|
+
if record then
|
288
|
+
if only_check then
|
289
|
+
record.deletable?(controller.authenticated_user)
|
290
|
+
else
|
291
|
+
record.delete
|
292
|
+
end
|
293
|
+
else
|
294
|
+
false
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Cowtech
|
8
|
+
module FormatHelper
|
9
|
+
def browser
|
10
|
+
unless @browser then
|
11
|
+
rv = OpenStruct.new({:engine => :other, :version => 1.0})
|
12
|
+
|
13
|
+
unless request.env['HTTP_USER_AGENT'].blank? then
|
14
|
+
ua = request.env['HTTP_USER_AGENT'].downcase
|
15
|
+
|
16
|
+
if ua.index('msie') and !ua.index('opera') and !ua.index('webtv') then
|
17
|
+
rv.engine = :msie
|
18
|
+
rv.version = /.+msie ([0-9\.]+).+/.match(ua)[1].to_f
|
19
|
+
elsif ua.index('gecko/') or ua.index("mozilla/")
|
20
|
+
rv.engine = :gecko
|
21
|
+
elsif ua.index('opera')
|
22
|
+
rv.engine = :opera
|
23
|
+
elsif ua.index('konqueror')
|
24
|
+
rv.engine = :konqueror
|
25
|
+
elsif ua.index('webkit/')
|
26
|
+
rv.engine = :webkit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
@browser = rv
|
31
|
+
end
|
32
|
+
|
33
|
+
@browser
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_field(field, default = nil)
|
37
|
+
if field.is_a?(Fixnum) then
|
38
|
+
field
|
39
|
+
elsif field.is_a?(Float) then
|
40
|
+
field.format_number
|
41
|
+
elsif field.blank? || field.strip.blank? then
|
42
|
+
(if default then default else "Not set" end)
|
43
|
+
else
|
44
|
+
field
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def currency_class(currency, include_positive = true, include_zero = true)
|
49
|
+
color = ""
|
50
|
+
|
51
|
+
if currency > 0 then
|
52
|
+
color = "positive" if include_positive
|
53
|
+
elsif currency < 0 then
|
54
|
+
color = "negative"
|
55
|
+
else
|
56
|
+
color = "zero" if include_zero
|
57
|
+
end
|
58
|
+
|
59
|
+
"class=\"numeric #{color}\""
|
60
|
+
end
|
61
|
+
|
62
|
+
def text_class(val, additional = nil)
|
63
|
+
"class=\"text #{if additional.blank? then nil else additional end} #{if val.blank? then "unset" else nil end}\""
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Cowtech
|
8
|
+
module ValidationHelper
|
9
|
+
def exists?(cls, query, params)
|
10
|
+
cls.constantize.where(query, params).count > 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def json_is_available?(cls, query, params, must_exists = false, internal = false)
|
14
|
+
rv = self.setup_json_response(:validator)
|
15
|
+
|
16
|
+
rv["success"] = true
|
17
|
+
rv["valid"] = (self.exists?(cls, query, params) == must_exists)
|
18
|
+
|
19
|
+
if internal then
|
20
|
+
rv
|
21
|
+
else
|
22
|
+
custom_respond_with(rv.to_json)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Cowtech
|
8
|
+
module RoR
|
9
|
+
module Models
|
10
|
+
class EMail < ActionMailer::Base
|
11
|
+
def self.setup(method = :smtp)
|
12
|
+
rv = YAML.load_file(Rails.root + "config/email.yml")
|
13
|
+
|
14
|
+
ActionMailer::Base.raise_delivery_errors = true
|
15
|
+
ActionMailer::Base.default_charset = "utf-8"
|
16
|
+
ActionMailer::Base.delivery_method = method
|
17
|
+
|
18
|
+
case method
|
19
|
+
when :fail_test
|
20
|
+
raise ArgumentError
|
21
|
+
when :smtp
|
22
|
+
ActionMailer::Base.smtp_settings = rv[:smtp]
|
23
|
+
end
|
24
|
+
|
25
|
+
rv
|
26
|
+
end
|
27
|
+
|
28
|
+
def setup(method = :smtp)
|
29
|
+
@configuration = EMail.setup(method) unless @configuration
|
30
|
+
@configuration
|
31
|
+
end
|
32
|
+
|
33
|
+
def generic(*args)
|
34
|
+
self.setup
|
35
|
+
|
36
|
+
# OTTENIAMO GLI ARGOMENTI
|
37
|
+
args = (if args.is_a?(Hash) then args else args[0] end).delete_if { |k,v| v.blank? }
|
38
|
+
|
39
|
+
# AGGIUSTIAMO REPLY TO
|
40
|
+
args[:reply_to] = args[:from] unless args[:reply_to]
|
41
|
+
|
42
|
+
# OTTENIAMO IL BODY
|
43
|
+
plain_body = args.delete(:body) || args.delete(:plain_body) || args.delete(:text_body) || args.delete(:plain_text) || args.delete(:text)
|
44
|
+
html_body = args.delete(:html_body) || args.delete(:html)
|
45
|
+
|
46
|
+
mail(args) do |format|
|
47
|
+
if plain_body then # SE C'E' PLAIN BODY
|
48
|
+
format.text do render :text => plain_body end
|
49
|
+
end
|
50
|
+
if html_body then # SE C'E' HTML
|
51
|
+
format.html do render :text => html_body end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Cowtech
|
8
|
+
module RoR
|
9
|
+
module Models
|
10
|
+
class ModelBase < ::ActiveRecord::Base
|
11
|
+
def editable?(user = nil)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def deletable?(user = nil)
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete(definitive = false)
|
20
|
+
unless definitive then
|
21
|
+
if self.deletable? then
|
22
|
+
if self.respond_to?(:eliminato) then
|
23
|
+
self.eliminato = true
|
24
|
+
self.save
|
25
|
+
true
|
26
|
+
elsif self.respond_to?(:stato) then
|
27
|
+
self.stato = Stato[:eliminato]
|
28
|
+
self.save
|
29
|
+
true
|
30
|
+
else
|
31
|
+
super()
|
32
|
+
end
|
33
|
+
else
|
34
|
+
false
|
35
|
+
end
|
36
|
+
else
|
37
|
+
super(definitive)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
Object.class_eval do
|
8
|
+
include Cowtech::RoR::Extensions::Object
|
9
|
+
end
|
10
|
+
|
11
|
+
TrueClass.class_eval do
|
12
|
+
include Cowtech::RoR::Extensions::True
|
13
|
+
end
|
14
|
+
|
15
|
+
FalseClass.class_eval do
|
16
|
+
include Cowtech::RoR::Extensions::False
|
17
|
+
end
|
18
|
+
|
19
|
+
String.class_eval do
|
20
|
+
include Cowtech::RoR::Extensions::String
|
21
|
+
end
|
22
|
+
|
23
|
+
Time.class_eval do
|
24
|
+
include Cowtech::RoR::Extensions::DateTime
|
25
|
+
end
|
26
|
+
|
27
|
+
Date.class_eval do
|
28
|
+
include Cowtech::RoR::Extensions::DateTime
|
29
|
+
end
|
30
|
+
|
31
|
+
DateTime.class_eval do
|
32
|
+
include Cowtech::RoR::Extensions::DateTime
|
33
|
+
end
|
34
|
+
|
35
|
+
Hash.class_eval do
|
36
|
+
include Cowtech::RoR::Extensions::Hash
|
37
|
+
end
|
38
|
+
|
39
|
+
Pathname.class_eval do
|
40
|
+
include Cowtech::RoR::Extensions::Pathname
|
41
|
+
end
|
data/lib/cowtech.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
if defined?(Rails) && Rails::VERSION::MAJOR == 3 then
|
8
|
+
require 'engine'
|
9
|
+
require 'extensions'
|
10
|
+
require 'monkey_patches'
|
11
|
+
|
12
|
+
dir = File.dirname(__FILE__) + '/../'
|
13
|
+
require dir + '/app/models/e_mail'
|
14
|
+
require dir + '/app/models/model_base'
|
15
|
+
end
|
data/lib/engine.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Cowtech
|
8
|
+
class Engine < Rails::Engine
|
9
|
+
end
|
10
|
+
end
|
data/lib/extensions.rb
ADDED
@@ -0,0 +1,283 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Cowtech
|
8
|
+
module RoR
|
9
|
+
module Extensions
|
10
|
+
module Object
|
11
|
+
include ActionView::Helpers::NumberHelper
|
12
|
+
|
13
|
+
def nil_as_string
|
14
|
+
if self.blank? then "" else self end
|
15
|
+
end
|
16
|
+
|
17
|
+
def is_valid_number?
|
18
|
+
self.is_valid_float?
|
19
|
+
end
|
20
|
+
|
21
|
+
def is_valid_integer?
|
22
|
+
self.is_a?(Integer) || (!self.blank? && /^([+-]?)(\d+)$/.match(self.to_s.strip) != nil)
|
23
|
+
end
|
24
|
+
|
25
|
+
def is_valid_float?
|
26
|
+
self.is_a?(Float) || (!self.blank? && /^([+-]?)(\d+)([.,]\d*)?$/.match(self.to_s.strip) != nil)
|
27
|
+
end
|
28
|
+
|
29
|
+
def is_valid_boolean?
|
30
|
+
self.is_a?(TrueClass) || self.is_a?(FalseClass) || self.is_a?(NilClass) || /^(1|0|true|false|yes|no|t|f|y|n)$/i.match(self.to_s.strip) != nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def ensure_array
|
34
|
+
self.is_a?(Array) ? self : [self]
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_float
|
38
|
+
self.is_valid_float? ? Kernel.Float(self.respond_to?(:gsub) ? self.gsub(",", ".") : self) : 0.0
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_integer
|
42
|
+
self.is_valid_integer? ? Kernel.Integer(self, self.is_a?(String) ? 10 : 0) : 0
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_boolean
|
46
|
+
if self.is_a?(TrueClass) || self.is_a?(FalseClass) || self.is_a?(NilClass) then
|
47
|
+
self
|
48
|
+
else
|
49
|
+
self.is_valid_boolean? ? (/^(1|on|true|yes|t|y)$/i.match(self.to_s.strip) != nil) : false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def round_to_precision(prec = 2)
|
54
|
+
number_with_precision(self, :precision => prec)
|
55
|
+
end
|
56
|
+
|
57
|
+
def format_number(prec = 2, decimal_separator = ",", add_string = "€", k_separator = ".")
|
58
|
+
number_to_currency(self,
|
59
|
+
{
|
60
|
+
:precision => prec,
|
61
|
+
:separator => decimal_separator,
|
62
|
+
:delimiter => k_separator,
|
63
|
+
:format => if add_string.blank? then "%n" else "%n %u" end,
|
64
|
+
:unit => if add_string.blank? then "" else add_string.strip end
|
65
|
+
})
|
66
|
+
end
|
67
|
+
|
68
|
+
def format_boolean
|
69
|
+
self.to_boolean ? "Sì" : "No"
|
70
|
+
end
|
71
|
+
|
72
|
+
def dump
|
73
|
+
raise Exception.new("DUMP: #{self.to_json}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
module True
|
78
|
+
def to_i
|
79
|
+
1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module False
|
84
|
+
def to_i
|
85
|
+
0
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
module String
|
90
|
+
def remove_accents
|
91
|
+
self.mb_chars.normalize(:kd).gsub(/[^\-x00-\x7F]/n, '').to_s
|
92
|
+
end
|
93
|
+
|
94
|
+
def untitleize
|
95
|
+
self.downcase.gsub(" ", "-")
|
96
|
+
end
|
97
|
+
|
98
|
+
def replace_ampersands
|
99
|
+
self.gsub(/&(\S+);/, "&\\1;")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
module Hash
|
104
|
+
def method_missing(method, *arg)
|
105
|
+
self[method.to_sym] || self[method.to_s]
|
106
|
+
end
|
107
|
+
|
108
|
+
def respond_to?(method)
|
109
|
+
self.has_key?(method.to_sym) || self.has_key?(method.to_s)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
module Pathname
|
114
|
+
def components
|
115
|
+
rv = []
|
116
|
+
self.each_filename do |p| rv << p end
|
117
|
+
rv
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
module DateTime
|
122
|
+
module ClassMethods
|
123
|
+
def months
|
124
|
+
i = 0
|
125
|
+
months = localized_months
|
126
|
+
months.keys.collect do |k|
|
127
|
+
i+= 1
|
128
|
+
{:value => i.to_s.rjust(2, "0"), :description => months[k][0, 3]}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def localized_months
|
133
|
+
{"January" => "January", "February" => "February", "March" => "March", "April" => "April", "May" => "May", "June" => "June",
|
134
|
+
"July" => "July", "August" => "August", "September" => "September", "October" => "October", "November" => "November", "December" => "December"}
|
135
|
+
end
|
136
|
+
|
137
|
+
def localized_days
|
138
|
+
{"Sunday" => "Sunday", "Monday" => "Monday", "Tuesday" => "Tuesday", "Wednesday" => "Wednesday", "Thursday" => "Thursday", "Friday" => "Friday", "Saturday" => "Saturday"}
|
139
|
+
end
|
140
|
+
|
141
|
+
def custom_format(key="date")
|
142
|
+
{
|
143
|
+
"date" => "%d/%m/%Y",
|
144
|
+
"time" => "%H:%M:%S",
|
145
|
+
"date-8601" => "%Y-%m-%d",
|
146
|
+
"date-time-8601" => "%Y-%m-%d %H:%M:%S",
|
147
|
+
"iso-8601" => "%FT%T%z",
|
148
|
+
"update" => "%d/%m/%Y %H:%M"
|
149
|
+
}.fetch(key.to_s, "%d/%m/%Y")
|
150
|
+
end
|
151
|
+
|
152
|
+
def years(offset = 10, also_future = true)
|
153
|
+
rv = []
|
154
|
+
y = Date.today.year
|
155
|
+
(y - offset..(also_future ? y + offset : y)).each do |year| rv << {:value => year} end
|
156
|
+
rv
|
157
|
+
end
|
158
|
+
|
159
|
+
def localized_short_months
|
160
|
+
rv = {}
|
161
|
+
self.localized_months.each do |k,v| rv[k[0, 3]] = v[0, 3] end
|
162
|
+
rv
|
163
|
+
end
|
164
|
+
|
165
|
+
def localized_short_days
|
166
|
+
rv = {}
|
167
|
+
self.localized_days.each do |k,v| rv[k[0, 3]] = v[0, 3] end
|
168
|
+
rv
|
169
|
+
end
|
170
|
+
|
171
|
+
def easter(year = nil)
|
172
|
+
day = 1
|
173
|
+
month = 3
|
174
|
+
year = Date.today.year unless year.is_valid_integer?
|
175
|
+
|
176
|
+
# GAUSS METHOD
|
177
|
+
m = 24
|
178
|
+
n = 5
|
179
|
+
a = year % 19
|
180
|
+
b = year % 4
|
181
|
+
c = year % 7
|
182
|
+
d = ((19 * a) + m) % 30
|
183
|
+
e = ((2 * b) + (4 * c) + (6 * d) + n) % 7
|
184
|
+
|
185
|
+
if d + e < 10 then
|
186
|
+
day = d + e + 22
|
187
|
+
else
|
188
|
+
day = d + e - 9
|
189
|
+
month = 4
|
190
|
+
end
|
191
|
+
|
192
|
+
if day == 26 && month == 4 then
|
193
|
+
day = 19
|
194
|
+
elsif day == 25 && month == 4 && d == 28 && e == 6 && a > 10 then
|
195
|
+
day = 18
|
196
|
+
end
|
197
|
+
#END
|
198
|
+
|
199
|
+
Date.civil(year, month, day)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def self.included(receiver)
|
204
|
+
receiver.extend ClassMethods
|
205
|
+
end
|
206
|
+
|
207
|
+
def lstrftime(format = nil)
|
208
|
+
format = self.class.custom_format($1) if format =~ /^custom::(.+)/
|
209
|
+
unlocal = self.strftime(format || self.class.custom_format("update"))
|
210
|
+
|
211
|
+
# SCAMBIAMO I MESI E I GIORNI COMPLETI
|
212
|
+
unlocal.gsub!(/(#{self.class.localized_months.keys.join("|")})/i) do |s| self.class.localized_months[$1] end
|
213
|
+
unlocal.gsub!(/(#{self.class.localized_days.keys.join("|")})/i) do |s| self.class.localized_days[$1] end
|
214
|
+
|
215
|
+
# SCAMBIAMO I MESI E I GIORNI CORTI
|
216
|
+
unlocal.gsub!(/(#{self.class.localized_short_months.keys.join("|")})/i) do |s| self.class.localized_short_months[$1] end
|
217
|
+
unlocal.gsub!(/(#{self.class.localized_short_days.keys.join("|")})/i) do |s| self.class.localized_short_days[$1] end
|
218
|
+
|
219
|
+
unlocal
|
220
|
+
end
|
221
|
+
|
222
|
+
def padded_month
|
223
|
+
self.month.to_s.rjust(2, "0")
|
224
|
+
end
|
225
|
+
|
226
|
+
def in_months
|
227
|
+
((self.year - 1) % 2000) * 12 + self.month
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
module Math
|
235
|
+
def self.max(a, b)
|
236
|
+
if a > b then a else b end
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.min(a, b)
|
240
|
+
if a < b then a else b end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
class ActiveRecord::Base
|
245
|
+
def self.table_prefix
|
246
|
+
p = ActiveRecord::Base.configurations[Rails.env]["table_prefix"]
|
247
|
+
!p.blank? ? p + "_" : ""
|
248
|
+
end
|
249
|
+
|
250
|
+
def self.table_suffix
|
251
|
+
p = ActiveRecord::Base.configurations[Rails.env]["table_suffix"]
|
252
|
+
!p.blank? ? p + "_" : ""
|
253
|
+
end
|
254
|
+
|
255
|
+
def self.set_table_name(value = nil, &block)
|
256
|
+
define_attr_method :table_name, "#{ActiveRecord::Base.table_prefix}#{value}#{ActiveRecord::Base.table_suffix}", &block
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.find_or_create(oid, attributes = nil)
|
260
|
+
begin
|
261
|
+
self.find(oid)
|
262
|
+
rescue ActiveRecord::RecordNotFound
|
263
|
+
self.new(attributes)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def self.safe_find(oid)
|
268
|
+
begin
|
269
|
+
rv = self.find(oid)
|
270
|
+
rescue ActiveRecord::RecordNotFound
|
271
|
+
nil
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def self.random
|
276
|
+
c = self.count
|
277
|
+
c != 0 ? self.find(:first, :offset => rand(c)) : nil
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.per_page
|
281
|
+
25
|
282
|
+
end
|
283
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module SubdomainFu
|
8
|
+
def self.override_only_path?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# To enable real SSL
|
14
|
+
if defined?(Mail) then
|
15
|
+
class Mail::SMTP
|
16
|
+
def deliver!(mail)
|
17
|
+
|
18
|
+
# Set the envelope from to be either the return-path, the sender or the first from address
|
19
|
+
envelope_from = mail.return_path || mail.sender || mail.from_addrs.first
|
20
|
+
if envelope_from.blank?
|
21
|
+
raise ArgumentError.new('A sender (Return-Path, Sender or From) required to send a message')
|
22
|
+
end
|
23
|
+
|
24
|
+
destinations ||= mail.destinations if mail.respond_to?(:destinations) && mail.destinations
|
25
|
+
if destinations.blank?
|
26
|
+
raise ArgumentError.new('At least one recipient (To, Cc or Bcc) is required to send a message')
|
27
|
+
end
|
28
|
+
|
29
|
+
message ||= mail.encoded if mail.respond_to?(:encoded)
|
30
|
+
if message.blank?
|
31
|
+
raise ArgumentError.new('A encoded content is required to send a message')
|
32
|
+
end
|
33
|
+
|
34
|
+
smtp = Net::SMTP.new(settings[:address], settings[:port])
|
35
|
+
if settings[:tls] || settings[:ssl]
|
36
|
+
if smtp.respond_to?(:enable_tls)
|
37
|
+
unless settings[:openssl_verify_mode]
|
38
|
+
smtp.enable_tls
|
39
|
+
else
|
40
|
+
openssl_verify_mode = settings[:openssl_verify_mode]
|
41
|
+
if openssl_verify_mode.kind_of?(String)
|
42
|
+
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{openssl_verify_mode.upcase}".constantize
|
43
|
+
end
|
44
|
+
context = Net::SMTP.default_ssl_context
|
45
|
+
context.verify_mode = openssl_verify_mode
|
46
|
+
smtp.enable_tls(context)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
elsif settings[:enable_starttls_auto]
|
50
|
+
if smtp.respond_to?(:enable_starttls_auto)
|
51
|
+
unless settings[:openssl_verify_mode]
|
52
|
+
smtp.enable_starttls_auto
|
53
|
+
else
|
54
|
+
openssl_verify_mode = settings[:openssl_verify_mode]
|
55
|
+
if openssl_verify_mode.kind_of?(String)
|
56
|
+
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{openssl_verify_mode.upcase}".constantize
|
57
|
+
end
|
58
|
+
context = Net::SMTP.default_ssl_context
|
59
|
+
context.verify_mode = openssl_verify_mode
|
60
|
+
smtp.enable_starttls_auto(context)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
smtp.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication]) do |smtp|
|
65
|
+
smtp.sendmail(message, envelope_from, destinations)
|
66
|
+
end
|
67
|
+
|
68
|
+
self
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/version.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the cowtech-rails gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Cowtech
|
8
|
+
module Rails
|
9
|
+
module Version
|
10
|
+
MAJOR = 1
|
11
|
+
MINOR = 0
|
12
|
+
PATCH = 0
|
13
|
+
BUILD = 0
|
14
|
+
|
15
|
+
STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/rails/init.rb
ADDED
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cowtech-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Shogun
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-04-05 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: A general purpose Rails utility plugin.
|
23
|
+
email: shogun_panda@me.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- README
|
30
|
+
files:
|
31
|
+
- app/helpers/cowtech/application_helper.rb
|
32
|
+
- app/helpers/cowtech/crud_helper.rb
|
33
|
+
- app/helpers/cowtech/format_helper.rb
|
34
|
+
- app/helpers/cowtech/validation_helper.rb
|
35
|
+
- app/models/e_mail.rb
|
36
|
+
- app/models/model_base.rb
|
37
|
+
- config/initializers/extensions.rb
|
38
|
+
- lib/cowtech.rb
|
39
|
+
- lib/engine.rb
|
40
|
+
- lib/extensions.rb
|
41
|
+
- lib/monkey_patches.rb
|
42
|
+
- lib/version.rb
|
43
|
+
- rails/init.rb
|
44
|
+
- README
|
45
|
+
has_rdoc: true
|
46
|
+
homepage: http://github.com/ShogunPanda/cowtech-rails
|
47
|
+
licenses:
|
48
|
+
- MIT
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.7
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: A general purpose Rails utility plugin.
|
77
|
+
test_files: []
|
78
|
+
|