[RUBY] I want to make a specific model of ActiveRecord ReadOnly

What is provided in ActiveRecord only affects some behaviors I'm worried about leaks, but I'll have to do my best to make a module to seal it.

Place it around lib / autoload / active_record_read_only.rb

module ActiveRecordReadOnly
  extend ActiveSupport::Concern

  # ActiveRecord::Should be rolled back with a ReadOnlyRecord error
  #It's not necessary to move it in vain, so seal it
  included do
    before_save { self.class.raise_readonly! }
    before_create { self.class.raise_readonly! }
    before_update { self.class.raise_readonly! }
    before_destroy { self.class.raise_readonly! }
  end

  #Basic ReadOnly control
  def readonly?
    true
  end

  #Seal touch
  #This is not enough for the following reasons, but it is overwritten to match the judgment function with the actual behavior.
  def no_touching?
    true
  end

  #Seal touch
  # no_touching?If you just seal it with, it will not cause an error, so seal it directly
  def touch
    self.class.raise_readonly!
  end

  module ClassMethods
    # update_column and update_columns etc readonly?Block column specification processing without judgment
    def readonly_attributes
      attribute_names
    end

    # readonly?Since it is a single process without judgment, it is sealed directly
    def delete(_id)
      raise_readonly!
    end

    #Since it is a batch operation and no column is specified, it is sealed directly.
    def delete_all
      raise_readonly!
    end

    #Since it is a batch operation and no column is specified, it is sealed directly.
    def update_all(_attributes)
      raise_readonly!
    end

    def raise_readonly!
      raise ActiveRecord::ReadOnlyRecord,
            "#{name}.included ActiveRecordReadOnly"
    end
  end
end

Just include

class User < ApplicationRecord
  include ActiveRecordReadOnly
end

It's closed

[1] pry(main)> ActiveRecord::Base.logger = nil
=> nil
[2] pry(main)> User.first.destroy
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[3] pry(main)> User.first.update(code: 'test')
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[4] pry(main)> User.first.update_columns(code: 'test')
ActiveRecord::ActiveRecordError: code is marked as readonly
from /usr/local/bundle/gems/activerecord-6.0.0/lib/active_record/persistence.rb:947:in `verify_readonly_attribute'
[5] pry(main)> User.first.update_column(:code, 'test')
ActiveRecord::ActiveRecordError: code is marked as readonly
from /usr/local/bundle/gems/activerecord-6.0.0/lib/active_record/persistence.rb:947:in `verify_readonly_attribute'
[6] pry(main)> User.first.touch
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[7] pry(main)> User.create(code: 'test')
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[8] pry(main)> User.delete(1)
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[9] pry(main)> User.delete_all
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[10] pry(main)> User.update_all(code: 'test')
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'

[Additional supplement] Intention to block the callback

When applied to the model body, it was meaningless because it can be defined after the blockade It is assumed that it will be separated into the inheritance model for viewing as shown below.

class User < ApplicationRecord
  before_create -> { }
end

class ReadOnlyUser < User
  include ActiveRecordReadOnly
end

Recommended Posts

I want to make a specific model of ActiveRecord ReadOnly
I want to call a method of another class
I want to monitor a specific file with WatchService
Rails6 I want to make an array of values with a check box
[Ruby] I want to make a program that displays today's day of the week!
I want to make a list with kotlin and java!
I want to make a function with kotlin and java!
I tried to make a message function of Rails Tutorial extension (Part 1): Create a model
I tried to make a client of RESAS-API in Java
I want to recursively search for files under a specific directory
I want to make a button with a line break with link_to [Note]
I want to develop a web application!
I want to write a nice build.gradle
I want to make an ios.android app
I want to write a unit test!
[Controller] I want to retrieve the numerical value of a specific column from the DB (my memo)
I tried to make a parent class of a value object in Ruby
[Rails] I want to send data of different models in a form
I want to output the day of the week
Make a margin to the left of the TextField
I did Java to make (a == 1 && a == 2 && a == 3) always true
Set the time of LocalDateTime to a specific time
[Ruby] I want to do a method jump!
I want to var_dump the contents of the intent
I wanted to make (a == 1 && a == 2 && a == 3) true in Java
I want to simply write a repeating string
I want to design a structured exception handling
[Android] I want to make QA easier ... That's right! Let's make a debug menu!
I want to recursively get the superclass and interface of a certain class
How to make a factory with a model with polymorphic association
I was addicted to the record of the associated model
I want to use a little icon in Rails
How to make JavaScript work on a specific page
I want to know the answer of the rock-paper-scissors app
I want to display the name of the poster of the comment
I want to apply ContainerRelativeShape only to specific corners [SwiftUI]
I tried to make a login function in Java
I want to define a function in Rails Console
I want to add a reference type column later
I want to click a GoogleMap pin in RSpec
[IOS] To allow rotation of only a specific screen
I want to be aware of the contents of variables!
I want to return the scroll position of UITableView!
I want to connect to Heroku MySQL from a client
I want to create a generic annotation for a type
I want to add a delete function to the comment function
I want to go back to a specific VC by tapping the back button on the NavigationBar!
[Rails] I want to display the link destination of link_to in a separate tab
I want to fetch another association of the parent model from the intermediate table with has_many
[Java] I want to convert a byte array to a hexadecimal number
I want to find a relative path in a situation using Path
I tried to make a reply function of Rails Tutorial extension (Part 3): Corrected a misunderstanding of specifications
I want to convert characters ...
I want to implement a product information editing function ~ part1 ~
I want to expand the clickable part of the link_to method
I want to change the log output settings of UtilLoggingJdbcLogger
I tried to make the sample application into a microservice according to the idea of the book "Microservice Architecture".
I want to call a method and count the number
I just wanted to make a Reactive Property in Java
I tried using Hotwire to make Rails 6.1 scaffold a SPA
I want to create a form to select the [Rails] category