Last Updated
Viewed 19 Times

I have an STI setup I'm using where all sti base classes get their core behavior from a module


module SingleTableInheritable
  extend ActiveSupport::Concern

  included do
    def self.inherited(subclass)
      subclass.class_eval do
        def method_missing(method_name, *args, &block)
          ... some stuff
          super
        end
      end

      super
    end
  end
end

I then have many classes inheriting from this module. The method missing mysteriously work on all but one

An example of a class where undefined methods get picked up by method_missing in the module

class DataModule < ApplicationRecord
  include SingleTableInheritable

  has_and_belongs_to_many :action_coordinates, class_name: "ActionCoordinates"
  has_and_belongs_to_many :datasets

  has_many :data_sub_modules

  belongs_to :interval, optional: true
  belongs_to :hardware_device, optional: true
end

And the class which never trigger the method missing on undefined_methods

class DataSubModule < ApplicationRecord
  include SingleTableInheritable

  belongs_to :data_module
end

The only thing I noticed as a possible explanation is that DataSubModule (the class that doesn't work) is the only table with a belongs_to connection to another STI table. All other connections are many to many and they all seem to get the correct behavior. But if I call the the relationships on the base classes it all works ie:

DataSubModule::Instance.first.data_module #this relationship works as normal
DataSubModule::Instance.first.some_undefined_method #this does not get picked up by the method missing
DataModule::Instance.first.some_undefined_method #this gets picked up by the method missing

I'm playing around with a microservice automation pipeline that builds out a bunch of templated code.

Currently, the pipeline code is automatically running via guard and generates a shell script to create databases, create new rails application and other types of assets.

I run ruby & rails within RbEnv and the script that I am executing works fine from the command line, it creates a brand new Rails 6 application.

But, when I run it from guard which has an existing Rails 5.2 environment Application, the new application is built as a Rails 5.2 app.

I have tried overriding certain settings, but it still picks up the environment that my code is running in.

When I run the script from the command line:

echo 'SHOULD CREATE A RAILS APP using VERSION 6.0.0 on RUBY 2.6.3'

gem install rails -v 6.0.0

echo 'rails -v'
rails -v

echo 'rbenv local'
rbenv local

echo 'rbenv version'
rbenv version

echo 'rbenv versions'
rbenv versions

rails _6.0.0_ new . -d postgresql --force --skip-action-mailer --skip-action-mailbox --skip-action-text --skip-spring --skip-test --skip-bundle --skip-webpack-install

I get the following output log

Successfully installed rails-6.0.0
1 gem installed
SHOULD CREATE A RAILS APP using VERSION 6.0.0 on RUBY 2.6.3
rails -v
Rails 6.0.0
rbenv local
2.6.3
rbenv version
2.6.3 (set by /Users/myname/dev/myapp/.ruby-version)
rbenv versions
  system
  2.4.1
  2.4.6
  2.5.3
* 2.6.3 (set by /Users/myname/dev/myapp/.ruby-version)

With following GEM file

ruby '2.6.3'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.0'
# Use postgresql as the database for Active Record
gem 'pg', '>= 0.18', '< 2.0'
# Use Puma as the app server

And confirmation via the last line that the application is Rails 6

remove  config/initializers/new_framework_defaults_6_0.rb

enter image description here

When I run the same script from ruby using variations on system and fork { exec { } }

    Dir.chdir File.dirname(output_file) do
      # fork { exec("bash #{output_file}") }
      system "bash #{output_file}"
      # system "/usr/local/bin/zsh #{output_file}"
    end

I get Rails 5.2

rails -v
Rails 5.2.3
rbenv local
rbenv: no local version configured for this directory
rbenv version
2.5.3 (set by RBENV_VERSION environment variable)
rbenv versions
  system
  2.4.1
  2.4.6
* 2.5.3 (set by RBENV_VERSION environment variable)
  2.6.3

enter image description here

Recently updated my Rails app to 6.0. When I run my tests I get the following deprecation warning from a scope on my Referral model:

DEPRECATION WARNING: Class level methods will no longer inherit scoping from `with_all_final_state_fulfillments` in Rails 6.1. To continue using the scoped relation, pass it into the block directly. To instead access the full set of models, as Rails 6.1 will, use `Referral.unscoped`. (called from block in <class:Referral> at /Users/home/workspace/APPNAME/app/models/referral.rb:60)

My Referral model scope in question is hacky, but written like this:

  scope :with_all_final_state_fulfillments, lambda {
    final_state_ids = Referral.with_fulfillment_in_final_state.pluck(:id).uniq
    not_final_state_ids = Referral.where(id: final_state_ids).with_fulfillment_not_in_final_state.pluck(:id).uniq

    id_list = final_state_ids - not_final_state_ids
    Referral.where(id: id_list)
  }

I've searched all around the internet for advice on how to fix this deprecation, including the Rails GitHub PR's making the change, but haven't found a clear English explanation anywhere.

How do I fix this deprecated scope for Rail 6.1?

I'm new to rails. So don't know how to follow the DRY method. lets dive into the question.

I have two method in my controller were I have followed the same code. So how can I reduce my code. In this two method only model name get difference. Please assist me

I need something like this

array = ['Userservice', 'Userschedule' ]
    array.each do |el|
        draft_info = el.find_by(user_id: 39, save_option: "publish")
        draft_info.delete if !draft_info.nil?
        @user_info = el.find_by(user_id: 39, save_option: "draft")
        el.create(@user_info.attributes.merge({:save_option => "publish", :id => el.maximum(:id).to_i.next }))
    end




def create_publish_user
    publish_user_schedule
    publish_user_service
end

def publish_user_service
 draft_service =  Userservice.where(user_id: current_user.id, save_option: "publish").delete_all
 user_service = Userservice.where(user_id: current_user.id, save_option: "draft")
 user_service.each { |ser|  
  Userservice.create(ser.attributes.merge({:save_option => "publish", :id => Userservice.maximum(:id).to_i.next }))
 }
end

def publish_user_schedule
 draft_schedule =  Userschedule.where(user_id: current_user.id, save_option: "publish").delete_all
 user_schedule = Userschedule.where(user_id: current_user.id, save_option: "draft")
 user_schedule.each { |sch|  
   Userschedule.create(sch.attributes.merge({:save_option => "publish", :id => Userschedule.maximum(:id).to_i.next }))
  }
end  

Similar Question 6 (1 solutions) : Rails: Circular dependency in connected STI classes

Similar Question 7 (1 solutions) : Creating the same model from multiple data sources

Similar Question 8 (2 solutions) : Using a private method with Single Table Inheritance

Similar Question 9 (1 solutions) : How many classes is too many? Rails STI

cc