Как переопределить конфигурации рельсов в отношении множественных таблиц и столбцов в виде змеи - PullRequest
8 голосов
/ 04 ноября 2019

Итак, я создаю приложение, в котором у меня есть бэкэнд, написанный на Rails, и клиент, написанный на Vue с Amplify. Моя база данных MySQL, и я использую AWS AppSync с GraphQL в качестве источника данных (указывая на мою базу данных).

AWS Amplify имеет структуру, которая позволяет мне создавать схемы на основе имен таблиц и столбцовс помощью одной простой команды: amplify api add-graphql-datasource. Но поскольку я использую рельсовые миграции, моя база данных использует соглашения Rails: множественные таблицы со столбцами в виде змеи.

Теперь проблема в том, что схемы GraphQL все некрасивые и не используют правильные соглашения (единственное числоназвания для типов и входов, с подпорками в верблюжьей клетке). Пример:

Мой бэкэнд имеет следующую миграцию:

class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :posts do |t|
      t.belongs_to :site, null: false
      t.string :title
      t.string :url
      t.text :body

      t.timestamps
    end
  end
end

И сгенерированная для этого схема:

type posts {
  id: Int!
  site_id: Int!
  title: String
  url: String
  body: String
  created_at: AWSDateTime!
  updated_at: AWSDateTime!
}

type Query {
  getPosts(id: Int!): posts
  listPostss: [posts]
  // ...
}

schema {
  query: Query
  // ...
}

Не говоря уже об этом:

input CreatepostsInput {
  id: Int!
  site_id: Int!
  title: String
  url: String
  body: String
  created_at: AWSDateTime!
  updated_at: AWSDateTime!
}

Итак, AWS Amplify является новым, он не подходит как Rails, и, кроме того, я не нашел ни адаптера, ни преобразователя для решения проблемы в клиенте ... Я надеюсь найти способсправиться с этим в Rails.

Мне нужно иметь возможность полностью изменить соглашения Rails, не нарушая ничего: миграции, ассоциации, как управлять ассоциациями (create_xxx, build_xxx).

Это приложение действительноновый, так что я могу воссоздать все миграции с нуля.

Спасибо

1 Ответ

1 голос
/ 08 ноября 2019

Я вижу некоторые вещи, которые вы можете сделать:

Таблицы:

В своей миграции вы можете изменить имя таблицы, но теперь вам нужно разрешитьмодель знает, что такое имя таблицы с self.table_name.

# migration
class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :post do |t| # singular 'post'
      ...
    end
  end
end

#model
class Post
  self.table_name = "post" # i think you can also use a symbol :post
end

Атрибуты:

Необходимо избегать использования методов миграции Rails, которые следуютСоглашения Rails, такие как t.belongs_to или t.references или t.timestamps.

# migration
class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :post do |t|
      # do not use this below
      # t.belongs_to :site, null: false
      t.bigint :siteId, null: false
      t.string :title
      t.string :url
      t.text :body

      # do not use this below
      # t.timestamps
      t.datetime :createdAt, default: ->{'CURRENT_TIMESTAMP'}
      t.datetime :updatedAt, default: ->{'CURRENT_TIMESTAMP'}
    end
  end
end

Отношения:

Вам также необходимо обновить ваши отношения в ваших моделях

class Post
  belongs_to :site, foreign_key: 'siteId'
end

Дополнительную информацию можно найти в Rails API . Убедитесь, что вы проверили документацию для других методов отношений .

Метки времени:

Поскольку столбцы меток времени (created_at, updated_at)больше не ожидаемый ActiveRecord, вам может понадобиться переопределить ActiveRecord::Timestamp модуль , чтобы они продолжали работать так, как вы ожидаете. Один из самых простых вариантов - обновить ApplicationRecord или класс отдельной модели следующим образом:

class ApplicationRecord # or class Post
  before_create :set_timestamps
  before_save :set_timestamps

  private
  def set_timestamps
    self.createdAt = DateTime.current if self.new_record?
    self.updatedAt = DateTime.now
  end
end

Или этот другой параметр взят из https://stackoverflow.com/a/52276865/1845602

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  class << self
    private

    def timestamp_attributes_for_create
      super << 'my_created_at_column'
    end

    def timestamp_attributes_for_update
      super << 'my_updated_at_column'
    end
  end
end

Автоматически сгенерированные входы :

Я могу ошибаться, но кажется, что имя таблицы вводится во имя ввода, например Create<table>Input, поэтому, если это так, вы можете назвать свою таблицу Post вместо post.

input CreatepostsInput {
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...