rails_core_extensions 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.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.hound.yml +2 -0
- data/.rspec +2 -0
- data/.ruby-style.yml +233 -0
- data/.travis.yml +14 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +62 -0
- data/Rakefile +12 -0
- data/gemfiles/rails3.gemfile +13 -0
- data/gemfiles/rails4.gemfile +14 -0
- data/lib/rails_core_extensions.rb +41 -0
- data/lib/rails_core_extensions/action_controller_sortable.rb +22 -0
- data/lib/rails_core_extensions/action_view_currency_extensions.rb +26 -0
- data/lib/rails_core_extensions/action_view_extensions.rb +62 -0
- data/lib/rails_core_extensions/action_view_has_many_extensions.rb +32 -0
- data/lib/rails_core_extensions/activatable.rb +38 -0
- data/lib/rails_core_extensions/active_model_extensions.rb +47 -0
- data/lib/rails_core_extensions/active_record_cache_all_attributes.rb +43 -0
- data/lib/rails_core_extensions/active_record_cloning.rb +81 -0
- data/lib/rails_core_extensions/active_record_extensions.rb +228 -0
- data/lib/rails_core_extensions/active_record_liquid_extensions.rb +32 -0
- data/lib/rails_core_extensions/active_support_concern.rb +134 -0
- data/lib/rails_core_extensions/breadcrumb.rb +170 -0
- data/lib/rails_core_extensions/caches_action_without_host.rb +17 -0
- data/lib/rails_core_extensions/concurrency.rb +152 -0
- data/lib/rails_core_extensions/position_initializer.rb +27 -0
- data/lib/rails_core_extensions/railtie.rb +7 -0
- data/lib/rails_core_extensions/sortable.rb +52 -0
- data/lib/rails_core_extensions/tasks/position_initializer.rake +12 -0
- data/lib/rails_core_extensions/time_with_zone.rb +16 -0
- data/lib/rails_core_extensions/version.rb +3 -0
- data/rails_core_extensions.gemspec +38 -0
- data/spec/action_controller_sortable_spec.rb +52 -0
- data/spec/action_view_extensions_spec.rb +25 -0
- data/spec/active_model_extensions_spec.rb +130 -0
- data/spec/active_record_extensions_spec.rb +126 -0
- data/spec/breadcrumb_spec.rb +85 -0
- data/spec/concurrency_spec.rb +110 -0
- data/spec/position_initializer_spec.rb +48 -0
- data/spec/schema.rb +17 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/spec_helper_model_base.rb +37 -0
- data/spec/support/coverage_loader.rb +26 -0
- metadata +294 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module RailsCoreExtensions
|
2
|
+
module ActionControllerSortable
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def sortable
|
9
|
+
include RailsCoreExtensions::ActionControllerSortable::InstanceMethods
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module InstanceMethods
|
14
|
+
def sort
|
15
|
+
RailsCoreExtensions::Sortable.new(params, controller_name).sort
|
16
|
+
|
17
|
+
render :update do |page|
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActionView
|
2
|
+
module Helpers
|
3
|
+
module FormTagHelper
|
4
|
+
# Create currency selector tag -- see select_tag for options
|
5
|
+
def currency_select_tag(name, current_value, options={})
|
6
|
+
selectable_options = []
|
7
|
+
selectable_options << ["--", nil] if options[:include_blank]
|
8
|
+
selectable_options += EnabledCurrency.all.map(&:iso_code) unless EnabledCurrency.all.empty?
|
9
|
+
select_tag(name, options_for_select(selectable_options, current_value), options)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module DateHelper
|
14
|
+
def currency_select(object_name, method, options = {})
|
15
|
+
value = options[:object] || EnabledCurrency.base_currency
|
16
|
+
currency_select_tag("#{object_name}[#{method}]", value, options.merge(:id => "#{object_name}_#{method}"))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class FormBuilder
|
21
|
+
def currency_select(method, options = {})
|
22
|
+
@template.currency_select(@object_name, method, options.merge(:object => @object.send(method)))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module RailsCoreExtensions
|
2
|
+
module ActionViewExtensions
|
3
|
+
def textilize(content)
|
4
|
+
super(h(content)).html_safe
|
5
|
+
end
|
6
|
+
|
7
|
+
# Will recursively parse a Hash and any sub hashes to be normal hashes
|
8
|
+
# This is useful when exporting hashes to non ruby systems, which don't understand HashWithIndifferentAccess
|
9
|
+
def hashify(element)
|
10
|
+
if element.is_a? Hash
|
11
|
+
element = element.to_hash if element.is_a?(HashWithIndifferentAccess)
|
12
|
+
element.each_pair do |key, value|
|
13
|
+
element[key] = hashify(value)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
# Must hashify enumerables encase their sub items are hashes
|
17
|
+
# Can't enumerate through string as it returns strings, which are also enumerable (stack level too deep)
|
18
|
+
if element.respond_to?(:each) && !element.is_a?(String)
|
19
|
+
element.map{ |sub| hashify(sub) }
|
20
|
+
else
|
21
|
+
element
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Generates a tooltip with given text
|
27
|
+
# text is textilized before display
|
28
|
+
def tooltip(hover_element_id, text, title='')
|
29
|
+
content = "<div style='width: 25em'>#{textilize(text)}</div>"
|
30
|
+
"<script>" +
|
31
|
+
"new Tip('#{hover_element_id}', '#{escape_javascript(content)}',"+
|
32
|
+
"{title : '#{escape_javascript title}', className: 'silver_smaller_div',"+
|
33
|
+
"showOn: 'mouseover', hideOn: { event: 'mouseout' }, fixed: false});"+
|
34
|
+
"</script>"
|
35
|
+
end
|
36
|
+
|
37
|
+
def expandable_list_for(objects, show = 4)
|
38
|
+
first, others = objects[0..(show-1)], objects[show..(objects.size-1)]
|
39
|
+
first.each do |o|
|
40
|
+
yield o
|
41
|
+
end
|
42
|
+
if others
|
43
|
+
content_tag 'div', :id => 'others', :style => 'display: none' do
|
44
|
+
others.each do |o|
|
45
|
+
yield o
|
46
|
+
end
|
47
|
+
end
|
48
|
+
"#{others.size} Others - ".html_safe + link_to_function("Show/Hide", "$('others').toggle()")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def boolean_select_tag(name, *args)
|
53
|
+
options = args.extract_options!
|
54
|
+
options ||= {}
|
55
|
+
opts = [['Yes', '1'], ['No', '0']]
|
56
|
+
opts = [blank_option] + opts if options[:include_blank]
|
57
|
+
select_tag name, options_for_select(opts, options[:selected])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
ActionView::Base.send(:include, RailsCoreExtensions::ActionViewExtensions) if defined?(ActionView::Base)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module RailsCoreExtensions
|
2
|
+
module HasManyExtensions
|
3
|
+
module Tags
|
4
|
+
def hm_check_box(object_name, method, options = {})
|
5
|
+
object = options.delete(:object)
|
6
|
+
parent = options.delete(:parent) || instance_variable_get(object_name)
|
7
|
+
objects = options.delete(:objects) || parent.send(method)
|
8
|
+
check_box_tag("#{object_name}[#{method}][]", object, objects.include?(object), options.merge(:id => "#{object_name}_#{method}"))
|
9
|
+
end
|
10
|
+
|
11
|
+
def hm_empty_array(object_name, method)
|
12
|
+
hidden_field_tag "#{object_name}[#{method}][]"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module FormBuilder
|
17
|
+
def hm_empty_array(method)
|
18
|
+
@habtm_fields ||= {}
|
19
|
+
@habtm_fields[method] = @object.send(method)
|
20
|
+
@template.hm_empty_array(@object_name, method)
|
21
|
+
end
|
22
|
+
|
23
|
+
def hm_check_box(method, object, options = {})
|
24
|
+
empty = (hm_empty_array(method) unless @habtm_fields && @habtm_fields[method])
|
25
|
+
(empty || '').html_safe + @template.hm_check_box(@object_name, method, options.merge(:object => object, :parent => @object, :objects => @habtm_fields[method]))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
ActionView::Base.send(:include, RailsCoreExtensions::HasManyExtensions::Tags) if defined?(ActionView::Base)
|
32
|
+
ActionView::Helpers::FormBuilder.send(:include, RailsCoreExtensions::HasManyExtensions::FormBuilder) if defined?(ActionView::Base)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Activatable
|
2
|
+
|
3
|
+
def self.included(controller)
|
4
|
+
controller.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
def activatable
|
10
|
+
include Activatable::InstanceMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
module InstanceMethods
|
16
|
+
|
17
|
+
def activate(success_block = nil)
|
18
|
+
resource.active = params[:active].presence || false
|
19
|
+
action = resource.active ? 'activate' : 'inactivate'
|
20
|
+
|
21
|
+
resource.save!
|
22
|
+
|
23
|
+
success_block ||= -> {
|
24
|
+
flash[:success] = "#{resource} #{action}d"
|
25
|
+
redirect_to(collection_path)
|
26
|
+
}
|
27
|
+
|
28
|
+
success_block.call
|
29
|
+
|
30
|
+
rescue ActiveRecord::ActiveRecordError => e
|
31
|
+
resource.errors.add(:base, "Failed to #{action}: " + e.message)
|
32
|
+
flash[:error] = resource.errors.full_messages.to_sentence
|
33
|
+
redirect_to(collection_path)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ActiveModelExtensions
|
2
|
+
module Validations
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
# Validates the presence of the required fields identified in a rule-string.
|
8
|
+
#
|
9
|
+
# Similar to validates_presence_of macro, but is an INSTANCE method.
|
10
|
+
# This allows it to vary depending on custom settings.
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# validate_required_fields "field1,field2 or field4"
|
14
|
+
#
|
15
|
+
|
16
|
+
# The string is a CSV of required field rules, where each field rule is:
|
17
|
+
# - the name of a required field
|
18
|
+
# - OR a set of required field names spearated by 'or' (where only ONE is required)
|
19
|
+
#
|
20
|
+
class CustomPresenceValidator < ActiveModel::Validator
|
21
|
+
def validate(record)
|
22
|
+
required_fields = Array.wrap(@options[:attributes]).first.call || []
|
23
|
+
return if required_fields.empty?
|
24
|
+
|
25
|
+
required_fields.flatten.each do |required_field|
|
26
|
+
if required_field.include? ' or '
|
27
|
+
fields = required_field.split(' or ')
|
28
|
+
if fields.all? { |field| record.send(field).to_s.blank? }
|
29
|
+
record.errors.add(:base, "One of %s is required" % fields.map(&:humanize).to_sentence)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
if record.send(required_field).to_s.blank?
|
33
|
+
record.errors.add(required_field, "is required")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
def validate_presence_by_custom_rules(*with)
|
43
|
+
validates_with CustomPresenceValidator, _merge_attributes(with)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ActiveRecordCacheAllAttributes
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
end
|
5
|
+
|
6
|
+
module InstanceMethods
|
7
|
+
def clear_attribute_cache
|
8
|
+
self.class.cache.delete("#{self.class.name}.attribute_cache") if self.class.should_cache?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def cache
|
14
|
+
Rails.cache
|
15
|
+
end
|
16
|
+
|
17
|
+
def attribute_cache
|
18
|
+
cache_key = "#{self.name}.attribute_cache"
|
19
|
+
if self.should_cache?
|
20
|
+
cache.read(cache_key) || self.generate_cache(cache_key)
|
21
|
+
else
|
22
|
+
self.generate_attributes_hash
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate_attributes_hash
|
27
|
+
scope = self
|
28
|
+
scope = scope.ordered if respond_to?(:ordered)
|
29
|
+
Hash[scope.all.map { |o| [o.send(self.cache_attributes_by), o.attributes] }]
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_cache(cache_key)
|
33
|
+
if (cache_value = generate_attributes_hash)
|
34
|
+
cache.write(cache_key, cache_value)
|
35
|
+
end
|
36
|
+
cache_value
|
37
|
+
end
|
38
|
+
|
39
|
+
def should_cache?
|
40
|
+
Rails.configuration.action_controller.perform_caching
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module ActiveRecordCloning
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
def inherited(subclass)
|
10
|
+
super
|
11
|
+
subclass.cloned_attributes_hash = cloned_attributes_hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def attributes_included_in_cloning
|
15
|
+
cloned_attributes_hash[:include].dup
|
16
|
+
end
|
17
|
+
|
18
|
+
def attributes_excluded_from_cloning
|
19
|
+
cloned_attributes_hash[:exclude].dup
|
20
|
+
end
|
21
|
+
|
22
|
+
def clones_attributes(*attributes)
|
23
|
+
cloned_attributes_hash[:include] = attributes.map(&:to_sym)
|
24
|
+
end
|
25
|
+
|
26
|
+
def clones_attributes_except(*attributes)
|
27
|
+
cloned_attributes_hash[:exclude] = attributes.map(&:to_sym)
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def cloned_attributes_hash
|
33
|
+
@cloned_attributes ||= {:include => [], :exclude => []}
|
34
|
+
end
|
35
|
+
|
36
|
+
def cloned_attributes_hash=(attributes_hash)
|
37
|
+
@cloned_attributes = attributes_hash
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
module InstanceMethods
|
43
|
+
|
44
|
+
def self.included(base)
|
45
|
+
base.class_eval %q{
|
46
|
+
alias_method :base_clone_attributes, :clone_attributes
|
47
|
+
def clone_attributes(reader_method = :read_attribute, attributes = {})
|
48
|
+
allowed = cloned_attributes
|
49
|
+
base_clone_attributes(reader_method, attributes).delete_if { |k,v| !allowed.include?(k.to_sym) }
|
50
|
+
end
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def clone_excluding(excludes=[])
|
55
|
+
method = ActiveRecord::Base.instance_methods(false).include?(:clone) ? :clone : :dup
|
56
|
+
cloned = send(method)
|
57
|
+
|
58
|
+
excludes ||= []
|
59
|
+
excludes = [excludes] unless excludes.is_a?(Enumerable)
|
60
|
+
|
61
|
+
excludes.each do |excluded_attr|
|
62
|
+
attr_writer = (excluded_attr.to_s + '=').to_sym
|
63
|
+
cloned.send attr_writer, nil
|
64
|
+
end
|
65
|
+
|
66
|
+
cloned
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def cloned_attributes
|
72
|
+
included_attributes = if self.class.attributes_included_in_cloning.empty?
|
73
|
+
attribute_names.map(&:to_sym)
|
74
|
+
else
|
75
|
+
attribute_names.map(&:to_sym) & self.class.attributes_included_in_cloning
|
76
|
+
end
|
77
|
+
included_attributes - self.class.attributes_excluded_from_cloning
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
module ActiveRecordExtensions
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
end
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
# Like establish_connection but postfixes the key with the rails environment
|
8
|
+
# e.g. database('hello') in development will look for the database
|
9
|
+
# which in config/database.yml is called hello_development
|
10
|
+
def database(key)
|
11
|
+
establish_connection("#{key}_#{Rails.env}")
|
12
|
+
end
|
13
|
+
|
14
|
+
def cache_all_attributes(options = {})
|
15
|
+
method = options[:by] || 'id'
|
16
|
+
class_eval <<-CACHE
|
17
|
+
after_save :clear_attribute_cache
|
18
|
+
after_destroy :clear_attribute_cache
|
19
|
+
cattr_accessor :cache_attributes_by
|
20
|
+
self.cache_attributes_by = '#{method}'
|
21
|
+
CACHE
|
22
|
+
extend ActiveRecordCacheAllAttributes::ClassMethods
|
23
|
+
include ActiveRecordCacheAllAttributes::InstanceMethods
|
24
|
+
end
|
25
|
+
|
26
|
+
# Create a new object from the attributes passed in
|
27
|
+
# OR update an existing
|
28
|
+
#
|
29
|
+
# If an :id attribute is present it will assume it's an existing record, and needs update
|
30
|
+
def new_or_update!(hash={}, options = {:hard_update => true})
|
31
|
+
hash.symbolize_keys!
|
32
|
+
if hash[:id].blank?
|
33
|
+
self.new(hash)
|
34
|
+
else
|
35
|
+
rec = self.find(hash[:id])
|
36
|
+
if options[:hard_update]
|
37
|
+
rec.update_attributes!(hash.except(:id))
|
38
|
+
else
|
39
|
+
rec.update_attributes(hash.except(:id))
|
40
|
+
end
|
41
|
+
rec
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def enum(field, values, options = {})
|
46
|
+
const_set("#{field.to_s.upcase}_OPTIONS", values)
|
47
|
+
|
48
|
+
select_options = if values.is_a?(Array)
|
49
|
+
values.map.with_index{|v, i| [v.to_s.humanize, i]}
|
50
|
+
elsif values.is_a?(Hash)
|
51
|
+
values.values.map.with_index{|v, i| [v, i]}
|
52
|
+
end
|
53
|
+
const_set("#{field.to_s.upcase}_SELECT_OPTIONS", select_options)
|
54
|
+
|
55
|
+
values.each.with_index do |value, i|
|
56
|
+
const_set("#{field.to_s.upcase}_#{value.to_s.upcase}", i)
|
57
|
+
method_name = options[:short_name] ? "#{value}?" : "#{field}_#{value}?"
|
58
|
+
class_eval <<-ENUM
|
59
|
+
def #{method_name}
|
60
|
+
#{field} == #{i}
|
61
|
+
end
|
62
|
+
ENUM
|
63
|
+
end
|
64
|
+
class_eval <<-ENUM
|
65
|
+
def #{field}_name
|
66
|
+
#{field.to_s.upcase}_OPTIONS[#{field}]
|
67
|
+
end
|
68
|
+
ENUM
|
69
|
+
end
|
70
|
+
|
71
|
+
def optional_fields(*possible_fields)
|
72
|
+
@optional_fields_loader = possible_fields.pop if possible_fields.last.is_a?(Proc)
|
73
|
+
|
74
|
+
class << self
|
75
|
+
def enabled_fields
|
76
|
+
@enabled_fields || @optional_fields_loader.try(:call)
|
77
|
+
end
|
78
|
+
|
79
|
+
def enabled_fields=(fields)
|
80
|
+
@enabled_fields = fields
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
possible_fields.each do |field|
|
85
|
+
instance_eval <<-EVAL
|
86
|
+
def #{field}_enabled?
|
87
|
+
enabled_fields.include?(:#{field})
|
88
|
+
end
|
89
|
+
EVAL
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
def position_helpers_for(*collections)
|
95
|
+
collections.each do |collection|
|
96
|
+
class_eval <<-EVAL
|
97
|
+
after_save do |record|
|
98
|
+
record.rebalance_#{collection.to_s.singularize}_positions!
|
99
|
+
end
|
100
|
+
|
101
|
+
def assign_#{collection.to_s.singularize}_position(object)
|
102
|
+
object.position = (#{collection}.last.try(:position) || 0) + 1 unless object.position
|
103
|
+
end
|
104
|
+
|
105
|
+
def rebalance_#{collection.to_s.singularize}_positions!(object = nil)
|
106
|
+
reload
|
107
|
+
#{collection}.sort_by(&:position).each_with_index do |o, index|
|
108
|
+
if o.position != (index + 1)
|
109
|
+
o.update_attribute(:position, index + 1)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
EVAL
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
# Validates presence of -- but works on parent within accepts_nested_attributes
|
119
|
+
#
|
120
|
+
def validates_presence_of_parent(foreign_key)
|
121
|
+
after_save do |record|
|
122
|
+
unless record.send(foreign_key)
|
123
|
+
record.errors.add_on_blank(foreign_key)
|
124
|
+
raise ActiveRecord::ActiveRecordError, record.errors.full_messages.to_sentence
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
# Run a block, being respectful of connection pools
|
131
|
+
#
|
132
|
+
# Useful for when you're not in the standard rails request process,
|
133
|
+
# since normally rails will take, then clear you're connection in the
|
134
|
+
# processing of the request.
|
135
|
+
#
|
136
|
+
# If you don't do this in, say, a command line task with threads, then
|
137
|
+
# you'll run out of connections after 5 x Threads are run simultaneously...
|
138
|
+
def with_connection_pooling
|
139
|
+
# Verify active connections and remove and disconnect connections
|
140
|
+
# associated with stale threads.
|
141
|
+
ActiveRecord::Base.verify_active_connections!
|
142
|
+
|
143
|
+
yield
|
144
|
+
|
145
|
+
# This code checks in the connection being used by the current thread back
|
146
|
+
# into the connection pool. It repeats this if you are using multiple
|
147
|
+
# connection pools. It will not disconnect the connection.
|
148
|
+
#
|
149
|
+
# Returns any connections in use by the current thread back to the pool,
|
150
|
+
# and also returns connections to the pool cached by threads that are no
|
151
|
+
# longer alive.
|
152
|
+
ActiveRecord::Base.clear_active_connections!
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
def translate(key, options = {})
|
158
|
+
klass = self
|
159
|
+
klass = klass.superclass while klass.superclass != ActiveRecord::Base
|
160
|
+
I18n.translate key, options.merge(:scope => klass.name.tableize.singularize)
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
def t(key, options = {})
|
165
|
+
self.translate(key, options)
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
module InstanceMethods
|
172
|
+
|
173
|
+
|
174
|
+
def all_errors
|
175
|
+
errors_hash = {}
|
176
|
+
self.errors.each do |attr, msg|
|
177
|
+
(errors_hash[attr] ||= []) << if self.respond_to?(attr) && (record_attr = self.send(attr)).is_a?(ActiveRecord::Base)
|
178
|
+
record_attr.all_errors
|
179
|
+
else
|
180
|
+
msg
|
181
|
+
end
|
182
|
+
end
|
183
|
+
errors_hash
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
def to_drop
|
188
|
+
@drop_class ||= (self.class.name+'Drop').constantize
|
189
|
+
@drop_class.new(self)
|
190
|
+
end
|
191
|
+
alias_method :to_liquid, :to_drop
|
192
|
+
|
193
|
+
|
194
|
+
# A unique id - even if you are unsaved!
|
195
|
+
def unique_id
|
196
|
+
id || @generated_dom_id || (@generated_dom_id = Time.now.to_f.to_s.gsub('.', '_'))
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
#getting audits
|
201
|
+
def audit_log
|
202
|
+
return (self.methods.include?('audits') ? self.audits : [])
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
private
|
208
|
+
|
209
|
+
def t(key, options = {})
|
210
|
+
self.class.translate(key, options)
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
def transfer_records(klass, objects, options = {})
|
215
|
+
record_ids = objects.flat_map { |o|
|
216
|
+
o.send(klass.name.underscore + '_ids')
|
217
|
+
}
|
218
|
+
unless record_ids.empty?
|
219
|
+
options[:foreign_key] ||= self.class.name.underscore + '_id'
|
220
|
+
update_options = options.except(:foreign_key)
|
221
|
+
update_options[options[:foreign_key]] = id
|
222
|
+
klass.where(id: record_ids).update_all(update_options)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|