From 42c411b66064163a92703e30b91ec8dbb462437c Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 29 Nov 2025 10:38:25 -0800 Subject: [PATCH] Use upstream version of has_json --- Gemfile | 2 +- Gemfile.lock | 4 +- app/models/account.rb | 2 +- .../active_record_schematized_json.rb | 79 ------------------- 4 files changed, 4 insertions(+), 83 deletions(-) delete mode 100644 lib/rails_ext/active_record_schematized_json.rb diff --git a/Gemfile b/Gemfile index 5de9f88..f63b7ff 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" git_source(:github) { |repo| "https://github.com/#{repo}.git" } # Rails -gem "rails", github: "rails/rails", branch: "main" +gem "rails", github: "rails/rails", ref: "7727f43d38bf1783550e7a47207a9548e34a2c25" # branch: "main" gem "ostruct" gem "benchmark" diff --git a/Gemfile.lock b/Gemfile.lock index 1fe1464..d4ea7f8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -26,8 +26,8 @@ GIT GIT remote: https://github.com/rails/rails.git - revision: 690ec8898318b8f50714e86676353ebe1551261e - branch: main + revision: 7727f43d38bf1783550e7a47207a9548e34a2c25 + ref: 7727f43d38bf1783550e7a47207a9548e34a2c25 specs: actioncable (8.2.0.alpha) actionpack (= 8.2.0.alpha) diff --git a/app/models/account.rb b/app/models/account.rb index 2da750c..239c9fc 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -2,5 +2,5 @@ class Account < ApplicationRecord include Joinable has_one_attached :logo - has_settings restrict_room_creation_to_administrators: false + has_json :settings, schema: { restrict_room_creation_to_administrators: false }, delegate: true end diff --git a/lib/rails_ext/active_record_schematized_json.rb b/lib/rails_ext/active_record_schematized_json.rb deleted file mode 100644 index a5380ab..0000000 --- a/lib/rails_ext/active_record_schematized_json.rb +++ /dev/null @@ -1,79 +0,0 @@ -module ActiveRecord - class SchematizedJson - def initialize(schema, data:) - @schema, @data = schema, data - update_data_with_schema_defaults - end - - def assign_data_with_type_casting(new_data) - new_data.each { |k, v| public_send "#{k}=", v } - end - - private - def method_missing(method_name, *args, **kwargs) - key = method_name.to_s.remove(/(\?|=)/) - - if @schema.key? key.to_sym - if method_name.ends_with?("?") - @data[key].present? - elsif method_name.ends_with?("=") - value = args.first - @data[key] = lookup_schema_type_for(key).cast(value) - else - @data[key] - end - else - super - end - end - - def respond_to_missing?(method_name, include_private = false) - @schema.key?(method_name.to_s.remove(/[?=]/).to_sym) || super - end - - def lookup_schema_type_for(key) - type_or_default_value = @schema[key.to_sym] - - case type_or_default_value - when :boolean, :integer, :string - ActiveModel::Type.lookup(type_or_default_value) - when TrueClass, FalseClass - ActiveModel::Type.lookup(:boolean) - when Integer - ActiveModel::Type.lookup(:integer) - when String - ActiveModel::Type.lookup(:string) - else - raise "Only boolean, integer, or strings are allowed as JSON schema types" - end - end - - def update_data_with_schema_defaults - @data.reverse_merge!(@schema.to_h { |k, v| [ k.to_s, v.is_a?(Symbol) ? nil : v ] }) - end - end - - class Base - class << self - def has_json(delegate: false, **schemas) - schemas.each do |name, schema| - define_method(name) { ActiveRecord::SchematizedJson.new(schema, data: self[name]) } - define_method("#{name}=") { |data| public_send(name).assign_data_with_type_casting(data) } - - schema.keys.each do |schema_key| - define_method(schema_key) { public_send(name).public_send(schema_key) } - define_method("#{schema_key}?") { public_send(name).public_send("#{schema_key}?") } - define_method("#{schema_key}=") { |value| send(name).public_send("#{schema_key}=", value) } - end if delegate - - # Ensures default values are set before saving - before_save -> { send(name) } - end - end - - def has_settings(schema) - has_json settings: schema, delegate: true - end - end - end -end