I keep getting the error ArgumentError: wrong number of arguments (0 for 1) for my default_scope which is default_scope { where("#{table_name}.tenant_id IS NULL") }
It keeps giving me this error and I don't understand why. I have the default scope in my users model.
Update:
Error output if using rails console:
ArgumentError: wrong number of arguments (0 for 1)
from /home/evan/Apps/demo-application/app/models/user.rb:18:in `hash'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/scoping.rb:64:in `value_for'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activesupport-4.0.4/lib/active_support/per_thread_registry.rb:40:in `public_send'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activesupport-4.0.4/lib/active_support/per_thread_registry.rb:40:in `block in method_missing'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/scoping/default.rb:123:in `ignore_default_scope?'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/scoping/default.rb:134:in `evaluate_default_scope'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/scoping/default.rb:110:in `build_default_scope'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/relation.rb:554:in `with_default_scope'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/relation.rb:582:in `exec_queries'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/relation.rb:471:in `load'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/relation.rb:220:in `to_a'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.4/lib/active_record/relation.rb:573:in `inspect'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/railties-4.0.4/lib/rails/commands/console.rb:90:in `start'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/railties-4.0.4/lib/rails/commands/console.rb:9:in `start'
from /home/evan/.rvm/gems/ruby-2.0.0-p195/gems/railties-4.0.4/lib/rails/commands.rb:62:in `<top (required)>'
from bin/rails:4:in `require'
The hash is in my user model as below.
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.hash(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.hash(User.new_remember_token)
end
Error output if using rails server:
ArgumentError - wrong number of arguments (0 for 1):
activerecord (4.0.4) lib/active_record/scoping.rb:70:in `set_value_for'
activesupport (4.0.4) lib/active_support/per_thread_registry.rb:40:in `block in method_missing'
activerecord (4.0.4) lib/active_record/scoping/default.rb:127:in `ignore_default_scope='
activerecord (4.0.4) lib/active_record/scoping/default.rb:140:in `ensure in evaluate_default_scope'
activerecord (4.0.4) lib/active_record/scoping/default.rb:140:in `evaluate_default_scope'
activerecord (4.0.4) lib/active_record/scoping/default.rb:110:in `build_default_scope'
activerecord (4.0.4) lib/active_record/relation.rb:554:in `with_default_scope'
activerecord (4.0.4) lib/active_record/relation.rb:582:in `exec_queries'
activerecord (4.0.4) lib/active_record/relation.rb:471:in `load'
activerecord (4.0.4) lib/active_record/relation.rb:220:in `to_a'
activerecord (4.0.4) lib/active_record/relation/finder_methods.rb:316:in `find_take'
activerecord (4.0.4) lib/active_record/relation/finder_methods.rb:66:in `take'
activerecord (4.0.4) lib/active_record/relation/finder_methods.rb:49:in `find_by'
activerecord (4.0.4) lib/active_record/querying.rb:6:in `find_by'
app/helpers/sessions_helper.rb:16:in `current_user'
app/helpers/sessions_helper.rb:19:in `signed_in?'
And the relevant rails methods:
def ignore_default_scope? # :nodoc:
ScopeRegistry.value_for(:ignore_default_scope, self)
end
def ignore_default_scope=(ignore) # :nodoc:
ScopeRegistry.set_value_for(:ignore_default_scope, self, ignore)
end
You should avoid overwriting Ruby core methods like Object#hash, also considering that Object#hash is an essential method in Ruby. From the docs:
Generates a Fixnum hash value for this object. This function must have
the property that a.eql?(b) implies a.hash == b.hash.
The hash value is used along with eql? by the Hash class to determine
if two objects reference the same hash key. Any hash value that
exceeds the capacity of a Fixnum will be truncated before being used.
The hash value for an object may not be identical across invocations
or implementations of ruby. If you need a stable identifier across
ruby invocations and implementations you will need to generate one
with a custom method.
If you really have to overwrite core methods you should guarantee their functionality and do not change their arguments: you will get unexpected behaviours all over your app otherwise, like the error you're referring.
I think that you have not such a variable or method as table_name
I think this will work:
table name = "users"
default_scope { where("#{table_name}.tenant_id IS NULL") }
Also it is cleaner to use callable objects for scopes (they are waiting for it), so it is better to use lambda here:
table name = "users"
default_scope ->{ where("#{table_name}.tenant_id IS NULL") }
# or old syntax:
default_scope lambda { where("#{table_name}.tenant_id IS NULL") }
Related
I'm using Rails 5.0.5 with Devise 4.3.0 for authentication. This app has been running smoothly for months, until I added a 'type'=>'string' attribute to my User model and attempted to create a new user. Submitting the form gives me a 500 internal server error. In this example, the User.type = 'hunter'.
NameError - wrong constant name hunter:
activesupport (5.0.5) lib/active_support/inflector/methods.rb:268:in `const_get'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:268:in `block in constantize'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `each'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `inject'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `constantize'
activesupport (5.0.5) lib/active_support/dependencies.rb:583:in `get'
activesupport (5.0.5) lib/active_support/dependencies.rb:614:in `constantize'
activerecord (5.0.5) lib/active_record/inheritance.rb:177:in `find_sti_class'
activerecord (5.0.5) lib/active_record/inheritance.rb:209:in `subclass_from_attributes'
activerecord (5.0.5) lib/active_record/inheritance.rb:55:in `new'
devise (4.3.0) lib/devise/models/registerable.rb:20:in `new_with_session'
app/models/user.rb:58:in `new_with_session'
user.rb:
def self.new_with_session(params, session)
if session['devise.user_attributes']
new(session['devise.user_attributes']) do |user|
user.attributes = params
user.valid?
end
else
super
end
end
Is Rails think this attribute value is a ClassName?? Can't seem to figure this one out. Any help greatly appreciated.
ActiveRecord uses the type column for Single Table Inheritance (STI) by default and the type value is expected to name a class. Presumably you don't have a hunter class so you get a confusing NameError from deep inside the guts of ActiveRecord.
From the fine manual:
inheritance_column()
Defines the name of the table column which will store the class name on single-table inheritance situations.
The default inheritance column name is type, which means it's a reserved word inside Active Record. To be able to use single-table inheritance with another column name, or to use the column type in your own model for something else, you can set inheritance_column:
self.inheritance_column = 'zoink'
Either rename your type column to something else or tell ActiveRecord to use some other column name for STI:
class User < ApplicationRecord
self.inheritance_column = 'there_is_no_sti_here' # Or whatever you're not using for a column name.
end
Using self.inheritance_column = nil also works.
If you're doing this a lot then you could make it declarative by adding a concern:
module STISuppression
extend ActiveSupport::Concern
included do
self.inheritance_column = nil
end
end
and then say things like:
class SomeModel < ApplicationRecord
include STISuppression
end
Same effect but it makes it clear what you're up to.
so how is that possible?
I have a Module, that puts a Ruby Object at the end of the renderd page in a nice structured HTML. So i recurse through the given object and build the HTML output. The following is an excerpt of the code where the error is thrown.
EDIT:(had a copy error in code)
o=some object
nicer=if o.respond_to?(:empty?) and o.empty?
add_class='empty'
'empty ' + class_name
else
case o
when TrueClass then
"TRUE"
when FalseClass then
"FALSE"
when Array
#some more when's
the error thrown: undefined method 'empty?' for #Journey::Routes:0x123456
the object (o) it self is ActionDispatch::Routing::RouteSet
again: how is that possible?
EDIT: Stack: (there is the bad one ...)
actionpack (3.2.13) lib/action_dispatch/routing/route_set.rb:366:in `empty?'
lib/tech_draw.rb:90:in `format_nice'
lib/tech_draw.rb:101:in `block in format_nice'
lib/tech_draw.rb:100:in `each'
lib/tech_draw.rb:100:in `map'
lib/tech_draw.rb:100:in `format_nice'
lib/tech_draw.rb:124:in `block in format_nice'
lib/tech_draw.rb:123:in `map'
lib/tech_draw.rb:123:in `format_nice'
lib/tech_draw.rb:13:in `block in say'
lib/tech_draw.rb:13:in `map'
lib/tech_draw.rb:13:in `say'
lib/tech_draw.rb:13:in `map'
lib/tech_draw.rb:6:in `say'
app/controllers/home_controller.rb:131:in `any_page'
actionpack (3.2.13) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
...
How is that possible? Easy:
class Thing
def respond_to? *args
true
end
end
o = Thing.new
o.respond_to?(:empty?) and o.empty?
# => NoMethodError: undefined method `empty?' for #<Thing:0x00000100ae2558>
Although why is it happening in this case is another matter.
ActionDispatch::Routing::RouteSet#empty? appears to call empty? on routes object. Assuming this object is an instance of Journey::Routes that would explain the error, as Journey::Routes doesn’t have an empty? method. (In current Rails versions Journey is part of Rails itself, but in Rails 3.2 it is separate).
I don’t why this is happening in your case though.
I want to show first users with last_request >= 1.day.ago and then add the rest users
def self.default_scope
where("last_request >= ?", 1.day.ago) + where("last_request < ? OR last_request is null", 1.day.ago)
end
This code raises that error:
undefined method `merge' for []:Array
How could I do that?
UPDATE
Error stack
NoMethodError - undefined method `merge' for #<Array:0xd16ba90>:
activerecord (3.2.13) lib/active_record/relation.rb:503:in `with_default_scope'
activerecord (3.2.13) lib/active_record/relation.rb:167:in `exec_queries'
activerecord (3.2.13) lib/active_record/relation.rb:160:in `block in to_a'
activerecord (3.2.13) lib/active_record/explain.rb:34:in `logging_query_plan'
activerecord (3.2.13) lib/active_record/relation.rb:159:in `to_a'
will_paginate (3.0.5) lib/will_paginate/active_record.rb:127:in `block in to_a'
will_paginate (3.0.5) lib/will_paginate/collection.rb:96:in `create'
will_paginate (3.0.5) lib/will_paginate/active_record.rb:126:in `to_a'
UPDATE2
I am using rails_admin, datetime field ordering is not working correctly
1)Order by ascending
2)Order by descending
In your particular case you can combine scopes to one with
default_scope where('last_request >= :time OR (last_request < :time OR last_request IS NULL)', time: 1.day.ago).order('last_request DESC')
UPD
That is not ActiveRecord or RailsAdmin issue, more info
ORDER BY ASC with Nulls at the Bottom
Rails: Order with nulls last
I have an Active Record model object called Event, which has many event_things. I want to be able to duplicate the event, so that it gets a new id. I'm using Rails 3.2 and in rails console am able to successfully call
event_copy = event.dup
event_copy.save
However, I also want to duplicate each of the Event's event_things.
copy = event_thing.dup
copy.event_id = event_copy.id
copy.save
But that gives me this error stack:
NoMethodError: undefined method `yaml' for nil:NilClass
from /Users/Ed/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/psych.rb:204:in `dump_stream'
from /Users/Ed/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/psych/core_ext.rb:35:in `psych_y'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:143:in `attribute_change'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `block in changes'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `map'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `changes'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/attribute_methods/dirty.rb:23:in `save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:241:in `block (2 levels) in save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:208:in `transaction'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:241:in `block in save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:252:in `rollback_active_record_state!'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:240:in `save'
from (irb):18
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands/console.rb:47:in `start'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands/console.rb:8:in `start'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
I ran into the same issue as this. It turns out that there's a Kernel.y extension method that is getting in your way, based on this article. Here is what I did to fix my problem:
class Event < ActiveRecord::Base
# alias the attributes
alias_attribute :x_pos, :x
alias_attribute :y_pos, :y
after_initialize :init
# after_initialize will still work, with the aliases
def init
self.x_pos ||= 0
self.y_pos ||= 0
end
# override Kernel.y
def y; end
# override self.y_pos to read out of the :attributes, since we blew away :y
def y_pos
attribute['y']
end
end
After doing this, I was finally able to use my model without having to rename the y database column.
While I normally don't advocate using gems liberally, if you have a lot of relations that need to be preserved in the duplication, or find yourself doing these manual duplications a lot, take a look at deep_clonable.
As for your specific error, try surrounding each line of code with a nil check (one line at a time). I'm sure there's just some case where you're ending up with a nil object that you're overlooking.
Trying to queue a job with delayed_job as follows:
Delayed::Job.enqueue(BackgroundProcess.new(current_user, object))
current_user and object are not nil when I print them out. The weird thing is that sometimes refreshing the page or running the command again works!
Here is the exception trace:
Delayed::Backend::ActiveRecord::Job Columns (44.8ms) SHOW FIELDS FROM `delayed_jobs`
TypeError (wrong argument type nil (expected Data)):
/Users/.rvm/rubies/ruby-1.9.1-p378/lib/ruby/1.9.1/yaml.rb:391:in `emit'
/Users/.rvm/rubies/ruby-1.9.1-p378/lib/ruby/1.9.1/yaml.rb:391:in `quick_emit'
/Users/.rvm/rubies/ruby-1.9.1-p378/lib/ruby/1.9.1/yaml/rubytypes.rb:86:in `to_yaml'
vendor/plugins/delayed_job/lib/delayed/backend/base.rb:65:in `payload_object='
activerecord (2.3.9) lib/active_record/base.rb:2918:in `block in assign_attributes'
activerecord (2.3.9) lib/active_record/base.rb:2914:in `each'
activerecord (2.3.9) lib/active_record/base.rb:2914:in `assign_attributes'
activerecord (2.3.9) lib/active_record/base.rb:2787:in `attributes='
activerecord (2.3.9) lib/active_record/base.rb:2477:in `initialize'
activerecord (2.3.9) lib/active_record/base.rb:725:in `new'
activerecord (2.3.9) lib/active_record/base.rb:725:in `create'
vendor/plugins/delayed_job/lib/delayed/backend/base.rb:21:in `enqueue'
I would guess that it is caused by the fact that you send the objects as arguments to your jobs (at least I assume that current_user and object are in fact objects and not id's). Send the id's instead and start with loading the objects when perform starts.
For example:
Delayed::Job.enqueue(BackgroundProcess.new(current_user.id, object.id))
class BackgroundProcess < Struct.new(:user_id, :object_id)
def perform
#current_user = User.find(user_id)
#object = Object.find(object_id)
...
end
end
This way, it does not risk any problem with serializing an ActiveRecord into the database and you will always load the latest changes when the job is run.
Ran into this same problem as well. I still don't know what is causing it, but for some reason cloning the object seems to solve it
u = User.find 123
u.to_yaml
=> TypeError: wrong argument type nil (expected Data)
u.clone.to_yaml
=> works like normal
Very frustrating. Would be better to know the root cause, but this might help if you are desperate.