Class: Parse::Schema::Migration

Inherits:
Object
  • Object
show all
Defined in:
lib/parse/schema.rb

Overview

Represents a schema migration to be applied.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_class, diff, client: nil) ⇒ Migration

Returns a new instance of Migration.



387
388
389
390
391
# File 'lib/parse/schema.rb', line 387

def initialize(model_class, diff, client: nil)
  @model_class = model_class
  @diff = diff
  @client = client || Parse.client
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



385
386
387
# File 'lib/parse/schema.rb', line 385

def client
  @client
end

#diffObject (readonly)

Returns the value of attribute diff.



385
386
387
# File 'lib/parse/schema.rb', line 385

def diff
  @diff
end

#model_classObject (readonly)

Returns the value of attribute model_class.



385
386
387
# File 'lib/parse/schema.rb', line 385

def model_class
  @model_class
end

Instance Method Details

#apply!(dry_run: false) ⇒ Hash

Apply the migration to the server.

Parameters:

  • dry_run (Boolean) (defaults to: false)

    if true, only preview without applying

Returns:

  • (Hash)

    results of the migration



447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/parse/schema.rb', line 447

def apply!(dry_run: false)
  return { status: :skipped, message: "No migration needed" } unless needed?

  if dry_run
    return { status: :preview, operations: operations, preview: preview }
  end

  results = { status: :success, applied: [], errors: [] }

  # Create class if needed
  unless @diff.server_exists?
    schema = build_schema
    response = @client.create_schema(@model_class.parse_class, schema)
    if response.success?
      results[:applied] << { action: :create_class, class_name: @model_class.parse_class }
    else
      results[:errors] << { action: :create_class, error: response.error }
      results[:status] = :partial
    end
    return results
  end

  # Add missing fields
  @diff.missing_on_server.each do |name, type|
    field_name = @model_class.field_map[name].to_s
    field_schema = { "fields" => { field_name => field_definition(type) } }

    response = @client.update_schema(@model_class.parse_class, field_schema)
    if response.success?
      results[:applied] << { action: :add_field, field: field_name, type: type }
    else
      results[:errors] << { action: :add_field, field: field_name, error: response.error }
      results[:status] = :partial
    end
  end

  results[:status] = :failed if results[:applied].empty? && results[:errors].any?
  results
end

#needed?Boolean

Check if migration is needed.

A migration is needed when the class does not yet exist on the server, or when the server does not already cover every locally-defined field. Defined in terms of the one-way SchemaDiff#server_covers_local? rather than the strict bidirectional SchemaDiff#in_sync? so that a server which is a strict superset of the local model (extra server-only columns the migrator would never add) does not report a "needed" migration with zero operations.

Returns:

  • (Boolean)


403
404
405
# File 'lib/parse/schema.rb', line 403

def needed?
  !@diff.server_exists? || !@diff.server_covers_local?
end

#operationsArray<Hash>

Get the operations that would be performed.

Returns:



409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/parse/schema.rb', line 409

def operations
  ops = []

  unless @diff.server_exists?
    ops << { action: :create_class, class_name: @model_class.parse_class }
  end

  @diff.missing_on_server.each do |name, type|
    ops << {
      action: :add_field,
      field: @model_class.field_map[name].to_s,
      type: REVERSE_TYPE_MAP[type] || "String",
    }
  end

  ops
end

#previewString

Preview the migration without applying.

Returns:

  • (String)

    human-readable preview



429
430
431
432
433
434
435
436
437
438
439
440
441
442
# File 'lib/parse/schema.rb', line 429

def preview
  return "No migration needed" unless needed?

  lines = ["Migration for #{@model_class.parse_class}:"]
  operations.each do |op|
    case op[:action]
    when :create_class
      lines << "  CREATE CLASS #{op[:class_name]}"
    when :add_field
      lines << "  ADD FIELD #{op[:field]} (#{op[:type]})"
    end
  end
  lines.join("\n")
end