ActiveRecord::Base.transaction - SystemStackError - stack level too deep:

Im having an issue that seems to only happen when trying to use a
transaction. Ive used transactions many times in the past and Im at a
loss
as to why im getting the stack level too deep problem.

SystemStackError - stack level too deep:
actionpack (3.2.13) lib/action_dispatch/middleware/reloader.rb:70:in
`’

I have a StackOveflow with more detail -
http://stackoverflow.com/q/16930511/1408461

As stated in the SO. If I try to save the record to the database outside
the transaction it saves just fine. I only get the error in the
transaction.

Params Object

params => {
“resource”=> {
“resource_type”=>“document”,
“resource_name”=>“My Rails Doc”,
“source_id”=>“Dropbox”
},
“resource_document”=> {
“resource_document”=>
#<ActionDispatch::Http::UploadedFile:0x007f8e919d06f8
@content_type=“text/plain”,
@headers= “Content-Disposition:
form-data; name="resource_document[resource_document]";
filename="rails_local_env_setup.txt"\r\n
Content-Type: text/plain\r\n”,
@original_filename=“rails_local_env_setup.txt”,
@tempfile=
#<File:/var/folders/t4/lfmj7mhj52b2krryzh7dj4hh0000gn/T/RackMultipart20130604-29589-2c0seo>>},

“action”=>“create”,
“controller”=>“resources”
}

Controller

def create

if current_teacher
@resource = ResourceObject.create_teacher_resource(params,
current_teacher)
end

if current_student
@resource = ResourceObject.create_student_resource(params,
current_student)
end

if current_admin
@resource = Resource.new(params[:resource])
end

respond_to do |format|
if @resource.success
format.html { redirect_to @resource, notice: ‘Resource was
successfully created.’ }
format.json { render json: @resource, status: :created, location:
@resource }
else
format.html { render action: “new” }
format.json { render json: @resource.errors, status:
:unprocessable_entity }
end
endend

Transaction

class ResourceObject

def self.create_teacher_resource(params, teacher)
begin
ActiveRecord::Base.transaction do
# Create Resource
@resource = Resource.new
@resource.resource_name = params[:resource][:resource_name]
@resource.resource_type = params[:resource][:resource_type]
@resource.source_id = params[:resource][:source_id]
@resource.teacher_id = teacher.id
@resource.save

    # Create Resource Document
    @resource_document = ResourceDocument.new
    @resource_document.resource_document = 

params[:resource_document][:resource_document]
@resource_document.resource_id = @resource.id
@resource_document.save

    # TODO Add Commom Core Joins
    # TODO Video Uploader
    # TODO Image Uploader

    return @resource.success = "ok"
  end
    rescue Exception => e
  # TODO Need to figure out how to pass exception message back to 

controller
return @resource.errors
end
end
end

end

Resource Model

class Resource < ActiveRecord::Base include TransactionAttributes
attr_accessible :resource_name, :resource_type, :source_id, :teacher_id,
:student_id, :success, :errors belongs_to :teacher, :class_name =>
“Teacher”, :foreign_key => “teacher_id” belongs_to :student, :class_name
=>
“Student”, :foreign_key => “student_id” has_many :resource_documents #
has_many :resource_images # has_many :resource_videos # has_many
:question_resources # has_many :assignment_resources end

On Saturday, 22 June 2013 16:06:54 UTC-7, Bob O wrote:

"source_id"=>"Dropbox"

end
if @resource.success
class ResourceObject
@resource.save

    return @resource.success = "ok"
  end
    rescue Exception => e

A style note here: rescuing Exception is not typically what you want.
See
this for more details:

class Resource < ActiveRecord::Base include TransactionAttributes

I’d be curious as to what’s in this module - it could be relevant…

attr_accessible :resource_name, :resource_type, :source_id, :teacher_id,
:student_id, :success, :errors

:errors here is not useful - attr_accessible controls mass-assignment
of
attributes (as when you do Resource.new(:param1 => ‘foo’, :param2 =>
‘bar’). You almost certainly do not want to mass-assign an internal part
of
ActiveRecord. :slight_smile:

belongs_to :teacher, :class_name => “Teacher”, :foreign_key =>
“teacher_id”

belongs_to :student, :class_name => “Student”, :foreign_key => “student_id”

Another minor (not terribly relevant) style note: :class_name and
:foreign_key are both redundant here, as the values specified are the
same
as the ActiveRecord defaults.

Next steps for debugging this:

  • it would be useful to see the code for the TransactionAttributes
    module
    you’re including. Perhaps something is hitting an internal method and
    making a mess.

  • showing the DB schema would help as well; again, having fields with
    names
    that clash with ActiveRecord’s can cause peculiar behavior.

  • a full stack trace might shed some light; especially in the case of
    StackLevelTooDeep, the final line isn’t always helpful.

–Matt J.

On Sunday, 23 June 2013 20:22:26 UTC-7, Bob O wrote:

self.success = success

end

That’s the problem right there - this method is calling itself. If you
want
to define a getter / setter, you should either do this:

def success
@success
end

def success=(value)
@success = value
end


Or this (preferred, if you’re just storing a value, as above):

attr_accessor :success

def errors
errors
end

def errors=(errors)
self.errors = errors
end
end

These will break some things - ActiveRecord already defines an errors
method + errors= assignment operator, and expects them to behave in a
particular way (for instance, the validations assume that you can make
calls like some_model.errors.add(:some_attribute, 'message')).

I highly recommend reading through the guides
(http://guides.rubyonrails.org/) or following some of Michael H.'s
excellent tutorial (http://ruby.railstutorial.org/) in preference to
digging through Stack Overflow - the answers there are incredibly useful
if
you’ve got a highly specific problem, but they can sometimes miss the
bigger picture.

Hope this helps,

–Matt J.

This is the TransactionAttributes

module TransactionAttributes

def success
success
end

def success=(success)
self.success = success
end

def errors
errors
end

def errors=(errors)
self.errors = errors
end
end

The reason for these was i was trying to set a property on a returned
object or the errors. I yet to figure out a way i can return a more
descriptive error message from the transaction back to the controller.

I’ll fix the style note. That just happens to populate when using a tab
trigger in Sublime.

This is the table schema

== Schema Information

Table name: resources

id :integer not null, primary key

resource_name :string(255)

teacher_id :integer

student_id :integer

source_id :string(255)

created_at :datetime not null

updated_at :datetime not null

resource_type :string(255)

The SystemStackError - stack level too deep:
actionpack (3.2.13) lib/action_dispatch/middleware/reloader.rb:70:in
`’
is the only thing i get in the console.

This is whats returned in the response.

SystemStackError at /resources

stack level too deep

actionpack (3.2.13) lib/action_dispatch/middleware/reloader.rb, line 70

65 response = @app.call(env)
66 response[2] = ActionDispatch::BodyProxy.new(response[2]) { cleanup! }
67 response
68 rescue Exception
69 cleanup!
> 70 raise
71 end
72
73 def prepare! #:nodoc:
74 run_callbacks :prepare if validated?
75 end

App backtrace

Full backtrace

  • actionpack (3.2.13) lib/action_dispatch/middleware/reloader.rb:70:in
    `’

based on a SO i read it said to turn on
the Rails.backtrace_cleaner.remove_silencers!

so ive dont that.

Is there something else i can do to that would be helpful?

Thanks Matt. That was the problem. At one point I had pulled those out,
or
at least I thought I did. I guess thats why I was confused. Anyway.
Thanks
For the help. I do have Michaels stuff. Its very good. My setters were a
rookie mistake.

One thing that I wish i could find more stuff about is transactions.
Most
examples seem to handle the transactions in the controller which I dont
like. So I have troubles getting the errors back to the controller for
better user feedback. Hence the reason I was trying to use the
TransactionAttributes module. Backfire!

Appreciate your help.

Bob