Stack level too deep error in Ruby on Rails
I've found the solution to this issue...
I'm using Rails 3 and my class looks like this (and the problematic methods was this too)
class Organization < ActiveRecord::Base
def self.parents
@organizations = self.find :all, :conditions => ['is_company = ? ',true]
select_choice = I18n.t("select") + " "+ I18n.t("segments.description")
@organization_parents = [select_choice]
for organization in @organizations
@organization_parents << [organization.name, organization.id]
end
return @organization_parents
end
#...
end
I did have to hack a lot in the code to find out something was wrong with the named_scope on the line
@organizations = self.find :all, :conditions => ['is_company = ? ',true]
So I had to change it to something like this
@organizations = Organization.where("is_company = ?",true)
But it was wrong too.. So I decided to add an scope for this below the class name so the final code looks like this:
class Organization < ActiveRecord::Base
scope :company, where("is_company = ?",true)
def self.parents
@organizations = self.company
select_choice = I18n.t("select") + " "+ I18n.t("segments.description")
@organization_parents = [select_choice]
for organization in @organizations
@organization_parents << [organization.name, organization.id]
end
return @organization_parents
end
#...
end
So using this line with the scope
@organizations = self.company
it worked flawlessly in every part of the code.
I was wondering if the named_scope is deprecated when using class methods or they are not supported from now and throws an error and not a warning before
Thanks for your help
Leo
How to fix the SystemStackError (stack level too deep) in rails model
In your code there is a before_create
callback that calls the remember
method. In this remember
method you call update_attribute
which internally tries to save
the record which calls the same before_create
callback.
To fix this just use a method to sets the remember_digest
attribute without triggering save
.
For example:
def remember
self.token = User.new_token
self.remember_digest = User.create_digest(token)
end
ruby on rails. stack level too deep error
The stack level too deep
error usually happens because your code is stuck in a loop: either a method calling itself, or two methods calling each other repeatedly.
In your case i think it's caused by the validate_order
method. You are calling this in a before_save
callback, and the method calls self.save
, which will trigger the callback, which will call the method again, which will save again, which will trigger the callback etc etc.
Think about this for a moment - it doesn't make sense to save an object as part of it's "before_save" functionality does it?
What i suspect you want to do is to just validate the object, and if validation fails that will automatically block the save anyway. Something like this
validate :validate_order
def validate_order
@deposit = self.deposit
@income = @deposit.income
@cashout = self.order_sum
if @income - @cashout <= 0
self.errors.add(:deposit, "is too small")
end
end
This is just an example as i don't know what the actual logic of what you are testing is supposed to be.
Ruby on Rails - SystemStackError (stack level too deep) when doing after_update
It's because you have again call the update method in your private method. That means the application will go in infinite loop and into dead conditions.
You just need to set the attribute into the self no need to call the update method inside the private method.
class Post < ActiveRecord::Base
before_update :navid_tadding_atgs
private
def navid_tadding_atgs
self.added_by_me = 'yes'
end
SystemStackError (stack level too deep) when deleting a record
The stack level too deep error occurs when you try to delete a record with relationships that declare dependent: :destroy
linking back to each other.
Example:
class Order < ActiveRecord::Base
has_many :items, dependent: :destroy
end
class Item < ActiveRecord::Base
belongs_to :order, dependent: :destroy
end
Removing dependent: :destroy
from the Item assocation should resolve the circular error/stack level too deep.
Arel: I get stack level too deep error when I try to get SQL from Arel
Now that I understand the desired output here is how I would go about this
class Report
JOB_STATS = Arel::Table.new('jobstat_jobs')
CORE_MEMBERS = Arel::Table.new('core_members')
SESSIONS = Arel::Table.new('sessions_projects_in_sessions')
def additions
# This could be ported too if I knew the tables for end_time, start_time, and num_nodes
{
node_hours: Arel.sql("((extract(epoch from (end_time - start_time))/ 3600))*num_nodes").sum,
jobs: JOB_STATS[:id].count
}
end
def n
@n ||= _base_query.as('n')
end
def s
@s ||= _base_query
.project(JOB_STATS[:state])
.group(JOB_STATS[:state]).as('s')
end
def alias_columns
additions.keys.flat_map do |key|
[s[key].as("s_#{key}"),
n[key].as("n_#{key}"),
(s[key] / n[key]).as("share_#{key}")]
end
end
def query
Arel::SelectManager.new.project(
s[:project_id].as('id'),
s[:state],
*alias_columns
)
.from(s)
.join(n).on(s[:project_id].eq(n[:project_id]))
end
def to_sql
query.to_sql
end
private
def cast_as_decimal(value,alias_name:)
Arel::Nodes::NamedFunction.new(
"CAST",
[Arel::Nodes::As.new(value, Arel.sql('DECIMAL'))]
).as(alias_name.to_s)
end
def _base_query
JOB_STATS
.project(
CORE_MEMBERS[:project_id],
*additions.map {|k,v| cast_as_decimal(v, alias_name: k)})
.join(CORE_MEMBERS).on(CORE_MEMBERS[:login].eq(JOB_STATS[:login]))
.outer_join(SESSIONS).on(SESSIONS[:project_id].eq(CORE_MEMBERS[:project_id]))
.where(JOB_STATS[:state].not_in(['COMPLETETED', 'RUNNING', 'unknown']))
.group(CORE_MEMBERS[:project_id])
end
end
Result of Report.new.to_sql
SELECT
s."project_id" AS id,
s."state",
s."node_hours" AS s_node_hours,
n."node_hours" AS n_node_hours,
s."node_hours" / n."node_hours" AS share_node_hours,
s."jobs" AS s_jobs,
n."jobs" AS n_jobs,
s."jobs" / n."jobs" AS share_jobs
FROM
(
SELECT
"core_members"."project_id",
CAST(SUM(((extract(epoch from (end_time - start_time))/ 3600))*num_nodes) AS DECIMAL) AS node_hours,
CAST(COUNT("jobstat_jobs"."id") AS DECIMAL) AS jobs,
"jobstat_jobs"."state"
FROM
"jobstat_jobs"
INNER JOIN "core_members" ON "core_members"."login" = "jobstat_jobs"."login"
LEFT OUTER JOIN "sessions_projects_in_sessions" ON "sessions_projects_in_sessions"."project_id" = "core_members"."project_id"
WHERE
"jobstat_jobs"."state" NOT IN (N'COMPLETETED', N'RUNNING', N'unknown')
GROUP BY
"core_members"."project_id",
"jobstat_jobs"."state"
) s
INNER JOIN (
SELECT
"core_members"."project_id",
CAST(SUM(((extract(epoch from (end_time - start_time))/ 3600))*num_nodes) AS DECIMAL) AS node_hours,
CAST(COUNT("jobstat_jobs"."id") AS DECIMAL) AS jobs
FROM
"jobstat_jobs"
INNER JOIN "core_members" ON "core_members"."login" = "jobstat_jobs"."login"
LEFT OUTER JOIN "sessions_projects_in_sessions" ON "sessions_projects_in_sessions"."project_id" = "core_members"."project_id"
WHERE
"jobstat_jobs"."state" NOT IN (N'COMPLETETED', N'RUNNING', N'unknown')
GROUP BY
"core_members"."project_id"
) n ON s."project_id" = n."project_id"
This will also allow you further filter the resulting query like so:
rpt = Report.new
q = rpt.query.where(rpt.n[:jobs].gt(12))
q.to_sql
#=> "...same as above...WHERE n.\"jobs\" > 12"
Rails 5.1.6 - Stack level too deep
I've got the solution, although I don't exactly understand why it was working till now.
Originally there was the below validation in the Scan model (as I posted earlier):
with_options unless: @photo.present? do
validates :reading, presence: true
validates :reading, numericality: true
validates :reading_date, presence: true
end
In irb I managed to localize the error to this validation part. After refactoring the @photo.present?
to a new method and calling that method in the validation, the problem is solved:
with_options unless: :has_photo? do
validates :reading, presence: true
validates :reading, numericality: true
validates :reading_date, presence: true
end
def has_photo?
@photo.present?
end
Call back before save : SystemStackError: stack level too deep
Stack level too deep indicates it went to infinite loop. If you save anything in before save, after save, before create, after create, before update, after update which call callback again it will cause stack level too deep.
In above code i found that set_st_point is called in before create and saving it which caused here Stack level too deep. Data is not saving after setting also that must be some other issue that you have to check if once you set 'lonlat ' some other place it is resetting it.
Once simple fix is in after create you can say
.update_column('lonlat',"POINT(#{longitude} #{latitude})")
update column will not call any callback this must be there in after create.
Related Topics
What Do the Different Brackets in Ruby Mean
Ruby: How to Make Irb Print Structure for Arrays and Hashes
Rbenv: Surviving Without Gemsets
What's the Difference Between Process.Fork and Process.Spawn in Ruby 1.9.2
Ruby Methods and Optional Parameters
How to Get the Line of Code That Triggers a Query
Extracting the Last N Characters from a Ruby String
How to Save Values into a Yaml File
Rails. How to Store Time of Day (For Schedule)
How to Call an Older Version of a Gem from the Commandline
Iterating Between Two Datetimes, with a One Hour Step
How to See the Dependency Tree Just from Gemfile
Rails 3.1 with Postgresql: Group by Must Be Used in an Aggregate Function