SystemStackError: stack level too deep #55

Closed
kushagr opened this Issue Jan 13, 2014 · 4 comments

Comments

Projects
None yet
2 participants
@kushagr

kushagr commented Jan 13, 2014

Hi, I was shifting my rails application from mongoDB to rethinkDB.
I seem to have run in an issue with nobrainer.

My getters have stopped working and are throwing a stack level too deep error.

For example :

class User
 include NoBrainer::Document
  field :year
  def year
    self[:year]
  end
end

Earlier with MongoDB this worked fine and only threw a stack level too deep error, when self[:year] was replaced with self.year(infinite recursion).
I wonder why this is not working with NoBrainer.

@nviennot

This comment has been minimized.

Show comment
Hide comment
@nviennot

nviennot Jan 13, 2014

Owner

In http://nobrainer.io/docs/fields/#accessing_fields :

Note that methods lower in the list calls the method directly above it. For example, self[attr] calls read_attribute(attr) which calls self.attr.

This means that self[:year] calls read_attribute(:year), which calls self[:year].

This behavior is interesting to ensure that an operation like self[:year] = "2014" triggers the type casting logic, which needs to go through the setters.

Owner

nviennot commented Jan 13, 2014

In http://nobrainer.io/docs/fields/#accessing_fields :

Note that methods lower in the list calls the method directly above it. For example, self[attr] calls read_attribute(attr) which calls self.attr.

This means that self[:year] calls read_attribute(:year), which calls self[:year].

This behavior is interesting to ensure that an operation like self[:year] = "2014" triggers the type casting logic, which needs to go through the setters.

@kushagr

This comment has been minimized.

Show comment
Hide comment
@kushagr

kushagr Jan 13, 2014

That is interesting. Is there a way to fix this ?
Cause I can't get my getters to work at all.
Is there any way to override my getters and setters ? I keep getting the same error no matter what i try.

Here is a link that might help you get the problem I'm going through.
http://api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Overwriting+default+accessors

Also I tried all three methods none of them worked.
I've been racking my brains out to make these getters work.
Any help is appreciated.

kushagr commented Jan 13, 2014

That is interesting. Is there a way to fix this ?
Cause I can't get my getters to work at all.
Is there any way to override my getters and setters ? I keep getting the same error no matter what i try.

Here is a link that might help you get the problem I'm going through.
http://api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Overwriting+default+accessors

Also I tried all three methods none of them worked.
I've been racking my brains out to make these getters work.
Any help is appreciated.

@nviennot

This comment has been minimized.

Show comment
Hide comment
@nviennot

nviennot Jan 13, 2014

Owner

I see. So the correct way to do it with nobrainer is to use super, as opposed to the active record way of doing things. For example:

class User
 include NoBrainer::Document
  field :year
  def year
    super
  end
end

It doesn't make much sense to me that read_attribute doesn't go through the user defined getters.
Another example: model_instance.attributes should return the attributes as filtered through the user specified getters. To me, this behavior makes a lot of sense, especially when using setters. For example:

class User
 include NoBrainer::Document
  field :year
  def year=(value)
    super(value.to_i)
  end
end

This piece of code would always call to_i when assigning the year attribute. Regardless if it's through instance.year = "1234", or instance.write_attribute(:year, "1234"), or instance['year'] = "1234", or instance.attributes = {"year" => "1234"}.

This way you get a much more consistent behavior when accessing model attributes. There is no way to bypass the user defined getter/setters, which I think is a good thing. I probably should document heavily this behavior though, because it will surprise more people.

Owner

nviennot commented Jan 13, 2014

I see. So the correct way to do it with nobrainer is to use super, as opposed to the active record way of doing things. For example:

class User
 include NoBrainer::Document
  field :year
  def year
    super
  end
end

It doesn't make much sense to me that read_attribute doesn't go through the user defined getters.
Another example: model_instance.attributes should return the attributes as filtered through the user specified getters. To me, this behavior makes a lot of sense, especially when using setters. For example:

class User
 include NoBrainer::Document
  field :year
  def year=(value)
    super(value.to_i)
  end
end

This piece of code would always call to_i when assigning the year attribute. Regardless if it's through instance.year = "1234", or instance.write_attribute(:year, "1234"), or instance['year'] = "1234", or instance.attributes = {"year" => "1234"}.

This way you get a much more consistent behavior when accessing model attributes. There is no way to bypass the user defined getter/setters, which I think is a good thing. I probably should document heavily this behavior though, because it will surprise more people.

@kushagr

This comment has been minimized.

Show comment
Hide comment
@kushagr

kushagr Jan 14, 2014

Thanks a lot for the help. super worked like a charm.

kushagr commented Jan 14, 2014

Thanks a lot for the help. super worked like a charm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment