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
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 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.
i'm having troubles with Devise Gem, i'm using the default recoverable methods, the links is being sent. The reset values (reset_password_sent_at) is saved in the database, but when i have to write down the new password and update it, gives this error
NoMethodError (undefined method `to_datetime' for nil:NilClass):
activesupport (4.0.2) lib/active_support/core_ext/date_time/calculations.rb:161:in `<=>'
activesupport (4.0.2) lib/active_support/core_ext/time/calculations.rb:286:in `compare_with_coercion'
activesupport (4.0.2) lib/active_support/time_with_zone.rb:214:in `<=>'
activerecord (4.0.2) lib/active_record/attribute_methods/dirty.rb:97:in `=='
activerecord (4.0.2) lib/active_record/attribute_methods/dirty.rb:97:in `!='
activerecord (4.0.2) lib/active_record/attribute_methods/dirty.rb:97:in `_field_changed?'
activerecord (4.0.2) lib/active_record/attribute_methods/dirty.rb:66:in `write_attribute'
activerecord (4.0.2) lib/active_record/attribute_methods/time_zone_conversion.rb:39:in `reset_password_sent_at='
devise (3.5.6) lib/devise/models/recoverable.rb:94:in `clear_reset_password_token'
devise (3.5.6) lib/devise/models/recoverable.rb:32:in `block (2 levels) in <module:Recoverable>'
activesupport (4.0.2) lib/active_support/callbacks.rb:377:in `_run__1626105923374900797__update__callbacks'
activesupport (4.0.2) lib/active_support/callbacks.rb:80:in `run_callbacks'
activerecord (4.0.2) lib/active_record/callbacks.rb:310:in `update_record'
activerecord (4.0.2) lib/active_record/timestamp.rb:70:in `update_record'
activerecord (4.0.2) lib/active_record/persistence.rb:477:in `create_or_update'
activerecord (4.0.2) lib/active_record/callbacks.rb:302:in `block in create_or_update'
activesupport (4.0.2) lib/active_support/callbacks.rb:393:in `_run__1626105923374900797__save__callbacks'
activesupport (4.0.2) lib/active_support/callbacks.rb:80:in `run_callbacks'
activerecord (4.0.2) lib/active_record/callbacks.rb:302:in `create_or_update'
activerecord (4.0.2) lib/active_record/persistence.rb:106:in `save'
activerecord (4.0.2) lib/active_record/validations.rb:51:in `save'
activerecord (4.0.2) lib/active_record/attribute_methods/dirty.rb:32:in `save'
activerecord (4.0.2) lib/active_record/transactions.rb:270:in `block (2 levels) in save'
activerecord (4.0.2) lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'
activerecord (4.0.2) lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `block in transaction'
activerecord (4.0.2) lib/active_record/connection_adapters/abstract/database_statements.rb:210:in `within_new_transaction'
activerecord (4.0.2) lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `transaction'
activerecord (4.0.2) lib/active_record/transactions.rb:209:in `transaction'
activerecord (4.0.2) lib/active_record/transactions.rb:323:in `with_transaction_returning_status'
activerecord (4.0.2) lib/active_record/transactions.rb:270:in `block in save'
activerecord (4.0.2) lib/active_record/transactions.rb:281:in `rollback_active_record_state!'
activerecord (4.0.2) lib/active_record/transactions.rb:269:in `save'
devise (3.5.6) lib/devise/models/recoverable.rb:48:in `reset_password'
devise (3.5.6) lib/devise/models/recoverable.rb:141:in `reset_password_by_token'
devise (3.5.6) app/controllers/devise/passwords_controller.rb:32:in `update'
debugging this its seems to be a problem with the reset_password_sent_at being nil when the password is reset (lib/devise/models/recoverable.rb:94:inclear_reset_password_token)
I've try to change my local time to the UTC stored but the problem isn't that. Any suggestion?
My solution for this was to upgrade my rails from 4.0.2 to 4.2.7. When i run the bundle install and update the gemfile dependencies now is working.
Upgrading devise from (3.5.6) to (4.2.0)
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