I have annoying problem with SHOW TABLES in my Rails 2.3.2 APP - it is slowing my APP very deep. The question is, how to get rid of SHOW TABLES usage and where it is used in Rails framework? From APP logs I can see that it is being used all the time.
Thank you!
config/environments/production.rb:
config.cache_classes = true
config.action_controller.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
"SHOW TABLES" is ORM-dependent SQL query, it fires with every action to provide classes reload in development mode. How much time does the query take?
I was seeing a similar problem in Rails 3.0 and was able to fix it using the gist pointed to from this issue. Looks like it's fixed in Rails 3.2.
I added ar_patch.rb to config/initializers with this code:
unless Rails.env.development?
require "active_record/connection_adapters/mysql2_adapter"
module ActiveRecord
module ConnectionAdapters
class Mysql2Adapter < AbstractAdapter
extend ActiveSupport::Memoizable
memoize :tables, :pk_and_sequence_for, :columns
end
end
end
end
Related
I have both lines:
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true
ActiveRecord::Base.verbose_query_logs = true
in my config/environments/development/rb
But in my development log the sql queries are logged like:
2022-08-10 08:35:18.536410 D [74:puma srv tp 004] (0.006ms) ActiveRecord -- Model Load -- { :sql => "SELECT ....", :binds => { .... }, :allocations => 1, :cached => true }
I have an N+1 queries issue to fix, but the information about which line in the code triggered the query is missing, so this is not helping me much.
I tried also using active-record-query-trace gem, with configuration:
if Rails.env.development?
ActiveRecordQueryTrace.enabled = true
ActiveRecordQueryTrace.level = :full
ActiveRecordQueryTrace.colorize = true # No colorization (default)
ActiveRecordQueryTrace.colorize = :light_purple
# Optional: other gem config options go here
end
but I see no changes at all in how queries are logged.
How can I enable the logging of the line triggering the query?
Thanks
If you want to know the reference point that made a DB query I used to use a gem called Marginalia. I use it in Rails 6 and it does exactaly what you are looking for.
From what I am reading Rails 7 includes this feature as a native feature (which is quite awesome I might add).
I found a link that talks about this:
Rails 7 includes Marginalia
Their example says:
# config/application.rb
module Saeloun
class Application < Rails::Application
config.active_record.query_log_tags_enabled = true
end
end
I use Rails 5.0.0, but for some reason belongs_to_required_by_default doesn't work!
Application was created as new rails 5 app
class Visit < ApplicationRecord
belongs_to :user
end
> v = Visit.new
> v.valid? # => true
it works only with optional: false option
class Visit < ApplicationRecord
belongs_to :user, optional: false
end
> v = Visit.new
> v.valid? # => false
but why doesn't work configuration:
Rails.application.config.active_record.belongs_to_required_by_default = true
Where are you putting it? Have confirmed it works by putting it in development.rb as config.active_record.belongs_to_required_by_default = true inside Rails.application.configure do.
If you want it for everything you can put it in application.rb under class Application < Rails::Application as config.active_record.belongs_to_required_by_default = true
I believe you'll find putting it in the initializers directory will have problems with the loading order.
EDIT FOR RAILS 5.1: Everything should work well on a default Rails 5.1 application. Just make sure config.load_defaults 5.1 is in your application.rb (reference).
OLD ANSWER FOR RAILS 5.0.x
It look like this is due to some gems that monkey patch activerecord incorrectly, according to this Rails issue https://github.com/rails/rails/issues/23589.
You may want to comment/uncomment them out in your Gemfile until you find the culprit.
After this tedious process, I found that for my latest project it was the gems ahoy_matey, cancancan and delayed_job_active_record that caused the problem (at the time of writing).
In the meantime Ropeney's answer works, although not ideal since the "official rails way" is to declare config.active_record.belongs_to_required_by_default = true in the new_framework_defaults.rb initializer, not in application.rb.
In case anyone is still having this issue, you can upgrade to Rails 5.1 to fix it. In Rails 5.1, config/initializers/new_framework_defaults.rbhas been removed and replaced with the line config.load_defaults 5.1 in application.rb. This line includes
active_record.belongs_to_required_by_default = true and the other options that were in new_framework_defaults.rb.
module myApp
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails
version.
config.load_defaults 5.1
See the end of this thread for more details: https://github.com/rails/rails/issues/23589.
active_record.belongs_to_required_by_default = true only works for FactoryBot.create() method. you will still get validation error of child records not present where you have used FactoryBot.build() method. Any idea why this is not working for build()? any workaround?
I am having two big problems with Active Admin
When I go to edit a user the encrypted password does not show so essentially i'm having to hack my own site and copy and paste another encrypted password in to the field to update the user - this is the same with create user.
The second issue is I cannot create a new user. When I go to create a user nothing happens. I don't get an error. The page just refreshes and the user does not save.
User.rb
ActiveAdmin.register User do
controller do
def permitted_params
params.permit!
end
end
end
I tried destroying my install of active admin and then I reinstalled it and generated the models again but same result. I'm using Rails 4.2.1 and Ruby 2.0.0.
gem 'activeadmin', github: 'activeadmin'
In development.rb
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load
# Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large
# number of complex assets.
config.assets.debug = true
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
# Adds additional error checking when serving assets at runtime.
# Checks for improperly declared sprockets dependencies.
# Raises helpful error messages.
config.assets.raise_runtime_errors = true
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end
I tried changing config.cache_classes = false to true but that does not work either.
I'm not sure what to do here. Any suggestions? I take it this is a bug. Hope it can be fixed. Thanks.
It appears you're permitted_params method in your app/admin/user.rb file is unconventional and could be causing you problems. You need to add them like this and also put in :encrypted_password if you want to be able to change/edit it ...
ActiveAdmin.register User do
permit_params :email, :password, :password_confirmation, :encrypted_password
...
end
I have a problem with my rails application. After an Update from Rails 3 to 4.
When I surf through the pages after starting the server in development mode everything is fine.
But after a single code change (even adding a space) every page request shows the following error.
Unable to autoload constant User, expected
/path/to/my/rails-app/app/models/user.rb to define it
The file lives exactly there and defines the class:
class User < ActiveRecord::Base
…
I tried many things with config.autoload_paths and config.eager_load_paths in application.rb but with no luck.
Deactivating spring did not help either.
Developing an app and having to restart the server after every single change seems so 90s.
$ rails -v
Rails 4.2.4
$ ruby -v
ruby 2.1.7p400 (2015-08-18 revision 51632) [x86_64-linux]
Some relevant configs:
development.rb
MyApp::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
# Do not eager load code on boot. This avoids loading your whole application
# just for the purpose of running a single test. If you are using a tool that
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
config.action_mailer.delivery_method = :test
config.action_mailer.default_url_options = {
host: 'localhost',
port: 3000
}
end
application.rb
module Serviceportal
class Application < Rails::Application
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
[… some asset precompile stuff …]
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = 'utf-8'
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += Dir["#{config.root}/app/mailers",
"#{config.root}/app/controllers/concerns",
"#{config.root}/app/models/concerns",
"#{config.root}/app/decorators/concerns",
"#{config.root}/lib",
"#{config.root}/lib/shared"
]
config.eager_load_paths += Dir["#{config.root}/app/mailers",
"#{config.root}/app/controllers/concerns",
"#{config.root}/app/models/concerns",
"#{config.root}/app/decorators/concerns",
"#{config.root}/lib",
"#{config.root}/lib/shared"]
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = 'Berlin'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
config.i18n.default_locale = :de
[… some SQL and active support stuff …]
config.action_controller.include_all_helpers = false
config.action_controller.action_on_unpermitted_parameters = :raise
# Do not swallow errors in after_commit/after_rollback callbacks.
config.active_record.raise_in_transactional_callbacks = true
end
end
Edit: The error mostly shows up in lib/auth/user_proxy.rb in the following function. Maybe this helps to narrow the range of possible causes.
def self.usertype_allowed?(type)
[ User, TempCustomer ].include? type.classify.safe_constantize rescue false
end
Edit 2: Stringify the class names in Edit 1 helped (thanks #Benjamin Sinclaire). But only leads to the next errors. I could also avoid using classes. But at the following error in app/controllers/concerns/security.rb there is nothing can change?
Unable to autoload constant User, expected
/path/to/my/rails-app/app/models/user.rb to define it
code:
def set_current_user
User.current = current_user
end
with current user saved in the Thread (code from /path/to/my/rails-app/app/models/user.rb
def self.current
Thread.current['current_user']
end
def self.current=(user)
Thread.current['current_user'] = user
end
Just to make it clear again: It works after server restart in development until I change some code somewhere.
1 See if you have any multiple-level class or module declaration done one one line and change them to be declared in several lines.
Instead of
class Parent::Sub::Child
end
Do
module Parent
module Sub
class Child
end
end
end
2 Check your model association definitions, and ensure you are never using constant. Use string instead.
Instead of
belongs_to :manager, class_name: User
Do
belongs_to :manager, class_name: 'User'
3 Just saw your edit. Can you refactor like this?
# I assume `type` is a string or such, so we can compare classes
# names instead of constants, and get rid of `safe_constantize`
def self.usertype_allowed?(type)
['User', 'TempCustomer'].include? type.classify rescue false
end
4 Not a good idea to serialize an active record object in the Thread storage. Change it to store the user id instead, like this:
def set_current_user
User.current = current_user.id
end
def self.current
Thread.current['current_user_id']
end
def self.current=(user_id)
Thread.current['current_user_id'] = user_id
end
You don't need include app/models/concerns and app/controllers/concerns in your autoload/ eagerload paths as they are included by default in Rails 4: https://signalvnoise.com/posts/3372-put-chubby-models-on-a-diet-with-concerns
Also make sure that your concerns are defined as modules, extend ActiveSupport::Concern and with the appropriate file name
#taggable.rb
module Taggable
extend ActiveSupport::Concern
end
Another cause of your problem might be that some modules/ classes in app/decorators/concerns, lib, lib/shared are using the User class
which is not loaded yet or some of it's dependencies are not loaded so try adding require_relative path_to_user.rb at the top of those files
-----Edit-------
Try adding at the top of lib/auth/user_proxy.rb
require_dependency 'app/models/user'
This way you'll remove any ambiguity in autoloading the User class and you won't mess around with Rails autoloading see more here: http://guides.rubyonrails.org/autoloading_and_reloading_constants.html#require-dependency , http://guides.rubyonrails.org/autoloading_and_reloading_constants.html#common-gotchas
Same problem but in an engine w/ namespaces. No issues in production or in development until a code-change / autoload.
The solution was to
checking for double definitions (there were none)
checking if the module nesting strictly follows rails conventions in the filesystem.
I've had myns under myengine/app/myns/subns/obj.rb but myns is being ignored as it is at the root of the app folder, so moving the myns folder into a subfolder myengine/app/lib/myns solved the issue.
Note: the rails error message was very explicit about the module nesting (while still pointing to the wrong .rb file in the filesystem) so look closely at the error. The error was 'Unable to autoload constant subns/obj.rb in .../myns/subns/obj.rb'. Rails suggesting the incorrect file-location (which exists) is misleading in this case.
During a Rails/Ruby Update I found time to look into this and finally found the cause.
The user class had an unloadable in it for years. That caused the problems since Rails 4. Now I removed this and found no issues after that.
Using Rails.cache.fetch like below is caching even in my development environment (with caching turned off):
#boat_features = Rails.cache.fetch("boat_features", expires_in: 10.minutes) do
BoatFeature.all
end
Has anyone run into this before?
That's normal. That sort of caching isn't turned off in development. In a previous app where this was a problem we used the memory store and then added a middleware that did Rails.cache.clear after every request.
Something like
config.middleware.use ClearCache
in development.rb
and then your ClearCache middleware should look something like
class ClearCache
def initialize(app)
#app = app
end
def call(env)
#app.call(env)
ensure
Rails.cache.clear
end
end
In Rails 3.2 there's also ActiveSupport::Cache::NullStore
I had the same problem. I worked around a lot then came up with this simple solution. In your development configuration file config/environments/development.rb add these settings
config.perform_caching = false
config.cache_store = :null_store