I upgraded to Rails 5 and after starting the server the login forms must be loaded. Then this error occurs:
ArgumentError - invalid argument: nil.:
activerecord (5.0.0.1) lib/active_record/relation/spawn_methods.rb:36:in `merge'
activerecord (5.0.0.1) lib/active_record/scoping/default.rb:119:in `block (2 levels) in build_default_scope'
activerecord (5.0.0.1) lib/active_record/scoping/default.rb:117:in `block in build_default_scope'
activerecord (5.0.0.1) lib/active_record/scoping/default.rb:141:in `evaluate_default_scope'
activerecord (5.0.0.1) lib/active_record/scoping/default.rb:116:in `build_default_scope'
activerecord (5.0.0.1) lib/active_record/scoping/named.rb:33:in `default_scoped'
activerecord (5.0.0.1) lib/active_record/scoping/named.rb:28:in `all'
activerecord (5.0.0.1) lib/active_record/scoping.rb:24:in `scope_attributes'
activerecord (5.0.0.1) lib/active_record/scoping.rb:36:in `populate_with_current_scope_attributes'
activerecord (5.0.0.1) lib/active_record/scoping.rb:43:in `initialize_internals_callback'
activerecord (5.0.0.1) lib/active_record/core.rb:317:in `initialize'
activerecord (5.0.0.1) lib/active_record/inheritance.rb:65:in `new'
devise (4.2.0) app/controllers/devise/sessions_controller.rb:9:in `new'
That seems to come from Devise I think?
After searching I found someone with the same error:
Turns it it was a gem which behind the scenes was attempting to do default_scope { nil }, looks like someone implemented protection against that (since it shouldn't really work)
What should I do?
nil is no longer valid as merge parameter, since that method expect a parameter of class ActiveRecord_Relation.
This issue is related to this PR on Rails.
This is the resolution commit on rails.
To avoid this error:
check merge attribute before calling it on a relation, and append it only if it's not null.
or pass always a valid ActiveRecord_Relation to merge, for example <ARModel>.all instead of nil if the actual parameter is nil.
Related
I've switched over to multi-databases where I have a reader and writer instance. As Rails 6+ auto switches database instances based on the HTTP verb, this has introduced several issues as it relates to Devise. While I was able to resolve most of them, one that seems to still be lingering is when a user submits an HTTP GET request and Devise tries to initiate a DELETE statement into the database.
Since Rails is connected to the read-only database during the GET request from the user, the user experiences a 404 error because of Devise trying to delete the session record.
Here's an example of the error:
ActiveRecord::ReadOnlyError: Write query attempted while in readonly mode: DELETE FROM "sessions" WHERE "sessions"."id" = $1
from activerecord (7.0.2.4) lib/active_record/connection_adapters/abstract_adapter.rb:120:in `check_if_write_query'
from activerecord (7.0.2.4) lib/active_record/connection_adapters/postgresql_adapter.rb:742:in `execute_and_clear'
from activerecord (7.0.2.4) lib/active_record/connection_adapters/postgresql/database_statements.rb:71:in `exec_delete'
from activerecord (7.0.2.4) lib/active_record/connection_adapters/abstract/database_statements.rb:181:in `delete'
from activerecord (7.0.2.4) lib/active_record/connection_adapters/abstract/query_cache.rb:22:in `delete'
from activerecord (7.0.2.4) lib/active_record/persistence.rb:530:in `_delete_record'
from activerecord (7.0.2.4) lib/active_record/persistence.rb:1043:in `_delete_row'
from activerecord (7.0.2.4) lib/active_record/persistence.rb:1039:in `destroy_row'
from activerecord (7.0.2.4) lib/active_record/counter_cache.rb:176:in `destroy_row'
from activerecord (7.0.2.4) lib/active_record/locking/optimistic.rb:121:in `destroy_row'
from activerecord (7.0.2.4) lib/active_record/persistence.rb:681:in `destroy'
from activerecord (7.0.2.4) lib/active_record/callbacks.rb:439:in `block in destroy'
from activesupport (7.0.2.4) lib/active_support/callbacks.rb:99:in `run_callbacks'
from activesupport (7.0.2.4) lib/active_support/callbacks.rb:929:in `_run_destroy_callbacks'
from activerecord (7.0.2.4) lib/active_record/callbacks.rb:439:in `destroy'
from activerecord (7.0.2.4) lib/active_record/transactions.rb:294:in `block in destroy'
from activerecord (7.0.2.4) lib/active_record/transactions.rb:354:in `block in with_transaction_returning_status'
from activerecord (7.0.2.4) lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
from activesupport (7.0.2.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
from activesupport (7.0.2.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
from activesupport (7.0.2.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
from activesupport (7.0.2.4) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
...
I just simply need to wrap wherever this is being initiated around this block:
ActiveRecord::Base.connected_to(role: :writing) do
# Devise method that calls DELETE on session needs to be here.
end
Is there a way to "intercept" or "wrap" this session delete call around the above method?
When the Rails app calls current_user it tries to detect the data from sessions table. Now, if the session is expired it will try to delete the record and since the call to the URL will be GET call, the app will use read only db. Now to make this work you will need to put the code of that uses the current_user session variable inside the code you mentioned above.
Need the below code to handle expired user sessions.
Add below in user.rb or in the model file with which the devise has been used.
# Implemneted this method since the automatic expiration of user session was raising read only db error
Warden::Manager.before_logout do |user, auth, opts|
ActiveRecord::Base.connected_to(role: :writing) do
auth.request.session.destroy
end
end
I spend few hours trying to find solution of my problem, but lost any hope to understood what i am done wrong.
Rails 4.2.6
my model:
app/models/component.rb
class Component < ActiveRecord::Base
validates :name, presence: true,
uniqueness: true,
forbid_changing: true #TODO [VS] Fix custom validator autoload
validates :label, presence: true,
uniqueness: true
end
my validator:
class ForbidChangingValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if record.send "#{attribute}_changed?".to_sym
record.errors[attribute] << options[:message] || t(:changing_forbidden)
end
end
end
when try reload the page i got error:
Unknown validator: 'ForbidChangingValidator'
ArgumentError - Unknown validator: 'ForbidChangingValidator':
activemodel (4.2.6) lib/active_model/validations/validates.rb:120:in `rescue in block in validates'
activemodel (4.2.6) lib/active_model/validations/validates.rb:117:in `block in validates'
activemodel (4.2.6) lib/active_model/validations/validates.rb:113:in `validates'
app/models/component.rb:6:in `<class:Component>'
app/models/component.rb:1:in `<top (required)>'
activesupport (4.2.6) lib/active_support/dependencies.rb:457:in `block in load_file'
activesupport (4.2.6) lib/active_support/dependencies.rb:647:in `new_constants_in'
activesupport (4.2.6) lib/active_support/dependencies.rb:456:in `load_file'
activesupport (4.2.6) lib/active_support/dependencies.rb:354:in `require_or_load'
activesupport (4.2.6) lib/active_support/dependencies.rb:494:in `load_missing_constant'
activesupport (4.2.6) lib/active_support/dependencies.rb:184:in `const_missing'
activesupport (4.2.6) lib/active_support/inflector/methods.rb:261:in `block in constantize'
activesupport (4.2.6) lib/active_support/inflector/methods.rb:259:in `constantize'
activesupport (4.2.6) lib/active_support/core_ext/string/inflections.rb:66:in `constantize'
repositor (0.6.0) lib/repositor/active_record.rb:6:in `initialize'
but when i am trying to call this validator from console i got:
!! #<ArgumentError: A copy of Component has been removed from the module tree but is still active!>
I found a lot of messages about thig issue, but can't to resolve mine.
Please, help somebody....
I found the issue. It's about naming policy. It strange ways rails try inflect the validator name.
I renamed my validator to ForbidChangesValidator and file also.
Everything goes great.
Thx all for attention.
Custom validations using using ActiveModel::EachValidator need to be declared in the root namespace or "core" autoload paths (however you want to define these directories).
For example:
(YES means will work and NO means won't work)
app/validations => YES since it is a new dir off of app/ it qualifies for root namespace
app/models => YES since it is a core directory
app/models/concerns => YES since it is a core directory
app/models/validations => NO Requires name spacing since it is a child directory off a core one.
Restarting the server fixed the issue for me, since everything else was right in place
Make sure you defined ForbidChangingValidator at app/validators/forbid_changing_validator.rb and add the configuration to:
config/application.rb
# add custom validators path
config.autoload_paths += %W["#{config.root}/app/validators/"]
All:
I am working on a project using the Ruby-on-Rails Framework. This project was initially based on Rails 4.0.9. I did a Brakeman Vulnerability Scan and I got n "Medium" level issue report that 4.0.9 is prone to DoS attack so I upgraded to 4.2.3.
But after the upgrade, I first got an error about "tzinfo" Data Source not found so I included the tzinfo-data gem with the platforms specification. That done, then my DB Queries using ActiveRecord Model starts failing whenever I do a method call on the results from the query.
CODE:
query = ['SELECT id, firstname, lastname, status, code FROM giftcard_orders WHERE phone = ? AND description LIKE ? ', phone, '%'+search]
#users = User.find_by_sql(query)
if #users.count > 0
#users.each do |user|
user[:code] = user[:code].do_decrypt
end
end
But immediately after the find_by_sql, I get some errors as below:
Completed 500 Internal Server Error in 685ms (ActiveRecord: 0.0ms)
*
NoMethodError (undefined method `type' for "int identity(10)":String):
activerecord (4.2.3) lib/active_record/attribute_methods/time_zone_conversion.rb:64:in `create_time_zone_conversion_attribute?'
activerecord (4.2.3) lib/active_record/attribute_methods/time_zone_conversion.rb:53:in `inherited'
org/jruby/RubyProc.java:290:in `call'
org/jruby/RubyProc.java:271:in `call'
activerecord (4.2.3) lib/active_record/attribute_decorators.rb:61:in `matching'
org/jruby/RubyArray.java:2468:in `select'
activerecord (4.2.3) lib/active_record/attribute_decorators.rb:60:in `matching'
activerecord (4.2.3) lib/active_record/attribute_decorators.rb:56:in `decorators_for'
activerecord (4.2.3) lib/active_record/attribute_decorators.rb:47:in `apply'
activerecord (4.2.3) lib/active_record/attribute_decorators.rb:29:in `add_user_provided_columns'
org/jruby/RubyArray.java:2399:in `collect'
org/jruby/RubyArray.java:2412:in `map'
activerecord (4.2.3) lib/active_record/attribute_decorators.rb:28:in `add_user_provided_columns'
activerecord (4.2.3) lib/active_record/attributes.rb:93:in `columns'
activerecord (4.2.3) lib/active_record/attributes.rb:98:in `columns_hash'
C:0:in `columns_hash'
activerecord (4.2.3) lib/active_record/relation/query_methods.rb:1067:in `arel_columns'
org/jruby/RubyArray.java:2399:in `collect'
org/jruby/RubyArray.java:2412:in `map'
activerecord (4.2.3) lib/active_record/relation/query_methods.rb:1066:in `arel_columns'
activerecord (4.2.3) lib/active_record/relation/query_methods.rb:1059:in `build_select'
activerecord (4.2.3) lib/active_record/relation/query_methods.rb:878:in `build_arel'
activerecord (4.2.3) lib/active_record/relation/query_methods.rb:858:in `arel'
activerecord (4.2.3) lib/active_record/relation/calculations.rb:210:in `perform_calculation'
activerecord (4.2.3) lib/active_record/relation/calculations.rb:127:in `calculate'
activerecord (4.2.3) lib/active_record/relation/calculations.rb:42:in `count'
activerecord (4.2.3) lib/active_record/relation.rb:268:in `empty?'
activerecord (4.2.3) lib/active_record/relation.rb:278:in `any?'
*
The method ActiveRecord::Base.find_by_sql has been deprecated for this Rails version:
http://apidock.com/rails/ActiveRecord/Base/find_by_sql/class
You should use ActiveRecord::Querying.find_by_sql as an alternative.
http://apidock.com/rails/ActiveRecord/Querying/find_by_sql
UPDATE
I am not really sure about your error, but I recommend you to:
See what happens with a simple query example, like select id FROM giftcard_orders,
Use directly the module:
ActiveRecord::Querying.find_by_sql(['select id FROM giftcard_orders'])
If this doesn't work, try to check that the find_by_sql method is called. Be careful with this:
$> bundle open activerecord go to lib/activerecord/querying.rb and put something to show you that is really using it (maybe a rails logger or a pry)
https://github.com/rails/rails/blob/v4.2.3/activerecord/lib/active_record/querying.rb
If you suspect is an ActiveRecord bug, open an issue on the github Rails repository:
https://github.com/rails/rails/issues
I would like to name my controller ESCsController, ESC being the acronym in question. I found the rails inflection docs which describe a way in which to accomplish this.
http://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html
Note: Acronyms that are passed to pluralize will no longer be recognized, since the acronym will not occur as a delimited unit in the pluralized result. To work around this, you must specify the pluralized form as an acronym as well:
acronym 'API'
camelize(pluralize('api')) #=> 'Apis'
acronym 'APIs'
camelize(pluralize('api')) #=> 'APIs'
I created my controller and models after adding this to environment.rb
ActiveSupport::Inflector.inflections { |i|
i.acronym 'ESC'
i.acronym 'ESCs'
}
Tested in the console these work perfectly. 'ESC'.pluralize() returns ESCs and 'ESCs'.singularize() returns ESC as expected
Controllers and models were generated through rails generate model ESC and rails generate controller ESCs respectively. This created escs_controller.rb and the model esc.rb as expected.
In my routes.rb I used to have
resources :ESCs, path: '/parts/escs'
which returned this error: 'ESCs' is not a supported controller name. This can lead to potential routing problems. See http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use
I ended up changing it to:
resources :ESCs, controller: 'escs', path: '/parts/escs'
However, now whenever I try and visit a page I get a circular dependency error:
Circular dependency detected while autoloading constant EscsController
Anyone know what's going on? It looks like whatever is trying to load the controller isn't seeing that it should be ESCsController and not EscsController. I'm new to rails so this could be a simple problem...
I'm using Rails 4.0.2
Here's the relevant part of the full stack trace.
activesupport (4.0.2) lib/active_support/dependencies.rb:461:in `load_missing_constant'
activesupport (4.0.2) lib/active_support/dependencies.rb:184:in `const_missing'
activesupport (4.0.2) lib/active_support/inflector/methods.rb:226:in `const_get'
activesupport (4.0.2) lib/active_support/inflector/methods.rb:226:in `block in constantize'
activesupport (4.0.2) lib/active_support/inflector/methods.rb:224:in `each'
activesupport (4.0.2) lib/active_support/inflector/methods.rb:224:in `inject'
activesupport (4.0.2) lib/active_support/inflector/methods.rb:224:in `constantize'
activesupport (4.0.2) lib/active_support/dependencies.rb:535:in `get'
activesupport (4.0.2) lib/active_support/dependencies.rb:566:in `constantize'
actionpack (4.0.2) lib/action_dispatch/routing/route_set.rb:76:in `controller_reference'
actionpack (4.0.2) lib/action_dispatch/routing/route_set.rb:66:in `controller'
actionpack (4.0.2) lib/action_dispatch/routing/route_set.rb:44:in `call'
actionpack (4.0.2) lib/action_dispatch/journey/router.rb:71:in `block in call'
actionpack (4.0.2) lib/action_dispatch/journey/router.rb:59:in `each'
actionpack (4.0.2) lib/action_dispatch/journey/router.rb:59:in `call'
actionpack (4.0.2) lib/action_dispatch/routing/route_set.rb:680:in `call'
Try moving code that adds the new inflections from environment.rb to config/initializers/inflections.rb then reload the server. Also, you don't need to specify a controller option for your route, just make it resources :escs, path: '/parts/escs' and it shall work fine.
I am trying to store a value in the session using the below code in my rails application
session[:key] = value
And i get the below error
TypeError (no _dump_data is defined for class Proc):
activesupport (3.2.9) lib/active_support/message_verifier.rb:53:in `dump'
activesupport (3.2.9) lib/active_support/message_verifier.rb:53:in `generate'
actionpack (3.2.9) lib/action_dispatch/middleware/cookies.rb:300:in `[]='
actionpack (3.2.9) lib/action_dispatch/middleware/session/cookie_store.rb:67:in `set_cookie'
rack (1.4.1) lib/rack/session/abstract/id.rb:330:in `commit_session'
rack (1.4.1) lib/rack/session/abstract/id.rb:206:in `context'
rack (1.4.1) lib/rack/session/abstract/id.rb:200:in `call'
actionpack (3.2.9) lib/action_dispatch/middleware/cookies.rb:341:in `call'
activerecord (3.2.9) lib/active_record/query_cache.rb:64:in `call'
activerecord (3.2.9) lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in `call'
actionpack (3.2.9) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (3.2.9) lib/active_support/callbacks.rb:405:in `
Any help is highly appreciated.
Your value is either a Proc or has s Proc nested inside of it somewhere. Procs and lambdas cannot be serialized/marshaled/dumped because they are closures. Closures depend on what is in memory at the time they are created, and therefore cannot be unserialized correctly later.
See this answer.
I'm not sure what I will be doing in my case, it looks like I will have to figure out a way to accomplish my task without relying on Procs.
What is this value? Is it a complicated object? An active record instance maybe?
I had the same problem trying to put an FourSquare client object into the session.
I've changed to create a new instance every time, instead of recovering from session, and it worked ok.
In my case, we were caching an ActiveRecord model and that model had an # variable that contained a lambda function. That was causing the issue.
Have you considered use Rack::Session::Pool instead of plain enable :sessions? Rack::Sessions::Pool allows for local storage of unserialisable objects, while storing the ID to the object in the cookie so it can be retrieved.
I used it to retain a(n) (unserialisable) database connection across Sinatra routes.
From http://www.getlaura.com/how-to-enable-sessions-with-sinatra/
require 'sinatra/base'
require 'customer.rb'
class SinatraApp < Sinatra::Base
use Rack::Session::Pool
get '/welcome' do
name = session[:customer].name
"Hello, #{name}!"
end
post '/:name' do
session[:customer] = Customer.new(params[:name])
redirect '/welcome'
end
end