class Avo::Fields::BelongsToField

def can_create?(final_target_resource = target_resource)

- target resource's policy allow creation (UserPolicy in this example)
- `can_create: true` option is present
Only can create when:
field :user, as: :belongs_to, can_create: true
def can_create?(final_target_resource = target_resource)
  @can_create && final_target_resource.authorization.authorize_action(:create, raise_exception: false)
end

def database_id

def database_id
  # If the field is a polymorphic value, return the polymorphic_type as key and pre-fill the _id in fill_field.
  return :"#{polymorphic_as}_type" if polymorphic_as.present?
  foreign_key
rescue
  id
end

def database_value

def database_value
  target_resource.id
rescue
  nil
end

def default_name

def default_name
  return polymorphic_as.to_s.humanize if polymorphic_as.present?
  super
end

def field_label

What the user sees in the text field
def field_label
  label
end

def field_value

The value
def field_value
  value.send(database_value)
rescue
  nil
end

def fill_field(record, key, value, params)

def fill_field(record, key, value, params)
  return record unless record.methods.include? key.to_sym
  if polymorphic_as.present?
    valid_model_class = valid_polymorphic_class params[:"#{polymorphic_as}_type"]
    record.send(:"#{polymorphic_as}_type=", valid_model_class)
    # If the type is blank, reset the id too.
    id_from_param = params["#{polymorphic_as}_id"]
    if valid_model_class.blank? || id_from_param.blank?
      record.send(:"#{polymorphic_as}_id=", nil)
    else
      record_id = target_resource(record:, polymorphic_model_class: value.safe_constantize).find_record(id_from_param).id
      record.send(:"#{polymorphic_as}_id=", record_id)
    end
  else
    record_id = value.blank? ? value : target_resource(record:).find_record(value).id
    record.send(:"#{key}=", record_id)
  end
  record
end

def foreign_key

def foreign_key
  @foreign_key ||= if polymorphic_as.present?
    polymorphic_as
  elsif @record.present?
    get_model_class(@record).reflections[@relation_method].foreign_key
  elsif @resource.present? && @resource.model_class.reflections[@relation_method].present?
    @resource.model_class.reflections[@relation_method].foreign_key
  end
end

def form_field_label

def form_field_label
  "#{id}_id"
end

def get_model_class(record)

def get_model_class(record)
  if record.nil?
    @resource.model_class
  elsif record.instance_of?(Class)
    record
  else
    record.class
  end
end

def get_record

def get_record
  @record || @resource.record
end

def id_input_foreign_key

def id_input_foreign_key
  if is_polymorphic?
    "#{foreign_key}_id"
  else
    foreign_key
  end
end

def index_link_to_record

def index_link_to_record
  if @link_to_record.present?
    get_record
  else
    value
  end
end

def index_link_to_resource

def index_link_to_resource
  if @link_to_record.present?
    @resource
  else
    target_resource
  end
end

def initialize(id, **args, &block)

def initialize(id, **args, &block)
  args[:placeholder] ||= I18n.t("avo.choose_an_option")
  super(id, **args, &block)
  @searchable = args[:searchable] == true
  @polymorphic_as = args[:polymorphic_as]
  @types = args[:types]
  @relation_method = id.to_s.parameterize.underscore
  @allow_via_detaching = args[:allow_via_detaching] == true
  @attach_scope = args[:attach_scope]
  @polymorphic_help = args[:polymorphic_help]
  @target = args[:target]
  @use_resource = args[:use_resource] || nil
  @can_create = args[:can_create].nil? ? true : args[:can_create]
  @link_to_record = args[:link_to_record].present? ? args[:link_to_record] : false
  @link_to_child_resource = args[:link_to_child_resource]
end

def is_polymorphic?

def is_polymorphic?
  polymorphic_as.present?
rescue
  false
end

def label

def label
  return if target_resource.blank?
  target_resource.new(record: value)&.record_title
end

def options

def options
  values_for_type
end

def polymorphic_form_field_label

def polymorphic_form_field_label
  "#{id}_type"
end

def reflection

Get the model reflection instance
def reflection
  reflection_for_key(id)
rescue
  nil
end

def reflection_for_key(key)

def reflection_for_key(key)
  get_model_class(get_record).reflections[key.to_s]
rescue
  nil
end

def relation_model_class

def relation_model_class
  @resource.model_class
end

def target_resource(record: @record, polymorphic_model_class: value&.class)

def target_resource(record: @record, polymorphic_model_class: value&.class)
  @target_resource ||= if use_resource.present?
    use_resource
  elsif is_polymorphic?
    if polymorphic_model_class.present?
      get_resource_by_model_class(polymorphic_model_class)
    else
      return nil
    end
  else
    reflection_key = polymorphic_as || id
    reflection_object = record.class.reflect_on_association(reflection_key)
    if (link_to_child_resource || @resource&.link_to_child_resource) && value.present?
      get_resource_by_model_class(value.class.to_s)
    elsif reflection_object.klass.present?
      get_resource_by_model_class(reflection_object.klass.to_s)
    elsif reflection_object.options[:class_name].present?
      get_resource_by_model_class(reflection_object.options[:class_name])
    else
      App.get_resource_by_name reflection_key
    end
  end
end

def to_permitted_param

def to_permitted_param
  if polymorphic_as.present?
    return [:"#{polymorphic_as}_type", :"#{polymorphic_as}_id"]
  end
  foreign_key.to_sym
end

def type_input_foreign_key

def type_input_foreign_key
  if is_polymorphic?
    "#{foreign_key}_type"
  end
end

def valid_polymorphic_class(possible_class)

def valid_polymorphic_class(possible_class)
  types.find do |type|
    type.to_s == possible_class.to_s
  end
end

def value

def value
  if is_polymorphic?
    # Get the value from the pre-filled association record
    super(polymorphic_as)
  else
    # Get the value from the pre-filled association record
    super(@relation_method)
  end
end

def values_for_type(model = nil)

def values_for_type(model = nil)
  resource = target_resource
  resource = Avo.resource_manager.get_resource_by_model_class model if model.present?
  query = resource.query_scope
  if attach_scope.present?
    query = Avo::ExecutionContext.new(target: attach_scope, query: query, parent: get_record).handle
  end
  query.all.limit(Avo.configuration.associations_lookup_list_limit).map do |record|
    [resource.new(record: record).record_title, record.to_param]
  end.tap do |options|
    options << t("avo.more_records_available") if options.size == Avo.configuration.associations_lookup_list_limit
  end
end