Как вставить данные, только если они соответствуют определенному условию из одной таблицы в другую в Rails? - PullRequest
0 голосов
/ 16 мая 2018

Я в некотором роде новичок в SQL и миграциях в целом, так что, возможно, мой подход здесь совершенно неправильный, но терпите меня;)

У меня есть модель Company, которая имеет атрибуты для рассылки SMTPконфигурации (например, smtp_address и smtp_port), которые являются необязательными.

Однако теперь мне нужна моя модель User, чтобы иметь возможность иметь конфигурацию SMTP, поэтому я создал модель SMTPConfiguration с атрибутами address, port и полиморфная ассоциация с smtpable.Эта модель будет принадлежать модели «Пользователь» или «Компания»

. Теперь я хотел бы перенести данные, которые у меня уже есть в таблице компаний, в таблицу конфигураций SMTP, что звучит довольно просто, за исключением того, что яхотите создать новую конфигурацию SMTP ТОЛЬКО в том случае, если в компании действительно установлены smtp_address и smtp_port.Если smtp_address и smtp_port отсутствуют, у Компании не должно быть соответствующей SMTPConfiguration.

Это было бы довольно легко сделать, используя условия Ruby и ActiveRecord, но из того, что я прочитал, вставляя строки по отдельностиActiveRecord может быть очень длинным для больших баз данных, поэтому гораздо лучше использовать сырой SQL.Оказывается, я отстой в SQL :(.

Я немного искал в StackOverFlow, и, используя this и this , я придумал что-то вроде

execute <<-SQL
  INSERT INTO smtp_configurations (address, port, smtpable_id)
  SELECT (c.smtp_address, c.smtp_port, c.id)
  FROM companies c
  WHERE c.smtp_address <> NULL
SQL

Это не сработает, поскольку не устанавливает created_at, updated_at и smtpable_type, но, если честно, у меня нет идей. Может ли activerecord-import? gem какой-нибудь пользы?

Я использую Rails 5.1.4 и Postgres 10.3

1 Ответ

0 голосов
/ 16 мая 2018

Попробуйте следующий код в вашей миграции :

created_at = Time.current.to_s(:db)
insert_clause = <<-SQL
  INSERT INTO smtp_configurations(
    smtpable_id,
    smtpable_type,
    address,
    port,
    created_at,
    updated_at
  )
  SELECT
    c.id,
    'Company',
    c.smtp_address,
    c.smtp_port,
    '#{created_at}',
    '#{created_at}'
  FROM companies c
  WHERE (c.smtp_address IS NOT NULL) AND (c.port IS NOT NULL)
SQL

execute(insert_clause)

ОБНОВЛЕНО : Изменен код для простых Rails.

...