39
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ActiveRecordでINNER JOINするとsaveできなくなる(解決策あり)

Last updated at Posted at 2012-12-21

ActiveRecordでクエリーを組み立てる時に、joinsメソッドを使ってINNER JOIN句を付けると、取ってきたレコードをsaveできなくなります。
その検証と、saveできるようにする、方法。

require 'logger'
require 'active_record'

# テーブル定義
class CreateShelves < ActiveRecord::Migration
  def change
    create_table :shelves
  end
end

class CreateBooks < ActiveRecord::Migration
  def change
    create_table :books do |t|
      t.integer :shelf_id
    end
  end
end

# モデル定義
class Shelf < ActiveRecord::Base
  has_many :books
end

class Book < ActiveRecord::Base
  belongs_to :shelf
end

# ActiveRecordのセットアップ
logger = Logger.new($stderr)
ActiveRecord::Base.logger = logger # SQLをログに出すようにする
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'

# テーブル作成
CreateShelves.new.change
CreateBooks.new.change

# レコード作成
shelf = Shelf.create
shelf.books << Book.new

# やっと本題
# これだとreadonlyになる
shelves = Shelf.joins(:books)
begin
  shelves.first.save
rescue => err
  logger.error "#{err.class} (#{err.message})" # => ActiveRecord::ReadOnlyRecord (ActiveRecord::ReadOnlyRecord)
end

# こうすればsaveできる
shelves = Shelf.joins(:books).readonly(false)
shelves.first.save # => true

save!じゃなくてsaveなのに例外を起こすからいやな感じですね。

39
37
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
39
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?