Hello,
I''m having trouble debugging an override of destroy. I have an object
that in some cases I need to send a parameter when I destroy it. Usually
not though. So I''ve defined destroy in the model class like this:
class Look < ActiveRecord::Base
belongs_to :palette
has_many :colorings, :dependent => :destroy
has_many :colors, :class_name => ''SiteColor'', :dependent
=> :destroy
has_one :active_regatta, :class_name => ''Regatta''
belongs_to :regatta
def destroy(options = {})
# special destroy so we don''t accidentally default look
protected_ids = [1]
super unless (protected_ids.include?(self.id) || options[:override]
)
end
end
The problem is that when I try to destroy one of these objects, I get an
error on the call to super, "wrong number of arguments (1 for 0)" :
>> l=Look.find(62)
=> #<Look:0x23d2a28 @attributes={"name"=>nil,
"id"=>"62",
"palette_id"=>nil,
"regatta_id"=>nil}>>> l.destroy
ArgumentError: wrong number of arguments (1 for 0)
from ./script/../config/../config/../app/models/look.rb:19:in
`destroy''
from ./script/../config/../config/../app/models/look.rb:19:in
`destroy''
from (irb):2>>
Note that there is a :has_many :dependent => :destroy relationship.
It seems that my call to super is getting arguments I don''t know about,
but I don''t understand how to dig any deeper into this. I tried
stepping
into the call to super itself, and I immediately end up in the rescue
clause for ActiveRecord''s transaction method:
(rdb:1) where
--> #0
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/database_statements.rb:62
in ''transaction''
(rdb:1) l [57, 66] in
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/database_statements.rb
57 transaction_open = true
58 end
59 yield
60 end
61 rescue Exception => database_transaction_rollback
=> 62 if transaction_open
63 transaction_open = false
64 rollback_db_transaction
65 end
66 raise
FWIW, I considered the possibility that it was one of the dependent
relationships'' objects who''s destroy method was getting sent a
parameter
it wasn''t expecting - so I defined both of those to accept a parameter
as well, and then *their* call to super caused this problem.
--
Posted via http://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Maybe you are over-complicating this.
Rails has a "before_destroy" filter.
Just use that, and if the ID of the object being destroyed is 1, abort
the process (by just returning false).
So maybe something as simple as this (just off the top of my head, so
you''ll wanna test it of course)
class Look < ActiveRecord::Base
belongs_to :palette
has_many :colorings, :dependent => :destroy
has_many :colors, :class_name => ''SiteColor'', :dependent
=> :destroy
has_one :active_regatta, :class_name => ''Regatta''
belongs_to :regatta
before_destroy { |record| return false if record.id == 1 }
end
Note: it''s such a simple check that you don''t even need to
call a
method... it can be handled right in the Proc.
Also note: the filter chain halts if you return false, which is
probably what you want in this case, but again: test it to be sure.
HTH!
-Danimal
On Apr 12, 11:12 pm, Avram Dorfman
<rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org>
wrote:> Hello,
>
> I''m having trouble debugging an override of destroy. I have an
object
> that in some cases I need to send a parameter when I destroy it. Usually
> not though. So I''ve defined destroy in the model class like this:
>
> class Look < ActiveRecord::Base
> belongs_to :palette
>
> has_many :colorings, :dependent => :destroy
> has_many :colors, :class_name => ''SiteColor'',
:dependent => :destroy
> has_one :active_regatta, :class_name => ''Regatta''
> belongs_to :regatta
>
> def destroy(options = {})
> # special destroy so we don''t accidentally default look
> protected_ids = [1]
>
> super unless (protected_ids.include?(self.id) || options[:override]
> )
> end
> end
>
> The problem is that when I try to destroy one of these objects, I get an
> error on the call to super, "wrong number of arguments (1 for 0)"
:
>
> >> l=Look.find(62)
>
> => #<Look:0x23d2a28 @attributes={"name"=>nil,
"id"=>"62",
> "palette_id"=>nil, "regatta_id"=>nil}>>>
l.destroy
>
> ArgumentError: wrong number of arguments (1 for 0)
> from ./script/../config/../config/../app/models/look.rb:19:in
> `destroy''
> from ./script/../config/../config/../app/models/look.rb:19:in
> `destroy''
> from (irb):2
>
>
>
> Note that there is a :has_many :dependent => :destroy relationship.
>
> It seems that my call to super is getting arguments I don''t know
about,
> but I don''t understand how to dig any deeper into this. I tried
stepping
> into the call to super itself, and I immediately end up in the rescue
> clause for ActiveRecord''s transaction method:
>
> (rdb:1) where
> --> #0
>
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/database_statements.rb:62
> in ''transaction''
> (rdb:1) l > [57, 66] in
>
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/database_statements.rb
> 57 transaction_open = true
> 58 end
> 59 yield
> 60 end
> 61 rescue Exception => database_transaction_rollback
> => 62 if transaction_open
> 63 transaction_open = false
> 64 rollback_db_transaction
> 65 end
> 66 raise
>
> FWIW, I considered the possibility that it was one of the dependent
> relationships'' objects who''s destroy method was getting
sent a parameter
> it wasn''t expecting - so I defined both of those to accept a
parameter
> as well, and then *their* call to super caused this problem.
> --
> Posted viahttp://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Daniel, I appreciate the suggestion. I don''t think it will cover my case, but I must admit I had forgoten all about before_destroy. I''ll have to put some more thought into this. The problem is that I want to be able to force the destroy if necessary. I''m not sure how I would articulate an override into before_destroy. But I''ll look into it. Part of the reason for my question is that this seems to be a case where what I thought I knew doesn''t seem to be correct, so I''m looking to improving my understanding of Rails. -Avram -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Avram, I''m confused. What do you mean by "want to be able to force the destroy"? If you have @look as the instance of the Look object you want to destroy, you just call @look.destroy, right? The before_destroy hook is just to make sure that you don''t destroy the Look object with ID=1 (or whatever ID you want to protect). Some other things to consider: You could use before_destroy but have it call a method instead of an inline proc. I.e.: before_destroy :skip_delete_if_not_one def skip_delete_if_not_one return false if id == 1 end Then, you could add other logic there if need be. Another thought that just occurred to me: If the default destroy method takes an options hash, maybe you need to pass that to super as well? Maybe that''s the error you are getting. Also, I vaguely remember something in the Agile book about this... i.e. not deleting the user with ID=1. You might see how that was done. I don''t think the problem is that your thinking is off... you are thinking about this in the right way. But like so many things in the Rails world, there are lots of ways to do something. So, you can call a before filter (as I suggested). Or you can override the destroy method (as you suggested). Both are "the right way"... it''s more a matter of taste, style and what you specifically want to accomplish. -Danimal On Apr 13, 8:06 am, Avram Dorfman <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> Daniel, > > I appreciate the suggestion. I don''t think it will cover my case, but I > must admit I had forgoten all about before_destroy. I''ll have to put > some more thought into this. > > The problem is that I want to be able to force the destroy if necessary. > I''m not sure how I would articulate an override into before_destroy. But > I''ll look into it. > > Part of the reason for my question is that this seems to be a case where > what I thought I knew doesn''t seem to be correct, so I''m looking to > improving my understanding of Rails. > > -Avram > -- > Posted viahttp://www.ruby-forum.com/.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Danimal,
Here''s what I want:
Object.find(2).destroy # object 2 is destroyed
Object.find(1).destroy # has no effect
Object.find(1).destroy :override => true # object 1 is destroyed.
I want to prevent someone from being able to delete certain Look objects
by mistake, but I don''t want to completely block my ability to destroy
the special ones.
The super destroy method does not take any parameters. The error is "1
for 0" not "0 for 1". It only comes up when I add parameters to
my
destroy method.
If I simply change my destroy method to
def destroy
super if self.id != 1
end
I don''t have any problems.
But now I can''t destroy object 1 intetionally without changing the
code.
--
Posted via http://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
I wonder if by declaring it as:
def destroy(options = {}) ...
if you are not actually overriding the default destroy method? (I''ve
got a reasonable amount of Ruby and Rails experience, but I''m by no
means an expert, so I may be misunderstanding something here).
What if you make a second method called: "destroy_override". So
instead of calling: Look.find(1).destroy :override => true you''d
call:
Look.find(1).destroy_override
Then, you do your original code but without the options parameter.
That overrides destroy() as a method and does the ID check. Then, in
destroy_override it just calls destroy, probably through an alias for
the original destroy so it doesn''t call your overridden method.
I hope that rambling made sense. Let me know if it didn''t.
-Danimal
On Apr 13, 9:22 am, Avram Dorfman
<rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org>
wrote:> Danimal,
>
> Here''s what I want:
>
> Object.find(2).destroy # object 2 is destroyed
> Object.find(1).destroy # has no effect
> Object.find(1).destroy :override => true # object 1 is destroyed.
>
> I want to prevent someone from being able to delete certain Look objects
> by mistake, but I don''t want to completely block my ability to
destroy
> the special ones.
>
> The super destroy method does not take any parameters. The error is "1
> for 0" not "0 for 1". It only comes up when I add parameters
to my
> destroy method.
>
> If I simply change my destroy method to
> def destroy
> super if self.id != 1
> end
>
> I don''t have any problems.
>
> But now I can''t destroy object 1 intetionally without changing the
code.
> --
> Posted viahttp://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
It made sense, it just doesn''t prevent accidental destruction of the object. It requires someone to be aware that they can''t indiscriminately call destroy on objects of this class. It isn''t really any different than requiring people to always say "object.destroy if !object.protected?. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---