reference | reverse | reason |
---|---|---|
Tenant.taggings |
NO | option :polymorphic not supported |
Tenant.tags |
NO | option :through not supported |
Tenant.providers |
Provider.tenant |
automatic |
Tenant.ext_management_systems |
ExtManagementSystem.tenant |
automatic |
Tenant.vm_or_templates |
VmOrTemplate.tenant |
automatic |
Tenant.vms |
NO | VmOrTemplate.tenant exists, but wrong parent class (want Vm ) |
Tenant.miq_templates |
NO | VmOrTemplate.tenant exists, but wrong parent class (want MiqTemplate ) |
Tenant.service_template_catalogs |
ServiceTemplateCatalog.tenant |
automatic |
Tenant.service_templates |
ServiceTemplate.tenant |
automatic |
Tenant.tenant_quotas |
TenantQuota.tenant |
automatic |
Tenant.miq_groups |
MiqGroup.tenant |
automatic |
Tenant.users |
NO | option :through not supported |
Tenant.ae_domains |
MiqAeDomain.tenant |
automatic |
Tenant.miq_requests |
MiqRequest.tenant |
automatic |
Tenant.miq_request_tasks |
MiqRequestTask.tenant |
automatic |
Tenant.services |
Service.tenant |
automatic |
Tenant.default_miq_group |
MiqGroup.tenant |
UNNEEDED: options[:inverse_of] |
Vm.snapshots |
Snapshot.vm_or_template |
automatic |
Vm.compliances |
NO | option :polymorphic not supported |
Vm.evm_owner |
NO | no reverse association User.vm_or_template (suggested values: vms , miq_templates) |
Vm.miq_group |
NO | no reverse association MiqGroup.vm_or_template (suggested values: vms , miq_templates) |
Vm.custom_attributes |
NO | option :polymorphic not supported |
Vm.miq_custom_attributes |
NO | scope not supported (CustomAttribute) |
Vm.ems_custom_attributes |
NO | scope not supported (CustomAttribute) |
Vm.miq_server |
NO | option :foreign_key not supported |
Vm.operating_system |
OperatingSystem.vm_or_template |
automatic |
Vm.hardware |
Hardware.vm_or_template |
automatic |
Vm.host |
NO | no reverse association Host.vm_or_template (suggested values: vms_and_templates , vms , miq_templates) |
Vm.ems_cluster |
NO | no reverse association EmsCluster.vm_or_template (suggested values: vms_and_templates , miq_templates , vms) |
Vm.storage |
NO | no reverse association Storage.vm_or_template (suggested values: vms_and_templates , miq_templates , vms , all_vms_and_templates , all_miq_templates , all_vms) |
Vm.repositories |
NO | option :through not supported |
Vm.storages |
NO | has_and_belongs_to_many not supported |
Vm.ext_management_system |
NO | option :foreign_key not supported |
Vm.miq_provision |
NO | MiqRequestTask.destination exists, but wrong parent class (want MiqProvision ) |
Vm.miq_provisions_from_template |
NO | MiqRequestTask.source exists, but wrong parent class (want MiqProvision ) |
Vm.miq_provision_vms |
NO | option :through not supported |
Vm.miq_provision_requests |
NO | MiqRequest.source exists, but wrong parent class (want MiqProvisionRequest ) |
Vm.guest_applications |
GuestApplication.vm_or_template |
automatic |
Vm.patches |
Patch.vm_or_template |
automatic |
Vm.accounts |
Account.vm_or_template |
automatic |
Vm.users |
NO | scope not supported (Account) |
Vm.groups |
NO | scope not supported (Account) |
Vm.system_services |
SystemService.vm_or_template |
automatic |
Vm.win32_services |
NO | scope not supported (SystemService) |
Vm.kernel_drivers |
NO | scope not supported (SystemService) |
Vm.filesystem_drivers |
NO | scope not supported (SystemService) |
Vm.linux_initprocesses |
NO | scope not supported (SystemService) |
Vm.filesystems |
NO | option :polymorphic not supported |
Vm.directories |
NO | scope not supported (Filesystem) |
Vm.files |
NO | scope not supported (Filesystem) |
Vm.scan_histories |
ScanHistory.vm_or_template |
automatic |
Vm.lifecycle_events |
LifecycleEvent.vm_or_template |
automatic |
Vm.advanced_settings |
NO | option :polymorphic not supported |
Vm.registry_items |
RegistryItem.vm_or_template |
automatic |
Vm.metrics |
NO | option :polymorphic not supported |
Vm.metric_rollups |
NO | option :polymorphic not supported |
Vm.vim_performance_states |
NO | option :polymorphic not supported |
Vm.storage_files |
StorageFile.vm_or_template |
automatic |
Vm.storage_files_files |
NO | scope not supported (StorageFile) |
Vm.ems_events |
NO | scope not supported (EmsEvent) |
Vm.ems_events_src |
NO | EventStream.vm_or_template exists, but wrong parent class (want EmsEvent ) |
Vm.ems_events_dest |
NO | option :foreign_key not supported |
Vm.policy_events |
NO | scope not supported (PolicyEvent) |
Vm.miq_events |
NO | EventStream.target exists, but wrong parent class (want MiqEvent ) |
Vm.miq_alert_statuses |
NO | option :polymorphic not supported |
Vm.miq_cim_instance |
NO | option :polymorphic not supported |
Vm.service_resources |
NO | option :polymorphic not supported |
Vm.direct_services |
NO | option :through not supported |
Vm.tenant |
NO | no reverse association Tenant.vm_or_template (suggested values: vm_or_templates , vms , miq_templates) |
Vm.taggings |
NO | option :polymorphic not supported |
Vm.tags |
NO | option :through not supported |
Vm.all_relationships |
NO | option :polymorphic not supported |
Vm.drift_states |
NO | option :polymorphic not supported |
Vm.first_drift_state |
NO | scope not supported (DriftState) |
Vm.last_drift_state |
NO | scope not supported (DriftState) |
Vm.first_drift_state_timestamp_rec |
NO | scope not supported (DriftState) |
Vm.last_drift_state_timestamp_rec |
NO | scope not supported (DriftState) |
Vm.vim_performance_operating_ranges |
NO | option :polymorphic not supported |
VmOrTemplate.snapshots |
Snapshot.vm_or_template |
automatic |
VmOrTemplate.compliances |
NO | option :polymorphic not supported |
VmOrTemplate.evm_owner |
NO | no reverse association User.vm_or_template (suggested values: vms , miq_templates) |
VmOrTemplate.miq_group |
NO | no reverse association MiqGroup.vm_or_template (suggested values: vms , miq_templates) |
VmOrTemplate.custom_attributes |
NO | option :polymorphic not supported |
VmOrTemplate.miq_custom_attributes |
NO | scope not supported (CustomAttribute) |
VmOrTemplate.ems_custom_attributes |
NO | scope not supported (CustomAttribute) |
VmOrTemplate.miq_server |
NO | option :foreign_key not supported |
VmOrTemplate.operating_system |
OperatingSystem.vm_or_template |
automatic |
VmOrTemplate.hardware |
Hardware.vm_or_template |
automatic |
VmOrTemplate.host |
NO | no reverse association Host.vm_or_template (suggested values: vms_and_templates , vms , miq_templates) |
VmOrTemplate.ems_cluster |
NO | no reverse association EmsCluster.vm_or_template (suggested values: vms_and_templates , miq_templates , vms) |
VmOrTemplate.storage |
NO | no reverse association Storage.vm_or_template (suggested values: vms_and_templates , miq_templates , vms , all_vms_and_templates , all_miq_templates , all_vms) |
VmOrTemplate.repositories |
NO | option :through not supported |
VmOrTemplate.storages |
NO | has_and_belongs_to_many not supported |
VmOrTemplate.ext_management_system |
NO | option :foreign_key not supported |
VmOrTemplate.miq_provision |
NO | MiqRequestTask.destination exists, but wrong parent class (want MiqProvision ) |
VmOrTemplate.miq_provisions_from_template |
NO | MiqRequestTask.source exists, but wrong parent class (want MiqProvision ) |
VmOrTemplate.miq_provision_vms |
NO | option :through not supported |
VmOrTemplate.miq_provision_requests |
NO | MiqRequest.source exists, but wrong parent class (want MiqProvisionRequest ) |
VmOrTemplate.guest_applications |
GuestApplication.vm_or_template |
automatic |
VmOrTemplate.patches |
Patch.vm_or_template |
automatic |
VmOrTemplate.accounts |
Account.vm_or_template |
automatic |
VmOrTemplate.users |
NO | scope not supported (Account) |
VmOrTemplate.groups |
NO | scope not supported (Account) |
VmOrTemplate.system_services |
SystemService.vm_or_template |
automatic |
VmOrTemplate.win32_services |
NO | scope not supported (SystemService) |
VmOrTemplate.kernel_drivers |
NO | scope not supported (SystemService) |
VmOrTemplate.filesystem_drivers |
NO | scope not supported (SystemService) |
VmOrTemplate.linux_initprocesses |
NO | scope not supported (SystemService) |
VmOrTemplate.filesystems |
NO | option :polymorphic not supported |
VmOrTemplate.directories |
NO | scope not supported (Filesystem) |
VmOrTemplate.files |
NO | scope not supported (Filesystem) |
VmOrTemplate.scan_histories |
ScanHistory.vm_or_template |
automatic |
VmOrTemplate.lifecycle_events |
LifecycleEvent.vm_or_template |
automatic |
VmOrTemplate.advanced_settings |
NO | option :polymorphic not supported |
VmOrTemplate.registry_items |
RegistryItem.vm_or_template |
automatic |
VmOrTemplate.metrics |
NO | option :polymorphic not supported |
VmOrTemplate.metric_rollups |
NO | option :polymorphic not supported |
VmOrTemplate.vim_performance_states |
NO | option :polymorphic not supported |
VmOrTemplate.storage_files |
StorageFile.vm_or_template |
automatic |
VmOrTemplate.storage_files_files |
NO | scope not supported (StorageFile) |
VmOrTemplate.ems_events |
NO | scope not supported (EmsEvent) |
VmOrTemplate.ems_events_src |
NO | EventStream.vm_or_template exists, but wrong parent class (want EmsEvent ) |
VmOrTemplate.ems_events_dest |
NO | option :foreign_key not supported |
VmOrTemplate.policy_events |
NO | scope not supported (PolicyEvent) |
VmOrTemplate.miq_events |
NO | EventStream.target exists, but wrong parent class (want MiqEvent ) |
VmOrTemplate.miq_alert_statuses |
NO | option :polymorphic not supported |
VmOrTemplate.miq_cim_instance |
NO | option :polymorphic not supported |
VmOrTemplate.service_resources |
NO | option :polymorphic not supported |
VmOrTemplate.direct_services |
NO | option :through not supported |
VmOrTemplate.tenant |
NO | no reverse association Tenant.vm_or_template (suggested values: vm_or_templates , vms , miq_templates) |
VmOrTemplate.taggings |
NO | option :polymorphic not supported |
VmOrTemplate.tags |
NO | option :through not supported |
VmOrTemplate.all_relationships |
NO | option :polymorphic not supported |
VmOrTemplate.drift_states |
NO | option :polymorphic not supported |
VmOrTemplate.first_drift_state |
NO | scope not supported (DriftState) |
VmOrTemplate.last_drift_state |
NO | scope not supported (DriftState) |
VmOrTemplate.first_drift_state_timestamp_rec |
NO | scope not supported (DriftState) |
VmOrTemplate.last_drift_state_timestamp_rec |
NO | scope not supported (DriftState) |
VmOrTemplate.vim_performance_operating_ranges |
NO | option :polymorphic not supported |
Host.ext_management_system |
NO | option :foreign_key not supported |
Host.ems_cluster |
NO | no reverse association EmsCluster.host (suggested values: hosts) |
Host.operating_system |
NO | no reverse association OperatingSystem.host |
Host.hardware |
Hardware.host |
automatic |
Host.vms_and_templates |
VmOrTemplate.host |
automatic |
Host.vms |
NO | VmOrTemplate.host exists, but wrong parent class (want Vm ) |
Host.miq_templates |
NO | VmOrTemplate.host exists, but wrong parent class (want MiqTemplate ) |
Host.storages |
NO | has_and_belongs_to_many not supported |
Host.switches |
Switch.host |
automatic |
Host.patches |
Patch.host |
automatic |
Host.system_services |
SystemService.host |
automatic |
Host.host_services |
NO | option :foreign_key not supported |
Host.metrics |
NO | option :polymorphic not supported |
Host.metric_rollups |
NO | option :polymorphic not supported |
Host.vim_performance_states |
NO | option :polymorphic not supported |
Host.ems_events |
NO | scope not supported (EmsEvent) |
Host.ems_events_src |
NO | EventStream.host exists, but wrong parent class (want EmsEvent ) |
Host.ems_events_dest |
NO | option :foreign_key not supported |
Host.policy_events |
NO | scope not supported (PolicyEvent) |
Host.guest_applications |
GuestApplication.host |
automatic |
Host.miq_events |
NO | EventStream.target exists, but wrong parent class (want MiqEvent ) |
Host.filesystems |
NO | option :polymorphic not supported |
Host.directories |
NO | scope not supported (Filesystem) |
Host.files |
NO | scope not supported (Filesystem) |
Host.accounts |
Account.host |
automatic |
Host.users |
NO | option :foreign_key not supported |
Host.groups |
NO | option :foreign_key not supported |
Host.advanced_settings |
NO | option :polymorphic not supported |
Host.miq_alert_statuses |
NO | option :polymorphic not supported |
Host.miq_cim_instance |
NO | option :polymorphic not supported |
Host.host_service_groups |
HostServiceGroup.host |
automatic |
Host.custom_attributes |
NO | option :polymorphic not supported |
Host.miq_custom_attributes |
NO | scope not supported (CustomAttribute) |
Host.ems_custom_attributes |
NO | scope not supported (CustomAttribute) |
Host.filesystems_custom_attributes |
NO | option :through not supported |
Host.taggings |
NO | option :polymorphic not supported |
Host.tags |
NO | option :through not supported |
Host.all_relationships |
NO | option :polymorphic not supported |
Host.drift_states |
NO | option :polymorphic not supported |
Host.first_drift_state |
NO | scope not supported (DriftState) |
Host.last_drift_state |
NO | scope not supported (DriftState) |
Host.first_drift_state_timestamp_rec |
NO | scope not supported (DriftState) |
Host.last_drift_state_timestamp_rec |
NO | scope not supported (DriftState) |
Host.vim_performance_operating_ranges |
NO | option :polymorphic not supported |
Host.authentications |
NO | option :polymorphic not supported |
Host.compliances |
NO | option :polymorphic not supported |
EmsCluster.taggings |
NO | option :polymorphic not supported |
EmsCluster.tags |
NO | option :through not supported |
EmsCluster.ext_management_system |
NO | option :foreign_key not supported |
EmsCluster.hosts |
Host.ems_cluster |
automatic |
EmsCluster.vms_and_templates |
VmOrTemplate.ems_cluster |
automatic |
EmsCluster.miq_templates |
NO | VmOrTemplate.ems_cluster exists, but wrong parent class (want MiqTemplate ) |
EmsCluster.vms |
NO | VmOrTemplate.ems_cluster exists, but wrong parent class (want Vm ) |
EmsCluster.metrics |
NO | option :polymorphic not supported |
EmsCluster.metric_rollups |
NO | option :polymorphic not supported |
EmsCluster.vim_performance_states |
NO | option :polymorphic not supported |
EmsCluster.policy_events |
NO | scope not supported (PolicyEvent) |
EmsCluster.miq_events |
NO | EventStream.target exists, but wrong parent class (want MiqEvent ) |
EmsCluster.drift_states |
NO | option :polymorphic not supported |
EmsCluster.first_drift_state |
NO | scope not supported (DriftState) |
EmsCluster.last_drift_state |
NO | scope not supported (DriftState) |
EmsCluster.first_drift_state_timestamp_rec |
NO | scope not supported (DriftState) |
EmsCluster.last_drift_state_timestamp_rec |
NO | scope not supported (DriftState) |
EmsCluster.all_relationships |
NO | option :polymorphic not supported |
EmsCluster.vim_performance_operating_ranges |
NO | option :polymorphic not supported |
=> true | ||
irb(main):002:0> |
Last active
January 14, 2016 17:58
-
-
Save kbrock/b764ff3fc1cb63c18d0d to your computer and use it in GitHub Desktop.
Active Record allows you to define relationships in 2 directions. But unfortunately, it is not always smart enough to detect when a relationship on one side is the same as the opposite direction. This aims to help you discover where and why rails is not helping you out.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Reason | |
def reason_inverse_name(src, ref) | |
# def inverse_name; delegate_reflection.send(:inverse_name); end | |
ref = ref.respond_to?(:delegate_reflection) ? ref.delegate_reflection : ref | |
if ref.options[:inverse_of] | |
# will this false positive a :through? | |
if ref.options[:inverse_of] == ref.send(:automatic_inverse_of) | |
"UNNEEDED: `options[:inverse_of]`" | |
else | |
"`options[:inverse_of]`" | |
end | |
else | |
reason_automatic_inverse_of(src, ref) | |
end | |
end | |
def reason_automatic_inverse_of(src, ref) | |
reason = reason_can_find_inverse_of_automatically?(src, ref, ref) | |
return reason if reason | |
inverse_name = ActiveSupport::Inflector.underscore(ref.options[:as] || ref.active_record.name.demodulize).to_sym | |
begin | |
reflection = ref.klass._reflect_on_association(inverse_name) | |
rescue NameError | |
# Give up: we couldn't compute the klass type so we won't be able | |
# to find any associations either. | |
return "cant compute #{ref.klass}.#{inverse_name}.klass" | |
end | |
reason_valid_inverse_reflection?(src, ref, reflection, "#{reflection.try(:active_record).try(:name) || ref.klass}.#{inverse_name}") | |
end | |
# return reason it is BAD | |
def reason_can_find_inverse_of_automatically?(src, ref, reflection) # inverse ( return value if failing) | |
case | |
when reflection.options[:inverse_of] == false | |
"detection disabled with `:inverse_of => false`" | |
when !ref.class::VALID_AUTOMATIC_INVERSE_MACROS.include?(reflection.macro) | |
"`#{ref.macro}` not supported" | |
when !(opts=ref.class::INVALID_AUTOMATIC_INVERSE_OPTIONS.select { |opt| reflection.options[opt] }).empty? | |
"option `:#{opts.join("`, `:")}` not supported" | |
when reflection.scope | |
# do default scopes even come into play? | |
"`scope` not supported (#{reflection.klass})#{" (there is a `default_scope`)" if reflection.klass.default_scopes.size > 0}" | |
end | |
end | |
def reason_valid_inverse_reflection?(src, ref, reflection, name) # inverse (return value if valid or not) | |
case | |
when !reflection | |
# would be nice to get all the STI ancestors | |
options = [ref.klass, ref.klass.base_class].uniq.flat_map do |k| | |
k.reflections.values.select { |r| | |
(r.klass.base_class rescue nil) == src.base_class | |
}.map(&:name) | |
end | |
possible = options.empty? ? "" : " (suggested values: `#{options.join("`, `")})`" | |
"no reverse association `#{name}`#{possible}" | |
when ref.klass.name != reflection.active_record.name | |
"`#{name}` exists, but wrong parent class (want `#{ref.klass.name}`)" | |
else | |
reason_can_find_inverse_of_automatically?(src, ref, reflection) # return value if valid or not | |
end | |
end | |
def reasons(*srcs) | |
srcs = [Tenant, Vm, VmOrTemplate, Host, EmsCluster] if srcs.empty? | |
puts "|reference|reverse|reason" | |
puts "|---------|-----|------" | |
srcs.each do |src| | |
src.reflections.values.each_with_index do |ref, i| | |
value = ref.send(:inverse_name) | |
why = reason_inverse_name(src, ref) | |
puts "|`#{src.name}.#{ref.name}`|#{value ? "`#{ref.klass.name}.#{value}`" : "**NO**"}|#{why || "automatic"}|" | |
end | |
end | |
nil | |
end | |
end | |
Reason.new.reasons(Tenant, Vm, VmOrTemplate, Host, EmsCluster) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment