2015-06-30 15:10:22 +00:00
|
|
|
class Models
|
|
|
|
include ApplicationLib
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
get list of models
|
|
|
|
|
|
|
|
result = Models.all
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
{
|
2015-08-16 09:14:24 +00:00
|
|
|
Some::Classname1 => {
|
2015-09-27 21:01:45 +00:00
|
|
|
attributes: ['id', 'name', '...'],
|
|
|
|
reflections: ...model.reflections...,
|
|
|
|
table: 'some_classname1s',
|
2015-06-30 15:10:22 +00:00
|
|
|
},
|
2015-08-16 09:14:24 +00:00
|
|
|
Some::Classname2 => {
|
2015-06-30 15:10:22 +00:00
|
|
|
attributes: ['id', 'name', '...']
|
|
|
|
reflections: ...model.reflections...
|
2015-09-27 21:01:45 +00:00
|
|
|
table: 'some_classname2s',
|
2015-06-30 15:10:22 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.all
|
|
|
|
all = {}
|
|
|
|
dir = "#{Rails.root}/app/models/"
|
|
|
|
Dir.glob( "#{dir}**/*.rb" ) do |entry|
|
|
|
|
next if entry =~ /application_model/i
|
2015-07-03 16:56:27 +00:00
|
|
|
next if entry =~ %r{channel/}i
|
|
|
|
next if entry =~ %r{observer/}i
|
|
|
|
next if entry =~ %r{store/provider/}i
|
2015-06-30 15:10:22 +00:00
|
|
|
entry.gsub!(dir, '')
|
|
|
|
entry = entry.to_classname
|
|
|
|
model_class = load_adapter(entry)
|
|
|
|
next if !model_class
|
|
|
|
next if !model_class.respond_to? :new
|
2015-08-17 13:25:41 +00:00
|
|
|
next if !model_class.respond_to? :table_name
|
|
|
|
table_name = model_class.table_name # handle models where not table exists, pending migrations
|
|
|
|
next if !ActiveRecord::Base.connection.tables.include?(table_name)
|
2015-06-30 15:10:22 +00:00
|
|
|
model_object = model_class.new
|
|
|
|
next if !model_object.respond_to? :attributes
|
|
|
|
all[model_class] = {}
|
|
|
|
all[model_class][:attributes] = model_class.attribute_names
|
|
|
|
all[model_class][:reflections] = model_class.reflections
|
2015-09-27 21:01:45 +00:00
|
|
|
all[model_class][:table] = model_class.table_name
|
2015-07-06 00:33:43 +00:00
|
|
|
#puts model_class
|
2015-06-30 15:10:22 +00:00
|
|
|
#puts "rrrr #{all[model_class][:attributes]}"
|
2015-07-06 00:33:43 +00:00
|
|
|
#puts " #{model_class.attribute_names.inspect}"
|
2015-06-30 15:10:22 +00:00
|
|
|
end
|
|
|
|
all
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
2015-08-16 09:14:24 +00:00
|
|
|
get list of searchable models
|
|
|
|
|
|
|
|
result = Models.searchable
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
[Model1, Model2, Model3]
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.searchable
|
|
|
|
models = []
|
2016-06-30 20:04:48 +00:00
|
|
|
all.each { |model_class, _options|
|
2015-08-16 09:14:24 +00:00
|
|
|
next if !model_class
|
|
|
|
next if !model_class.respond_to? :search_preferences
|
|
|
|
models.push model_class
|
|
|
|
}
|
|
|
|
models
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
2015-06-30 15:10:22 +00:00
|
|
|
get reference list of a models
|
|
|
|
|
|
|
|
result = Models.references('User', 2)
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
{
|
|
|
|
'Some::Classname1' => {
|
2015-07-06 00:33:43 +00:00
|
|
|
attribute1: 12,
|
|
|
|
attribute2: 6,
|
2015-06-30 15:10:22 +00:00
|
|
|
},
|
|
|
|
'Some::Classname2' => {
|
2015-07-06 00:33:43 +00:00
|
|
|
updated_by_id: 12,
|
|
|
|
created_by_id: 6,
|
2015-06-30 15:10:22 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.references(object_name, object_id)
|
2016-06-06 06:34:15 +00:00
|
|
|
object_name = object_name.to_s
|
2015-07-06 00:33:43 +00:00
|
|
|
|
|
|
|
# check if model exists
|
2015-06-30 15:10:22 +00:00
|
|
|
object_model = load_adapter(object_name)
|
|
|
|
object_model.find(object_id)
|
2015-07-06 00:33:43 +00:00
|
|
|
|
2015-06-30 15:10:22 +00:00
|
|
|
list = all
|
2015-07-06 00:33:43 +00:00
|
|
|
references = {}
|
2015-06-30 15:10:22 +00:00
|
|
|
|
|
|
|
# find relations via attributes
|
2015-07-06 00:33:43 +00:00
|
|
|
ref_attributes = ["#{object_name.downcase}_id"]
|
|
|
|
|
|
|
|
# for users we do not define relations for created_by_id &
|
|
|
|
# updated_by_id - add it here directly
|
|
|
|
if object_name == 'User'
|
|
|
|
ref_attributes.push 'created_by_id'
|
|
|
|
ref_attributes.push 'updated_by_id'
|
|
|
|
end
|
2016-06-30 20:04:48 +00:00
|
|
|
list.each { |model_class, model_attributes|
|
2015-07-06 00:33:43 +00:00
|
|
|
if !references[model_class.to_s]
|
|
|
|
references[model_class.to_s] = {}
|
|
|
|
end
|
2015-07-03 16:51:22 +00:00
|
|
|
|
2015-07-06 00:33:43 +00:00
|
|
|
next if !model_attributes[:attributes]
|
2016-06-30 20:04:48 +00:00
|
|
|
ref_attributes.each { |item|
|
2015-07-03 16:51:22 +00:00
|
|
|
next if !model_attributes[:attributes].include?(item)
|
|
|
|
|
|
|
|
count = model_class.where("#{item} = ?", object_id).count
|
2016-01-16 10:05:04 +00:00
|
|
|
next if count.zero?
|
2015-07-06 00:33:43 +00:00
|
|
|
if !references[model_class.to_s][item]
|
|
|
|
references[model_class.to_s][item] = 0
|
|
|
|
end
|
2015-07-03 16:51:22 +00:00
|
|
|
Rails.logger.debug "FOUND (by id) #{model_class}->#{item} #{count}!"
|
2015-07-06 00:33:43 +00:00
|
|
|
references[model_class.to_s][item] += count
|
2015-06-30 15:10:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# find relations via reflections
|
2016-06-30 20:04:48 +00:00
|
|
|
list.each { |model_class, model_attributes|
|
2015-06-30 15:10:22 +00:00
|
|
|
next if !model_attributes[:reflections]
|
2016-06-30 20:04:48 +00:00
|
|
|
model_attributes[:reflections].each { |_reflection_key, reflection_value|
|
2015-07-03 16:51:22 +00:00
|
|
|
|
2015-06-30 15:10:22 +00:00
|
|
|
next if reflection_value.macro != :belongs_to
|
2015-07-06 00:33:43 +00:00
|
|
|
col_name = "#{reflection_value.name}_id"
|
|
|
|
next if ref_attributes.include?(col_name)
|
2015-07-03 16:51:22 +00:00
|
|
|
|
2015-06-30 15:10:22 +00:00
|
|
|
if reflection_value.options[:class_name] == object_name
|
2015-07-06 00:33:43 +00:00
|
|
|
count = model_class.where("#{col_name} = ?", object_id).count
|
2016-01-16 10:05:04 +00:00
|
|
|
next if count.zero?
|
2015-07-06 00:33:43 +00:00
|
|
|
if !references[model_class.to_s][col_name]
|
|
|
|
references[model_class.to_s][col_name] = 0
|
|
|
|
end
|
|
|
|
Rails.logger.debug "FOUND (by ref without class) #{model_class}->#{col_name} #{count}!"
|
|
|
|
references[model_class.to_s][col_name] += count
|
2015-06-30 15:10:22 +00:00
|
|
|
end
|
2015-07-03 16:51:22 +00:00
|
|
|
|
|
|
|
next if reflection_value.options[:class_name]
|
|
|
|
next if reflection_value.name != object_name.downcase.to_sym
|
|
|
|
|
2015-07-06 00:33:43 +00:00
|
|
|
count = model_class.where("#{col_name} = ?", object_id).count
|
2016-01-16 10:05:04 +00:00
|
|
|
next if count.zero?
|
2015-07-06 00:33:43 +00:00
|
|
|
if !references[model_class.to_s][col_name]
|
|
|
|
references[model_class.to_s][col_name] = 0
|
|
|
|
end
|
|
|
|
Rails.logger.debug "FOUND (by ref with class) #{model_class}->#{col_name} #{count}!"
|
|
|
|
references[model_class.to_s][col_name] += count
|
2015-06-30 15:10:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-06 00:33:43 +00:00
|
|
|
# cleanup, remove models with empty references
|
2016-06-30 20:04:48 +00:00
|
|
|
references.each { |k, v|
|
2015-07-06 00:33:43 +00:00
|
|
|
next if !v.empty?
|
|
|
|
references.delete(k)
|
2015-06-30 15:10:22 +00:00
|
|
|
}
|
2015-07-06 00:33:43 +00:00
|
|
|
|
2015-06-30 15:10:22 +00:00
|
|
|
references
|
|
|
|
end
|
|
|
|
|
2015-07-06 00:33:43 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
get reference total of a models
|
|
|
|
|
|
|
|
count = Models.references_total('User', 2)
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
count # 1234
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.references_total(object_name, object_id)
|
2015-07-06 01:12:36 +00:00
|
|
|
references = references(object_name, object_id)
|
2015-07-06 00:33:43 +00:00
|
|
|
total = 0
|
2016-06-30 20:04:48 +00:00
|
|
|
references.each { |_model, model_references|
|
|
|
|
model_references.each { |_col, count|
|
2015-07-06 00:33:43 +00:00
|
|
|
total += count
|
|
|
|
}
|
|
|
|
}
|
|
|
|
total
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
merge model references to other model
|
|
|
|
|
2015-07-06 06:22:17 +00:00
|
|
|
result = Models.merge('User', 2, 4711) # Object, object_id_of_primary, object_id_which_should_be_merged
|
2015-07-06 00:33:43 +00:00
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
true # false
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.merge(object_name, object_id_primary, object_id_to_merge, force = false)
|
|
|
|
|
|
|
|
# if lower x references to update, do it right now
|
|
|
|
if force
|
2015-07-06 01:12:36 +00:00
|
|
|
total = references_total(object_name, object_id_to_merge)
|
2015-07-06 00:33:43 +00:00
|
|
|
if total > 1000
|
2016-03-01 14:26:46 +00:00
|
|
|
raise "Can't merge object because object has more then 1000 (#{total}) references, please contact your system administrator."
|
2015-07-06 00:33:43 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-07-06 01:12:36 +00:00
|
|
|
# update references
|
|
|
|
references = references(object_name, object_id_to_merge)
|
2016-06-30 20:04:48 +00:00
|
|
|
references.each { |model, attributes|
|
2015-07-06 00:33:43 +00:00
|
|
|
model_object = Object.const_get(model)
|
2015-07-06 01:12:36 +00:00
|
|
|
|
|
|
|
# collect items and attributes to update
|
2015-07-06 00:33:43 +00:00
|
|
|
items_to_update = {}
|
2016-06-30 20:04:48 +00:00
|
|
|
attributes.each { |attribute, _count|
|
2015-07-06 01:12:36 +00:00
|
|
|
Rails.logger.debug "#{object_name}: #{model}.#{attribute}->#{object_id_to_merge}->#{object_id_primary}"
|
2016-06-30 20:04:48 +00:00
|
|
|
model_object.where("#{attribute} = ?", object_id_to_merge).each { |item|
|
2015-07-06 00:33:43 +00:00
|
|
|
if !items_to_update[item.id]
|
|
|
|
items_to_update[item.id] = item
|
|
|
|
end
|
|
|
|
items_to_update[item.id][attribute.to_sym] = object_id_primary
|
|
|
|
}
|
|
|
|
}
|
2015-07-06 01:12:36 +00:00
|
|
|
|
|
|
|
# update items
|
2015-07-06 06:22:17 +00:00
|
|
|
ActiveRecord::Base.transaction do
|
2016-06-30 20:04:48 +00:00
|
|
|
items_to_update.each { |_id, item|
|
2015-07-06 06:22:17 +00:00
|
|
|
item.save
|
|
|
|
}
|
|
|
|
end
|
2015-07-06 00:33:43 +00:00
|
|
|
}
|
|
|
|
true
|
|
|
|
end
|
2015-07-03 15:38:50 +00:00
|
|
|
end
|