LoginSignup
4
4

More than 5 years have passed since last update.

ActiveRecordでMySQLのviewに対してinsertする

Posted at

はじめに

ActiveRecordでMySQLのviewにinsertをかけようとした時に困ったのでメモ

viewを使うように設定する

users テーブルから view_users というviewを作り、ActiveRecordから参照するように設定する

CREATE VIEW view_users AS SELECT * from users;
class User < ActiveRecord::Base
  self.primary_key = :id
  self.table_name = "view_users"
end

createしたinstanceのidが0になる

pry(main) > User.create(name: 'hoge')
=> #<User: 0x007fc91201c150
 id: 0,
 name: "hoge",
 created_at: Sun, 10 Jan 2016 13:23:03 UTC +00:00,
 updated_at: Sun, 10 Jan 2016 13:23:03 UTC +00:00>

どこでidを設定しているか

def _create_record(attribute_names = self.attribute_names)
  attributes_values = arel_attributes_with_values_for_create(attribute_names)

  new_id = self.class.unscoped.insert attributes_values
  self.id ||= new_id if self.class.primary_key

  @new_record = false
  id
end

primary_key が存在する、かつ self.id がセットされていない場合に id が設定される
この id は、 LAST_INSERT_ID() が設定される

そもそもインスタンス初期化時に id = 0 となっている

pry(main) > User.new(name: 'hoge')
=> #<User: 0x007fc90f201db0
 id: 0,
 name: "hoge",
 created_at: Sun, 10 Jan 2016 13:23:03 UTC +00:00,
 updated_at: Sun, 10 Jan 2016 13:23:03 UTC +00:00>

MySQLのデフォルト値が0になっている

オリジナルのテーブルの id の定義は default null となっているが、viewでは default 0 となっている

root@localhost [paynote_development] > desc users;
+--------------------+--------------+------+-----+---------+----------------+
| Field              | Type         | Null | Key | Default | Extra          |
+--------------------+--------------+------+-----+---------+----------------+
| id                 | int(11)      | NO   | PRI | NULL    | auto_increment |
| name               | varchar(255) | YES  |     | NULL    |                |
| created_at         | datetime     | NO   |     | NULL    |                |
| updated_at         | datetime     | NO   |     | NULL    |                |
+--------------------+--------------+------+-----+---------+----------------+
10 rows in set (0.00 sec)
root@localhost [paynote_development] > desc view_users;
+--------------------+--------------+------+-----+---------+-------+
| Field              | Type         | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| id                 | int(11)      | NO   |     | 0       |       |
| name               | varchar(255) | YES  |     | NULL    |       |
| created_at         | datetime     | NO   |     | NULL    |       |
| updated_at         | datetime     | NO   |     | NULL    |       |
+--------------------+--------------+------+-----+---------+-------+
10 rows in set (0.00 sec)

解決法

綺麗な解決法か分からないが、インスタンス生成時に id を修正すれば良い

class User < ActiveRecord::Base
  self.primary_key = :id
  self.table_name = "view_users"
  after_initialize :fix_id

  def fix_id
    self.id = nil if self.id == 0
  end
end
4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4