Error with has_and_belongs_to_many association #6

Closed
torsakch opened this Issue Feb 8, 2012 · 13 comments

Comments

Projects
None yet
2 participants
@torsakch

torsakch commented Feb 8, 2012

When I use the has_and_belongs_to_many association in the model having act_as_tenant, I got the internal server error. Actually, it is an NoMethodError (undefined method ... ). So, I don't the problem. Please help me to verify. Thanks

@torsakch

This comment has been minimized.

Show comment
Hide comment
@torsakch

torsakch Feb 8, 2012

Note that when I put the acts_as_tenant(:account) before the :has_and_belongs_to_many association, the problem doesn't occur. But when I put it below the :has_and_belongs_to_many association in the model. The problem occurs.

The reason that I want to put it below the :has_and_belongs_to_many association is that I want to make an inheritance of the model and the child model will be assigned to acts_as_tenant. So, the code in the parent model will be executed first and following by the child model code.

Could you tell me how to solve this problem? Thank you in advance.

torsakch commented Feb 8, 2012

Note that when I put the acts_as_tenant(:account) before the :has_and_belongs_to_many association, the problem doesn't occur. But when I put it below the :has_and_belongs_to_many association in the model. The problem occurs.

The reason that I want to put it below the :has_and_belongs_to_many association is that I want to make an inheritance of the model and the child model will be assigned to acts_as_tenant. So, the code in the parent model will be executed first and following by the child model code.

Could you tell me how to solve this problem? Thank you in advance.

@ErwinM

This comment has been minimized.

Show comment
Hide comment
@ErwinM

ErwinM Feb 9, 2012

Owner

Could you post your model code for me?

Owner

ErwinM commented Feb 9, 2012

Could you post your model code for me?

@torsakch

This comment has been minimized.

Show comment
Hide comment
@torsakch

torsakch Feb 10, 2012

Thank you for replying me. Here are my models.

class Account < ActiveRecord::Base
has_many :users
end

class User < ActiveRecord::Base
belongs_to :account
has_and_belongs_to_many :roles
end

class Role < ActiveRecord::Base
has_and_belongs_to_many :users
end

class Member < User
acts_as_tenant(:account)
end

Thank you for replying me. Here are my models.

class Account < ActiveRecord::Base
has_many :users
end

class User < ActiveRecord::Base
belongs_to :account
has_and_belongs_to_many :roles
end

class Role < ActiveRecord::Base
has_and_belongs_to_many :users
end

class Member < User
acts_as_tenant(:account)
end

@ghost ghost assigned ErwinM Feb 11, 2012

@ErwinM

This comment has been minimized.

Show comment
Hide comment
@ErwinM

ErwinM Feb 11, 2012

Owner

In the code above acts_as_tenant has nothing to do with the HABTM association: acts_as_tenant is defined on the member model which does not have an HABTM association.

Can you also post the code that triggers the 'undefined method'-error, or post the stack trace?

Owner

ErwinM commented Feb 11, 2012

In the code above acts_as_tenant has nothing to do with the HABTM association: acts_as_tenant is defined on the member model which does not have an HABTM association.

Can you also post the code that triggers the 'undefined method'-error, or post the stack trace?

@torsakch

This comment has been minimized.

Show comment
Hide comment
@torsakch

torsakch Feb 11, 2012

I have tracked to the code and the error comes from the model_extensions.rb.

71 reflect_on_all_associations.each do |a|
72 unless a == reflection || a.macro == :has_many || a.macro == :has_one || a.options[:polymorphic]
73 # check if the association is aliasing another class, if so
74 # find the unaliased class name
75 association_class = a.options[:class_name].nil? ? a.name.to_s.classify.constantize : a.options[:class_name].constantize
76 validates_each a.foreign_key.to_sym do |record, attr, value|
77 # Invalidate the association unless the parent is known to the tenant or no association has
78 # been set.
79 record.errors.add attr, "is invalid (Acts_as_Tenant)" unless value.nil? || association_class.where(:id => value).present?
80 end
81 end
82 end

I think in this block code, it passes through the "unless" block because the association is HABTM and it gets an error in the "validates_each" block.

I have tracked to the code and the error comes from the model_extensions.rb.

71 reflect_on_all_associations.each do |a|
72 unless a == reflection || a.macro == :has_many || a.macro == :has_one || a.options[:polymorphic]
73 # check if the association is aliasing another class, if so
74 # find the unaliased class name
75 association_class = a.options[:class_name].nil? ? a.name.to_s.classify.constantize : a.options[:class_name].constantize
76 validates_each a.foreign_key.to_sym do |record, attr, value|
77 # Invalidate the association unless the parent is known to the tenant or no association has
78 # been set.
79 record.errors.add attr, "is invalid (Acts_as_Tenant)" unless value.nil? || association_class.where(:id => value).present?
80 end
81 end
82 end

I think in this block code, it passes through the "unless" block because the association is HABTM and it gets an error in the "validates_each" block.

@torsakch

This comment has been minimized.

Show comment
Hide comment
@torsakch

torsakch Feb 12, 2012

One more thing, it happens just only on the update operations. (eg. update_attributes)

One more thing, it happens just only on the update operations. (eg. update_attributes)

@ErwinM

This comment has been minimized.

Show comment
Hide comment
@ErwinM

ErwinM Feb 12, 2012

Owner

I think this is happening because your Role model is not scoped to account. Could you try scoping the Role model to account as well and see if you get the error?

Owner

ErwinM commented Feb 12, 2012

I think this is happening because your Role model is not scoped to account. Could you try scoping the Role model to account as well and see if you get the error?

@torsakch

This comment has been minimized.

Show comment
Hide comment
@torsakch

torsakch Feb 12, 2012

Thank you so much for answering. In the role model, why I need to scope to :account, because I don't need :roles table to be scoped. It is generic for every tenant. I mean for every user they will use the same roles in the table.

Thank you so much for answering. In the role model, why I need to scope to :account, because I don't need :roles table to be scoped. It is generic for every tenant. I mean for every user they will use the same roles in the table.

@ErwinM

This comment has been minimized.

Show comment
Hide comment
@ErwinM

ErwinM Feb 12, 2012

Owner

yup, I understand that. It would help me figure out if that's the problem though..

Owner

ErwinM commented Feb 12, 2012

yup, I understand that. It would help me figure out if that's the problem though..

@torsakch

This comment has been minimized.

Show comment
Hide comment
@torsakch

torsakch Feb 13, 2012

Right now, my code is changed. I decided to remove the roles table from my project and use the role_mask attributes instead.

Note that... If I add "|| a.macro == :has_and_belongs_to_many" to the line 72. It can solve the problem too. But I am not sure whether it affects the security? or am I doing the right thing.

Note2. in the error it said "undefined method user_id". So, I don't that why it involves with user_id.

Right now, my code is changed. I decided to remove the roles table from my project and use the role_mask attributes instead.

Note that... If I add "|| a.macro == :has_and_belongs_to_many" to the line 72. It can solve the problem too. But I am not sure whether it affects the security? or am I doing the right thing.

Note2. in the error it said "undefined method user_id". So, I don't that why it involves with user_id.

@torsakch

This comment has been minimized.

Show comment
Hide comment
@torsakch

torsakch Mar 5, 2012

@ErwinM When I added the account_id in Role, the problem is disappeared. I think the problem has occur in case of the :belongs_to macro. So what should I do?

torsakch commented Mar 5, 2012

@ErwinM When I added the account_id in Role, the problem is disappeared. I think the problem has occur in case of the :belongs_to macro. So what should I do?

@ErwinM

This comment has been minimized.

Show comment
Hide comment
@ErwinM

ErwinM Mar 5, 2012

Owner

@torsakch I think it's actually a problem with the gem: the gem currently assumes that every association will always be scoped to the tenant. In practice, a scoped model can be associated with a non-scoped model (like in your case).

I will need to fix this in the code. I'll try to push out an update tonight.

Owner

ErwinM commented Mar 5, 2012

@torsakch I think it's actually a problem with the gem: the gem currently assumes that every association will always be scoped to the tenant. In practice, a scoped model can be associated with a non-scoped model (like in your case).

I will need to fix this in the code. I'll try to push out an update tonight.

@ErwinM

This comment has been minimized.

Show comment
Hide comment
@ErwinM

ErwinM Apr 13, 2012

Owner

This should actually be fixed now. Let me know if it isn't.

Owner

ErwinM commented Apr 13, 2012

This should actually be fixed now. Let me know if it isn't.

@ErwinM ErwinM closed this Apr 13, 2012

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