I''m trying to write an application that involves with three kinds of inherited models: The lowest is Person, a model merely used as records, and nothing else of importance. Officer inherits from Person, and unlike Person, stores a password for verification and logging in. Admin inherits from Officer, and is the same as Officers except there must be at least one of them. I want to make an internal method that allows me to turn a Person into an Officer, an Officer to Admin, Admin to Person, etc. What''s a clean method of upgrading/downgrading within this single-inheritance? Here''s the source file, as well as a quick template for what I want to see happen: =======Person.rb=======class Person < ActiveRecord::Base #first_name is required: must start with a capital validates_presence_of :first_name validates_format_of :first_name, :with => /^[A-Z][a-zA-Z0-9, .]+$/ #last_name is required: must start with a capital validates_presence_of :last_name validates_format_of :last_name, :with => /^[A-Z][a-zA-Z0-9, .]+$/ #rin is required: must be unique; also, must all be lowercases #with 0 to 2 numbers following the letters. validates_presence_of :rin validates_format_of :rin, :with => /^[a-z]+[0-9]{0,2}$/ validates_uniqueness_of :rin #email must be unique, and it is required. validates_presence_of :email validates_format_of :email, :with => /^[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-z]{2,3}){1,2}$/ validates_uniqueness_of :email #year is required, and must be a 4 digit number greater than 2000 validates_presence_of :year validates_numericality_of :year, :only_integer => true validates_length_of :year, :is => 4 #turns a Person or Officer to Admin def turn_to_admin self[:type] = ''Admin'' #somehow update with Admin-based validations self end #turns a Person or Admin to Officer def turn_to_officer self[:type] = ''Officer'' #somehow update with Officer-based validations self end #technically, this does nothing def turn_to_person nil end protected def validate errors.add(:year, "should be between 2000 and 3000") if ( year.to_i < 2000 or year.to_i > 3000 ) end #completely ignore the passwords end =======Officer.rb=======class Officer < Person #take care of password thingy validates_length_of :password, :minimum => 5 attr_accessor :password_confirmation validates_confirmation_of :password #some functions def validate errors.add_to_base("Missing password") if hashed_password.blank? end def self.authenticate(name, password) person = self.find_by_rin(name) if person expected_password = encrypted_password(password, person.salt) if person.hashed_password!=expected_password person = nil end end person end def password @password end def password=(pwd) @password = pwd create_new_salt self.hashed_password = Officer.encrypted_password(self.password, self.salt) end #turn_to_admin is inherited from Person #This does nothing def turn_to_officer nil end #turns an Officer or Admin def turn_to_person self[:type] = ''Person'' #somehow update with Officer-based validations self end #careful of private statements private def self.encrypted_password(password, salt) string_to_hash = password + "Japan is an island of interest" + salt Digest::SHA1.hexdigest(string_to_hash) end def create_new_salt self.salt = (self.object_id * rand).to_s + rand.to_s end end =======Admin.rb=======class Admin < Officer #Make sure there''s at least one admin def after_destroy if Admin.count.zero? raise "Can''t delete the last admin" end end #turn_to_person is inherited by Officer #Return nil, again def turn_to_admin nil end #turns an Admin to Officer def turn_to_officer self[:type] = ''Officer'' #somehow update with Officer-based validations self end end --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Single table inheritance applies perfectly to this need, basically you have to add a type column, and build the people table with all the columns that any of the three classes will do, then both admin and officer have to inherit from person, (I never tested double inheritance) so some repetition at admin and officer model may happen, (you can use a mixin if you want to avoid that) On May 26, 4:05 pm, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I''m trying to write an application that involves with three kinds of > inherited models: > > The lowest is Person, a model merely used as records, and nothing else > of importance. > Officer inherits from Person, and unlike Person, stores a password for > verification and logging in. > Admin inherits from Officer, and is the same as Officers except there > must be at least one of them. > > I want to make an internal method that allows me to turn a Person into > an Officer, an Officer to Admin, Admin to Person, etc. What''s a clean > method of upgrading/downgrading within this single-inheritance? > > Here''s the source file, as well as a quick template for what I want to > see happen: > =======Person.rb=======> class Person < ActiveRecord::Base > #first_name is required: must start with a capital > validates_presence_of :first_name > validates_format_of :first_name, > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > #last_name is required: must start with a capital > validates_presence_of :last_name > validates_format_of :last_name, > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > #rin is required: must be unique; also, must all be lowercases > #with 0 to 2 numbers following the letters. > validates_presence_of :rin > validates_format_of :rin, > :with => /^[a-z]+[0-9]{0,2}$/ > validates_uniqueness_of :rin > > #email must be unique, and it is required. > validates_presence_of :email > validates_format_of :email, > :with => /^[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-z]{2,3}){1,2}$/ > validates_uniqueness_of :email > > #year is required, and must be a 4 digit number greater than 2000 > validates_presence_of :year > validates_numericality_of :year, > :only_integer => true > validates_length_of :year, > :is => 4 > > #turns a Person or Officer to Admin > def turn_to_admin > self[:type] = ''Admin'' > #somehow update with Admin-based validations > self > end > > #turns a Person or Admin to Officer > def turn_to_officer > self[:type] = ''Officer'' > #somehow update with Officer-based validations > self > end > > #technically, this does nothing > def turn_to_person > nil > end > > protected > > def validate > errors.add(:year, "should be between 2000 and 3000") if > ( year.to_i < 2000 or year.to_i > 3000 ) > end > > #completely ignore the passwords > end > =======Officer.rb=======> class Officer < Person > #take care of password thingy > validates_length_of :password, :minimum => 5 > > attr_accessor :password_confirmation > validates_confirmation_of :password > > #some functions > def validate > errors.add_to_base("Missing password") if hashed_password.blank? > end > > def self.authenticate(name, password) > person = self.find_by_rin(name) > if person > expected_password = encrypted_password(password, person.salt) > if person.hashed_password!=expected_password > person = nil > end > end > person > end > > def password > @password > end > > def password=(pwd) > @password = pwd > create_new_salt > self.hashed_password = Officer.encrypted_password(self.password, > self.salt) > end > > #turn_to_admin is inherited from Person > > #This does nothing > def turn_to_officer > nil > end > > #turns an Officer or Admin > def turn_to_person > self[:type] = ''Person'' > #somehow update with Officer-based validations > self > end > > #careful of private statements > private > > def self.encrypted_password(password, salt) > string_to_hash = password + "Japan is an island of interest" + > salt > Digest::SHA1.hexdigest(string_to_hash) > end > > def create_new_salt > self.salt = (self.object_id * rand).to_s + rand.to_s > end > end > =======Admin.rb=======> class Admin < Officer > > #Make sure there''s at least one admin > def after_destroy > if Admin.count.zero? > raise "Can''t delete the last admin" > end > end > > #turn_to_person is inherited by Officer > > #Return nil, again > def turn_to_admin > nil > end > > #turns an Admin to Officer > def turn_to_officer > self[:type] = ''Officer'' > #somehow update with Officer-based validations > self > end > end--~--~---------~--~----~------------~-------~--~----~ 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@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I think he''s got this already. What he''s trying to do is assign a person to be an Admin or an Officer. I think all you do is self.type = "Admin and then self.reload and it might work. On Tue, May 27, 2008 at 12:28 PM, Andres <paglayan-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Single table inheritance applies perfectly to this need, > basically you have to add a type column, > and build the people table with all the columns that any of the three > classes will do, > then both admin and officer have to inherit from person, > (I never tested double inheritance) > so some repetition at admin and officer model may happen, > (you can use a mixin if you want to avoid that) > > > On May 26, 4:05 pm, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > I''m trying to write an application that involves with three kinds of > > inherited models: > > > > The lowest is Person, a model merely used as records, and nothing else > > of importance. > > Officer inherits from Person, and unlike Person, stores a password for > > verification and logging in. > > Admin inherits from Officer, and is the same as Officers except there > > must be at least one of them. > > > > I want to make an internal method that allows me to turn a Person into > > an Officer, an Officer to Admin, Admin to Person, etc. What''s a clean > > method of upgrading/downgrading within this single-inheritance? > > > > Here''s the source file, as well as a quick template for what I want to > > see happen: > > =======Person.rb=======> > class Person < ActiveRecord::Base > > #first_name is required: must start with a capital > > validates_presence_of :first_name > > validates_format_of :first_name, > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > #last_name is required: must start with a capital > > validates_presence_of :last_name > > validates_format_of :last_name, > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > #rin is required: must be unique; also, must all be lowercases > > #with 0 to 2 numbers following the letters. > > validates_presence_of :rin > > validates_format_of :rin, > > :with => /^[a-z]+[0-9]{0,2}$/ > > validates_uniqueness_of :rin > > > > #email must be unique, and it is required. > > validates_presence_of :email > > validates_format_of :email, > > :with => /^[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-z]{2,3}){1,2}$/ > > validates_uniqueness_of :email > > > > #year is required, and must be a 4 digit number greater than 2000 > > validates_presence_of :year > > validates_numericality_of :year, > > :only_integer => true > > validates_length_of :year, > > :is => 4 > > > > #turns a Person or Officer to Admin > > def turn_to_admin > > self[:type] = ''Admin'' > > #somehow update with Admin-based validations > > self > > end > > > > #turns a Person or Admin to Officer > > def turn_to_officer > > self[:type] = ''Officer'' > > #somehow update with Officer-based validations > > self > > end > > > > #technically, this does nothing > > def turn_to_person > > nil > > end > > > > protected > > > > def validate > > errors.add(:year, "should be between 2000 and 3000") if > > ( year.to_i < 2000 or year.to_i > 3000 ) > > end > > > > #completely ignore the passwords > > end > > =======Officer.rb=======> > class Officer < Person > > #take care of password thingy > > validates_length_of :password, :minimum => 5 > > > > attr_accessor :password_confirmation > > validates_confirmation_of :password > > > > #some functions > > def validate > > errors.add_to_base("Missing password") if hashed_password.blank? > > end > > > > def self.authenticate(name, password) > > person = self.find_by_rin(name) > > if person > > expected_password = encrypted_password(password, person.salt) > > if person.hashed_password!=expected_password > > person = nil > > end > > end > > person > > end > > > > def password > > @password > > end > > > > def password=(pwd) > > @password = pwd > > create_new_salt > > self.hashed_password = Officer.encrypted_password(self.password, > > self.salt) > > end > > > > #turn_to_admin is inherited from Person > > > > #This does nothing > > def turn_to_officer > > nil > > end > > > > #turns an Officer or Admin > > def turn_to_person > > self[:type] = ''Person'' > > #somehow update with Officer-based validations > > self > > end > > > > #careful of private statements > > private > > > > def self.encrypted_password(password, salt) > > string_to_hash = password + "Japan is an island of interest" + > > salt > > Digest::SHA1.hexdigest(string_to_hash) > > end > > > > def create_new_salt > > self.salt = (self.object_id * rand).to_s + rand.to_s > > end > > end > > =======Admin.rb=======> > class Admin < Officer > > > > #Make sure there''s at least one admin > > def after_destroy > > if Admin.count.zero? > > raise "Can''t delete the last admin" > > end > > end > > > > #turn_to_person is inherited by Officer > > > > #Return nil, again > > def turn_to_admin > > nil > > end > > > > #turns an Admin to Officer > > def turn_to_officer > > self[:type] = ''Officer'' > > #somehow update with Officer-based validations > > self > > end > > end > > >-- Appreciated my help? Recommend me on Working With Rails http://workingwithrails.com/person/11030-ryan-bigg --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Yeah, I did already know. It''s is why I was asking something else :-)! Anyway, I tried the reload method: ----- def test_changing_officer_to_member officer = Officer.find(:first) assert officer assert officer.update_attributes(:type => ''Person'', :password => ''Ha, ha, you cannot login!!!'', :password_confirmation => ''Ha, ha, you cannot login!!!'') officer.reload assert_equal officer.class.to_s, ''Person'' end ----- It failed miserably: ----- 1) Failure: test_changing_officer_to_member(OfficerTest) [officer_test.rb:89:in `test_changing_officer_to_member'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ active_support/testing/default.rb:7:in `run'']: <"Officer"> expected but was <"Person">. 9 tests, 22 assertions, 1 failures, 0 errors Process ruby exited with code 1 ------ Any other solutions? In addition, looking back at my test code, I noticed that: ------ def test_defective_new officer = Officer.new( :first_name => ''John'', :last_name => ''Doe'', :rin => ''doej'', :email => ''doej-IL7dBOYR4Vg@public.gmane.org'', :year => 2011, :password => ''forka'') assert officer.valid? assert_equal officer.class.to_s, ''Officer'' end ----- Passes. It shouldn''t. It should compare whether password and confirmation password is the same thing, then give out an error. Why by only giving a password, the model passes? After all, this test passes correctly: ---- def test_unequal_password_confirmation officer = Officer.new( :first_name => ''John'', :last_name => ''Doe'', :rin => ''doej'', :email => ''doej-IL7dBOYR4Vg@public.gmane.org'', :year => 2011, :password => ''jojoj'', :password_confirmation => ''kkkkk'') assert !officer.valid? assert officer.errors.invalid?(:password) end ---- Finally, random, but I''ll also like to test in "rake script/console testing". Unfortunately, the console doesn''t seem to realize I''ve downloaded the plugin "acts_as_list", nor does it seem to connect the Database really well. What can I do to fix this? I''m using InstantRails, by the way: does this have to do with anything? On May 27, 12:26 am, "Ryan Bigg (Radar)" <radarliste...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I think he''s got this already. > > What he''s trying to do is assign a person to be an Admin or an Officer. I > think all you do is self.type = "Admin and then self.reload and it might > work. > > > > On Tue, May 27, 2008 at 12:28 PM, Andres <pagla...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Single table inheritance applies perfectly to this need, > > basically you have to add a type column, > > and build the people table with all the columns that any of the three > > classes will do, > > then both admin and officer have to inherit from person, > > (I never tested double inheritance) > > so some repetition at admin and officer model may happen, > > (you can use a mixin if you want to avoid that) > > > On May 26, 4:05 pm, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > I''m trying to write an application that involves with three kinds of > > > inherited models: > > > > The lowest is Person, a model merely used as records, and nothing else > > > of importance. > > > Officer inherits from Person, and unlike Person, stores a password for > > > verification and logging in. > > > Admin inherits from Officer, and is the same as Officers except there > > > must be at least one of them. > > > > I want to make an internal method that allows me to turn a Person into > > > an Officer, an Officer to Admin, Admin to Person, etc. What''s a clean > > > method of upgrading/downgrading within this single-inheritance? > > > > Here''s the source file, as well as a quick template for what I want to > > > see happen: > > > =======Person.rb=======> > > class Person < ActiveRecord::Base > > > #first_name is required: must start with a capital > > > validates_presence_of :first_name > > > validates_format_of :first_name, > > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > #last_name is required: must start with a capital > > > validates_presence_of :last_name > > > validates_format_of :last_name, > > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > #rin is required: must be unique; also, must all be lowercases > > > #with 0 to 2 numbers following the letters. > > > validates_presence_of :rin > > > validates_format_of :rin, > > > :with => /^[a-z]+[0-9]{0,2}$/ > > > validates_uniqueness_of :rin > > > > #email must be unique, and it is required. > > > validates_presence_of :email > > > validates_format_of :email, > > > :with => /^[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-z]{2,3}){1,2}$/ > > > validates_uniqueness_of :email > > > > #year is required, and must be a 4 digit number greater than 2000 > > > validates_presence_of :year > > > validates_numericality_of :year, > > > :only_integer => true > > > validates_length_of :year, > > > :is => 4 > > > > #turns a Person or Officer to Admin > > > def turn_to_admin > > > self[:type] = ''Admin'' > > > #somehow update with Admin-based validations > > > self > > > end > > > > #turns a Person or Admin to Officer > > > def turn_to_officer > > > self[:type] = ''Officer'' > > > #somehow update with Officer-based validations > > > self > > > end > > > > #technically, this does nothing > > > def turn_to_person > > > nil > > > end > > > > protected > > > > def validate > > > errors.add(:year, "should be between 2000 and 3000") if > > > ( year.to_i < 2000 or year.to_i > 3000 ) > > > end > > > > #completely ignore the passwords > > > end > > > =======Officer.rb=======> > > class Officer < Person > > > #take care of password thingy > > > validates_length_of :password, :minimum => 5 > > > > attr_accessor :password_confirmation > > > validates_confirmation_of :password > > > > #some functions > > > def validate > > > errors.add_to_base("Missing password") if hashed_password.blank? > > > end > > > > def self.authenticate(name, password) > > > person = self.find_by_rin(name) > > > if person > > > expected_password = encrypted_password(password, person.salt) > > > if person.hashed_password!=expected_password > > > person = nil > > > end > > > end > > > person > > > end > > > > def password > > > @password > > > end > > > > def password=(pwd) > > > @password = pwd > > > create_new_salt > > > self.hashed_password = Officer.encrypted_password(self.password, > > > self.salt) > > > end > > > > #turn_to_admin is inherited from Person > > > > #This does nothing > > > def turn_to_officer > > > nil > > > end > > > > #turns an Officer or Admin > > > def turn_to_person > > > self[:type] = ''Person'' > > > #somehow update with Officer-based validations > > > self > > > end > > > > #careful of private statements > > > private > > > > def self.encrypted_password(password, salt) > > > string_to_hash = password + "Japan is an island of interest" + > > > salt > > > Digest::SHA1.hexdigest(string_to_hash) > > > end > > > > def create_new_salt > > > self.salt = (self.object_id * rand).to_s + rand.to_s > > > end > > > end > > > =======Admin.rb=======> > > class Admin < Officer > > > > #Make sure there''s at least one admin > > > def after_destroy > > > if Admin.count.zero? > > > raise "Can''t delete the last admin" > > > end > > > end > > > > #turn_to_person is inherited by Officer > > > > #Return nil, again > > > def turn_to_admin > > > nil > > > end > > > > #turns an Admin to Officer > > > def turn_to_officer > > > self[:type] = ''Officer'' > > > #somehow update with Officer-based validations > > > self > > > end > > > end > > -- > Appreciated my help? > Recommend me on Working With Railshttp://workingwithrails.com/person/11030-ryan-bigg--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Reinitialize the variable seems to be the only option then, switch the type over to Officer and then do Officer.find(@person.id) and it may work that way. On Wed, May 28, 2008 at 9:47 AM, Taro <japtar10101-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Yeah, I did already know. It''s is why I was asking something > else :-)! > Anyway, I tried the reload method: > ----- > def test_changing_officer_to_member > officer = Officer.find(:first) > assert officer > assert officer.update_attributes(:type => ''Person'', > :password => ''Ha, ha, you cannot login!!!'', > :password_confirmation => ''Ha, ha, you cannot login!!!'') > officer.reload > assert_equal officer.class.to_s, ''Person'' > end > ----- > It failed miserably: > ----- > 1) Failure: > test_changing_officer_to_member(OfficerTest) > [officer_test.rb:89:in `test_changing_officer_to_member'' > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > active_support/testing/default.rb:7:in `run'']: > <"Officer"> expected but was > <"Person">. > > 9 tests, 22 assertions, 1 failures, 0 errors > Process ruby exited with code 1 > ------ > Any other solutions? > > In addition, looking back at my test code, I noticed that: > ------ > def test_defective_new > officer = Officer.new( :first_name => ''John'', > :last_name => ''Doe'', :rin => ''doej'', > :email => ''doej-IL7dBOYR4Vg@public.gmane.org'', :year => 2011, > :password => ''forka'') > assert officer.valid? > assert_equal officer.class.to_s, ''Officer'' > end > ----- > Passes. It shouldn''t. It should compare whether password and > confirmation password is the same thing, then give out an error. Why > by only giving a password, the model passes? After all, this test > passes correctly: > ---- > def test_unequal_password_confirmation > officer = Officer.new( :first_name => ''John'', > :last_name => ''Doe'', :rin => ''doej'', > :email => ''doej-IL7dBOYR4Vg@public.gmane.org'', :year => 2011, > :password => ''jojoj'', :password_confirmation => ''kkkkk'') > assert !officer.valid? > assert officer.errors.invalid?(:password) > end > ---- > Finally, random, but I''ll also like to test in "rake script/console > testing". Unfortunately, the console doesn''t seem to realize I''ve > downloaded the plugin "acts_as_list", nor does it seem to connect the > Database really well. What can I do to fix this? I''m using > InstantRails, by the way: does this have to do with anything? > > On May 27, 12:26 am, "Ryan Bigg (Radar)" <radarliste...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > wrote: > > I think he''s got this already. > > > > What he''s trying to do is assign a person to be an Admin or an Officer. I > > think all you do is self.type = "Admin and then self.reload and it might > > work. > > > > > > > > On Tue, May 27, 2008 at 12:28 PM, Andres <pagla...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > Single table inheritance applies perfectly to this need, > > > basically you have to add a type column, > > > and build the people table with all the columns that any of the three > > > classes will do, > > > then both admin and officer have to inherit from person, > > > (I never tested double inheritance) > > > so some repetition at admin and officer model may happen, > > > (you can use a mixin if you want to avoid that) > > > > > On May 26, 4:05 pm, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > I''m trying to write an application that involves with three kinds of > > > > inherited models: > > > > > > The lowest is Person, a model merely used as records, and nothing > else > > > > of importance. > > > > Officer inherits from Person, and unlike Person, stores a password > for > > > > verification and logging in. > > > > Admin inherits from Officer, and is the same as Officers except there > > > > must be at least one of them. > > > > > > I want to make an internal method that allows me to turn a Person > into > > > > an Officer, an Officer to Admin, Admin to Person, etc. What''s a > clean > > > > method of upgrading/downgrading within this single-inheritance? > > > > > > Here''s the source file, as well as a quick template for what I want > to > > > > see happen: > > > > =======Person.rb=======> > > > class Person < ActiveRecord::Base > > > > #first_name is required: must start with a capital > > > > validates_presence_of :first_name > > > > validates_format_of :first_name, > > > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > > > #last_name is required: must start with a capital > > > > validates_presence_of :last_name > > > > validates_format_of :last_name, > > > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > > > #rin is required: must be unique; also, must all be lowercases > > > > #with 0 to 2 numbers following the letters. > > > > validates_presence_of :rin > > > > validates_format_of :rin, > > > > :with => /^[a-z]+[0-9]{0,2}$/ > > > > validates_uniqueness_of :rin > > > > > > #email must be unique, and it is required. > > > > validates_presence_of :email > > > > validates_format_of :email, > > > > :with => /^[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-z]{2,3}){1,2}$/ > > > > validates_uniqueness_of :email > > > > > > #year is required, and must be a 4 digit number greater than 2000 > > > > validates_presence_of :year > > > > validates_numericality_of :year, > > > > :only_integer => true > > > > validates_length_of :year, > > > > :is => 4 > > > > > > #turns a Person or Officer to Admin > > > > def turn_to_admin > > > > self[:type] = ''Admin'' > > > > #somehow update with Admin-based validations > > > > self > > > > end > > > > > > #turns a Person or Admin to Officer > > > > def turn_to_officer > > > > self[:type] = ''Officer'' > > > > #somehow update with Officer-based validations > > > > self > > > > end > > > > > > #technically, this does nothing > > > > def turn_to_person > > > > nil > > > > end > > > > > > protected > > > > > > def validate > > > > errors.add(:year, "should be between 2000 and 3000") if > > > > ( year.to_i < 2000 or year.to_i > 3000 ) > > > > end > > > > > > #completely ignore the passwords > > > > end > > > > =======Officer.rb=======> > > > class Officer < Person > > > > #take care of password thingy > > > > validates_length_of :password, :minimum => 5 > > > > > > attr_accessor :password_confirmation > > > > validates_confirmation_of :password > > > > > > #some functions > > > > def validate > > > > errors.add_to_base("Missing password") if hashed_password.blank? > > > > end > > > > > > def self.authenticate(name, password) > > > > person = self.find_by_rin(name) > > > > if person > > > > expected_password = encrypted_password(password, person.salt) > > > > if person.hashed_password!=expected_password > > > > person = nil > > > > end > > > > end > > > > person > > > > end > > > > > > def password > > > > @password > > > > end > > > > > > def password=(pwd) > > > > @password = pwd > > > > create_new_salt > > > > self.hashed_password = Officer.encrypted_password(self.password, > > > > self.salt) > > > > end > > > > > > #turn_to_admin is inherited from Person > > > > > > #This does nothing > > > > def turn_to_officer > > > > nil > > > > end > > > > > > #turns an Officer or Admin > > > > def turn_to_person > > > > self[:type] = ''Person'' > > > > #somehow update with Officer-based validations > > > > self > > > > end > > > > > > #careful of private statements > > > > private > > > > > > def self.encrypted_password(password, salt) > > > > string_to_hash = password + "Japan is an island of interest" + > > > > salt > > > > Digest::SHA1.hexdigest(string_to_hash) > > > > end > > > > > > def create_new_salt > > > > self.salt = (self.object_id * rand).to_s + rand.to_s > > > > end > > > > end > > > > =======Admin.rb=======> > > > class Admin < Officer > > > > > > #Make sure there''s at least one admin > > > > def after_destroy > > > > if Admin.count.zero? > > > > raise "Can''t delete the last admin" > > > > end > > > > end > > > > > > #turn_to_person is inherited by Officer > > > > > > #Return nil, again > > > > def turn_to_admin > > > > nil > > > > end > > > > > > #turns an Admin to Officer > > > > def turn_to_officer > > > > self[:type] = ''Officer'' > > > > #somehow update with Officer-based validations > > > > self > > > > end > > > > end > > > > -- > > Appreciated my help? > > Recommend me on Working With Railshttp:// > workingwithrails.com/person/11030-ryan-bigg > > >-- Appreciated my help? Recommend me on Working With Rails http://workingwithrails.com/person/11030-ryan-bigg --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Behold!!! ----- def test_changing_officer_to_member officer = Officer.find(:first) assert officer assert officer.update_attributes(:type => ''Person'', :password => ''Ha, ha, you cannot login!!!'', :password_confirmation => ''Ha, ha, you cannot login!!!'') officer.reload assert_equal officer.class.to_s, ''Person'' end def test_changing_officer_to_member2 officer = Officer.find(:first) assert officer officer.type = ''Person'' officer.reload assert_equal officer.class.to_s, ''Person'' end def test_changing_officer_to_member3 officer = Officer.find(:first) assert officer officer[:type] = ''Person'' officer.reload assert_equal officer.class.to_s, ''Person'' end def test_changing_officer_to_member4 officer = Officer.find(:first) assert officer officer[:type] = ''Person'' officer = Officer.find(officer.id) assert_equal officer.class.to_s, ''Person'' end def test_changing_officer_to_member5 officer = Officer.find(:first) assert officer officer[:type] = ''Person'' officer = Person.find(officer.id) assert_equal officer.class.to_s, ''Person'' end def test_changing_officer_to_member6 officer = Officer.find(:first) assert officer officer.type = ''Person'' officer = Person.find(officer.id) assert_equal officer.class.to_s, ''Person'' end ----- 1) Failure: test_changing_officer_to_member(OfficerTest) [officer_test.rb:90:in `test_changing_officer_to_member'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ active_support/testing/default.rb:7:in `run'']: <"Officer"> expected but was <"Person">. 2) Failure: test_changing_officer_to_member2(OfficerTest) [officer_test.rb:98:in `test_changing_officer_to_member2'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ active_support/testing/default.rb:7:in `run'']: <"Officer"> expected but was <"Person">. 3) Failure: test_changing_officer_to_member3(OfficerTest) [officer_test.rb:106:in `test_changing_officer_to_member3'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ active_support/testing/default.rb:7:in `run'']: <"Officer"> expected but was <"Person">. 4) Failure: test_changing_officer_to_member4(OfficerTest) [officer_test.rb:114:in `test_changing_officer_to_member4'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ active_support/testing/default.rb:7:in `run'']: <"Officer"> expected but was <"Person">. 5) Failure: test_changing_officer_to_member5(OfficerTest) [officer_test.rb:122:in `test_changing_officer_to_member5'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ active_support/testing/default.rb:7:in `run'']: <"Officer"> expected but was <"Person">. 6) Failure: test_changing_officer_to_member6(OfficerTest) [officer_test.rb:130:in `test_changing_officer_to_member6'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ active_support/testing/default.rb:7:in `run'']: <"Officer"> expected but was <"Person">. On May 27, 8:19 pm, "Ryan Bigg (Radar)" <radarliste...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Reinitialize the variable seems to be the only option then, switch the type > over to Officer and then do Officer.find(@person.id) and it may work that > way. > > > > On Wed, May 28, 2008 at 9:47 AM, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Yeah, I did already know. It''s is why I was asking something > > else :-)! > > Anyway, I tried the reload method: > > ----- > > def test_changing_officer_to_member > > officer = Officer.find(:first) > > assert officer > > assert officer.update_attributes(:type => ''Person'', > > :password => ''Ha, ha, you cannot login!!!'', > > :password_confirmation => ''Ha, ha, you cannot login!!!'') > > officer.reload > > assert_equal officer.class.to_s, ''Person'' > > end > > ----- > > It failed miserably: > > ----- > > 1) Failure: > > test_changing_officer_to_member(OfficerTest) > > [officer_test.rb:89:in `test_changing_officer_to_member'' > > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > > active_support/testing/default.rb:7:in `run'']: > > <"Officer"> expected but was > > <"Person">. > > > 9 tests, 22 assertions, 1 failures, 0 errors > > Process ruby exited with code 1 > > ------ > > Any other solutions? > > > In addition, looking back at my test code, I noticed that: > > ------ > > def test_defective_new > > officer = Officer.new( :first_name => ''John'', > > :last_name => ''Doe'', :rin => ''doej'', > > :email => ''d...-IL7dBOYR4Vg@public.gmane.org'', :year => 2011, > > :password => ''forka'') > > assert officer.valid? > > assert_equal officer.class.to_s, ''Officer'' > > end > > ----- > > Passes. It shouldn''t. It should compare whether password and > > confirmation password is the same thing, then give out an error. Why > > by only giving a password, the model passes? After all, this test > > passes correctly: > > ---- > > def test_unequal_password_confirmation > > officer = Officer.new( :first_name => ''John'', > > :last_name => ''Doe'', :rin => ''doej'', > > :email => ''d...-IL7dBOYR4Vg@public.gmane.org'', :year => 2011, > > :password => ''jojoj'', :password_confirmation => ''kkkkk'') > > assert !officer.valid? > > assert officer.errors.invalid?(:password) > > end > > ---- > > Finally, random, but I''ll also like to test in "rake script/console > > testing". Unfortunately, the console doesn''t seem to realize I''ve > > downloaded the plugin "acts_as_list", nor does it seem to connect the > > Database really well. What can I do to fix this? I''m using > > InstantRails, by the way: does this have to do with anything? > > > On May 27, 12:26 am, "Ryan Bigg (Radar)" <radarliste...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > > wrote: > > > I think he''s got this already. > > > > What he''s trying to do is assign a person to be an Admin or an Officer. I > > > think all you do is self.type = "Admin and then self.reload and it might > > > work. > > > > On Tue, May 27, 2008 at 12:28 PM, Andres <pagla...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > Single table inheritance applies perfectly to this need, > > > > basically you have to add a type column, > > > > and build the people table with all the columns that any of the three > > > > classes will do, > > > > then both admin and officer have to inherit from person, > > > > (I never tested double inheritance) > > > > so some repetition at admin and officer model may happen, > > > > (you can use a mixin if you want to avoid that) > > > > > On May 26, 4:05 pm, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > I''m trying to write an application that involves with three kinds of > > > > > inherited models: > > > > > > The lowest is Person, a model merely used as records, and nothing > > else > > > > > of importance. > > > > > Officer inherits from Person, and unlike Person, stores a password > > for > > > > > verification and logging in. > > > > > Admin inherits from Officer, and is the same as Officers except there > > > > > must be at least one of them. > > > > > > I want to make an internal method that allows me to turn a Person > > into > > > > > an Officer, an Officer to Admin, Admin to Person, etc. What''s a > > clean > > > > > method of upgrading/downgrading within this single-inheritance? > > > > > > Here''s the source file, as well as a quick template for what I want > > to > > > > > see happen: > > > > > =======Person.rb=======> > > > > class Person < ActiveRecord::Base > > > > > #first_name is required: must start with a capital > > > > > validates_presence_of :first_name > > > > > validates_format_of :first_name, > > > > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > > > #last_name is required: must start with a capital > > > > > validates_presence_of :last_name > > > > > validates_format_of :last_name, > > > > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > > > #rin is required: must be unique; also, must all be lowercases > > > > > #with 0 to 2 numbers following the letters. > > > > > validates_presence_of :rin > > > > > validates_format_of :rin, > > > > > :with => /^[a-z]+[0-9]{0,2}$/ > > > > > validates_uniqueness_of :rin > > > > > > #email must be unique, and it is required. > > > > > validates_presence_of :email > > > > > validates_format_of :email, > > > > > :with => /^[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-z]{2,3}){1,2}$/ > > > > > validates_uniqueness_of :email > > > > > > #year is required, and must be a 4 digit number greater than 2000 > > > > > validates_presence_of :year > > > > > validates_numericality_of :year, > > > > > :only_integer => true > > > > > validates_length_of :year, > > > > > :is => 4 > > > > > > #turns a Person or Officer to Admin > > > > > def turn_to_admin > > > > > self[:type] = ''Admin'' > > > > > #somehow update with Admin-based validations > > > > > self > > > > > end > > > > > > #turns a Person or Admin to Officer > > > > > def turn_to_officer > > > > > self[:type] = ''Officer'' > > > > > #somehow update with Officer-based validations > > > > > self > > > > > end > > > > > > #technically, this does nothing > > > > > def turn_to_person > > > > > nil > > > > > end > > > > > > protected > > > > > > def validate > > > > > errors.add(:year, "should be between 2000 and 3000") if > > > > > ( year.to_i < 2000 or year.to_i > 3000 ) > > > > > end > > > > > > #completely ignore the passwords > > > > > end > > > > > =======Officer.rb=======> > > > > class Officer < Person > > > > > #take care of password thingy > > > > > validates_length_of :password, :minimum => 5 > > > > > > attr_accessor :password_confirmation > > > > > validates_confirmation_of :password > > > > > > #some functions > > > > > def validate > > > > > errors.add_to_base("Missing password") if hashed_password.blank? > > > > > end > > > > > > def self.authenticate(name, password) > > > > > person = self.find_by_rin(name) > > > > > if person > > > > > expected_password = encrypted_password(password, person.salt) > > > > > if person.hashed_password!=expected_password > > > > > person = nil > > > > > end > > > > > end > > > > > person > > > > > end > > > > > > def password > > > > > @password > > > > > end > > > > > > def password=(pwd) > > > > > @password = pwd > > > > > create_new_salt > > > > > self.hashed_password = Officer.encrypted_password(self.password, > > > > > self.salt) > > > > > end > > > > > > #turn_to_admin is inherited from Person > > > > > > #This does nothing > > > > > def turn_to_officer > > > > > nil > > > > > end > > > > > > #turns an Officer or Admin > > > > > def turn_to_person > > > > > self[:type] = ''Person'' > > > > > #somehow update with Officer-based validations > > > > > self > > > > > end > > > > > > #careful of private statements > > > > > private > > > > > > def self.encrypted_password(password, salt) > > > > > string_to_hash = password + "Japan is an island of interest" + > > > > > salt > > > > > Digest::SHA1.hexdigest(string_to_hash) > > > > > end > > > > > > def create_new_salt > > > > > self.salt = (self.object_id * rand).to_s + rand.to_s > > > > > end > > > > > end > > > > > =======Admin.rb=======> > > > > class Admin < Officer > > > > > > #Make sure there''s at least one admin > > > > > def after_destroy > > > > > if Admin.count.zero? > > > > > raise "Can''t delete the last admin" > > > > > end > > > > > end > > > > > > #turn_to_person is inherited by Officer > > > > > > #Return nil, again > > > > > def turn_to_admin > > > > > nil > > > > > end > > > > > > #turns an Admin to Officer > > > > > def turn_to_officer > > > > > self[:type] = ''Officer'' > > > > > #somehow update with Officer-based validations > > > > > self > > > > > end > > > > > end > > > > -- > > > Appreciated my help? > > > Recommend me on Working With Railshttp:// > > workingwithrails.com/person/11030-ryan-bigg > > -- > Appreciated my help? > Recommend me on Working With Railshttp://workingwithrails.com/person/11030-ryan-bigg--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Your test is wrong. You should be doing: person = Person.find(id) person.type = "Officer" person.save officer = Officer.find(id) officer.class == Officer And that will return true. On Wed, May 28, 2008 at 9:55 AM, Taro <japtar10101-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Behold!!! > > ----- > def test_changing_officer_to_member > officer = Officer.find(:first) > assert officer > assert officer.update_attributes(:type => ''Person'', > :password => ''Ha, ha, you cannot login!!!'', > :password_confirmation => ''Ha, ha, you cannot login!!!'') > officer.reload > assert_equal officer.class.to_s, ''Person'' > end > > def test_changing_officer_to_member2 > officer = Officer.find(:first) > assert officer > officer.type = ''Person'' > officer.reload > assert_equal officer.class.to_s, ''Person'' > end > > def test_changing_officer_to_member3 > officer = Officer.find(:first) > assert officer > officer[:type] = ''Person'' > officer.reload > assert_equal officer.class.to_s, ''Person'' > end > > def test_changing_officer_to_member4 > officer = Officer.find(:first) > assert officer > officer[:type] = ''Person'' > officer = Officer.find(officer.id) > assert_equal officer.class.to_s, ''Person'' > end > > def test_changing_officer_to_member5 > officer = Officer.find(:first) > assert officer > officer[:type] = ''Person'' > officer = Person.find(officer.id) > assert_equal officer.class.to_s, ''Person'' > end > > def test_changing_officer_to_member6 > officer = Officer.find(:first) > assert officer > officer.type = ''Person'' > officer = Person.find(officer.id) > assert_equal officer.class.to_s, ''Person'' > end > ----- > > > 1) Failure: > test_changing_officer_to_member(OfficerTest) > [officer_test.rb:90:in `test_changing_officer_to_member'' > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > active_support/testing/default.rb:7:in `run'']: > <"Officer"> expected but was > <"Person">. > > 2) Failure: > test_changing_officer_to_member2(OfficerTest) > [officer_test.rb:98:in `test_changing_officer_to_member2'' > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > active_support/testing/default.rb:7:in `run'']: > <"Officer"> expected but was > <"Person">. > > 3) Failure: > test_changing_officer_to_member3(OfficerTest) > [officer_test.rb:106:in `test_changing_officer_to_member3'' > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > active_support/testing/default.rb:7:in `run'']: > <"Officer"> expected but was > <"Person">. > > 4) Failure: > test_changing_officer_to_member4(OfficerTest) > [officer_test.rb:114:in `test_changing_officer_to_member4'' > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > active_support/testing/default.rb:7:in `run'']: > <"Officer"> expected but was > <"Person">. > > 5) Failure: > test_changing_officer_to_member5(OfficerTest) > [officer_test.rb:122:in `test_changing_officer_to_member5'' > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > active_support/testing/default.rb:7:in `run'']: > <"Officer"> expected but was > <"Person">. > > 6) Failure: > test_changing_officer_to_member6(OfficerTest) > [officer_test.rb:130:in `test_changing_officer_to_member6'' > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > active_support/testing/default.rb:7:in `run'']: > <"Officer"> expected but was > <"Person">. > > On May 27, 8:19 pm, "Ryan Bigg (Radar)" <radarliste...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > wrote: > > Reinitialize the variable seems to be the only option then, switch the > type > > over to Officer and then do Officer.find(@person.id) and it may work > that > > way. > > > > > > > > On Wed, May 28, 2008 at 9:47 AM, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > Yeah, I did already know. It''s is why I was asking something > > > else :-)! > > > Anyway, I tried the reload method: > > > ----- > > > def test_changing_officer_to_member > > > officer = Officer.find(:first) > > > assert officer > > > assert officer.update_attributes(:type => ''Person'', > > > :password => ''Ha, ha, you cannot login!!!'', > > > :password_confirmation => ''Ha, ha, you cannot login!!!'') > > > officer.reload > > > assert_equal officer.class.to_s, ''Person'' > > > end > > > ----- > > > It failed miserably: > > > ----- > > > 1) Failure: > > > test_changing_officer_to_member(OfficerTest) > > > [officer_test.rb:89:in `test_changing_officer_to_member'' > > > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > > > active_support/testing/default.rb:7:in `run'']: > > > <"Officer"> expected but was > > > <"Person">. > > > > > 9 tests, 22 assertions, 1 failures, 0 errors > > > Process ruby exited with code 1 > > > ------ > > > Any other solutions? > > > > > In addition, looking back at my test code, I noticed that: > > > ------ > > > def test_defective_new > > > officer = Officer.new( :first_name => ''John'', > > > :last_name => ''Doe'', :rin => ''doej'', > > > :email => ''d...-IL7dBOYR4Vg@public.gmane.org'', :year => 2011, > > > :password => ''forka'') > > > assert officer.valid? > > > assert_equal officer.class.to_s, ''Officer'' > > > end > > > ----- > > > Passes. It shouldn''t. It should compare whether password and > > > confirmation password is the same thing, then give out an error. Why > > > by only giving a password, the model passes? After all, this test > > > passes correctly: > > > ---- > > > def test_unequal_password_confirmation > > > officer = Officer.new( :first_name => ''John'', > > > :last_name => ''Doe'', :rin => ''doej'', > > > :email => ''d...-IL7dBOYR4Vg@public.gmane.org'', :year => 2011, > > > :password => ''jojoj'', :password_confirmation => ''kkkkk'') > > > assert !officer.valid? > > > assert officer.errors.invalid?(:password) > > > end > > > ---- > > > Finally, random, but I''ll also like to test in "rake script/console > > > testing". Unfortunately, the console doesn''t seem to realize I''ve > > > downloaded the plugin "acts_as_list", nor does it seem to connect the > > > Database really well. What can I do to fix this? I''m using > > > InstantRails, by the way: does this have to do with anything? > > > > > On May 27, 12:26 am, "Ryan Bigg (Radar)" <radarliste...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > > > wrote: > > > > I think he''s got this already. > > > > > > What he''s trying to do is assign a person to be an Admin or an > Officer. I > > > > think all you do is self.type = "Admin and then self.reload and it > might > > > > work. > > > > > > On Tue, May 27, 2008 at 12:28 PM, Andres <pagla...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > > Single table inheritance applies perfectly to this need, > > > > > basically you have to add a type column, > > > > > and build the people table with all the columns that any of the > three > > > > > classes will do, > > > > > then both admin and officer have to inherit from person, > > > > > (I never tested double inheritance) > > > > > so some repetition at admin and officer model may happen, > > > > > (you can use a mixin if you want to avoid that) > > > > > > > On May 26, 4:05 pm, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > I''m trying to write an application that involves with three kinds > of > > > > > > inherited models: > > > > > > > > The lowest is Person, a model merely used as records, and nothing > > > else > > > > > > of importance. > > > > > > Officer inherits from Person, and unlike Person, stores a > password > > > for > > > > > > verification and logging in. > > > > > > Admin inherits from Officer, and is the same as Officers except > there > > > > > > must be at least one of them. > > > > > > > > I want to make an internal method that allows me to turn a Person > > > into > > > > > > an Officer, an Officer to Admin, Admin to Person, etc. What''s a > > > clean > > > > > > method of upgrading/downgrading within this single-inheritance? > > > > > > > > Here''s the source file, as well as a quick template for what I > want > > > to > > > > > > see happen: > > > > > > =======Person.rb=======> > > > > > class Person < ActiveRecord::Base > > > > > > #first_name is required: must start with a capital > > > > > > validates_presence_of :first_name > > > > > > validates_format_of :first_name, > > > > > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > > > > > #last_name is required: must start with a capital > > > > > > validates_presence_of :last_name > > > > > > validates_format_of :last_name, > > > > > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > > > > > #rin is required: must be unique; also, must all be lowercases > > > > > > #with 0 to 2 numbers following the letters. > > > > > > validates_presence_of :rin > > > > > > validates_format_of :rin, > > > > > > :with => /^[a-z]+[0-9]{0,2}$/ > > > > > > validates_uniqueness_of :rin > > > > > > > > #email must be unique, and it is required. > > > > > > validates_presence_of :email > > > > > > validates_format_of :email, > > > > > > :with => /^[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-z]{2,3}){1,2}$/ > > > > > > validates_uniqueness_of :email > > > > > > > > #year is required, and must be a 4 digit number greater than > 2000 > > > > > > validates_presence_of :year > > > > > > validates_numericality_of :year, > > > > > > :only_integer => true > > > > > > validates_length_of :year, > > > > > > :is => 4 > > > > > > > > #turns a Person or Officer to Admin > > > > > > def turn_to_admin > > > > > > self[:type] = ''Admin'' > > > > > > #somehow update with Admin-based validations > > > > > > self > > > > > > end > > > > > > > > #turns a Person or Admin to Officer > > > > > > def turn_to_officer > > > > > > self[:type] = ''Officer'' > > > > > > #somehow update with Officer-based validations > > > > > > self > > > > > > end > > > > > > > > #technically, this does nothing > > > > > > def turn_to_person > > > > > > nil > > > > > > end > > > > > > > > protected > > > > > > > > def validate > > > > > > errors.add(:year, "should be between 2000 and 3000") if > > > > > > ( year.to_i < 2000 or year.to_i > 3000 ) > > > > > > end > > > > > > > > #completely ignore the passwords > > > > > > end > > > > > > =======Officer.rb=======> > > > > > class Officer < Person > > > > > > #take care of password thingy > > > > > > validates_length_of :password, :minimum => 5 > > > > > > > > attr_accessor :password_confirmation > > > > > > validates_confirmation_of :password > > > > > > > > #some functions > > > > > > def validate > > > > > > errors.add_to_base("Missing password") if > hashed_password.blank? > > > > > > end > > > > > > > > def self.authenticate(name, password) > > > > > > person = self.find_by_rin(name) > > > > > > if person > > > > > > expected_password = encrypted_password(password, > person.salt) > > > > > > if person.hashed_password!=expected_password > > > > > > person = nil > > > > > > end > > > > > > end > > > > > > person > > > > > > end > > > > > > > > def password > > > > > > @password > > > > > > end > > > > > > > > def password=(pwd) > > > > > > @password = pwd > > > > > > create_new_salt > > > > > > self.hashed_password > Officer.encrypted_password(self.password, > > > > > > self.salt) > > > > > > end > > > > > > > > #turn_to_admin is inherited from Person > > > > > > > > #This does nothing > > > > > > def turn_to_officer > > > > > > nil > > > > > > end > > > > > > > > #turns an Officer or Admin > > > > > > def turn_to_person > > > > > > self[:type] = ''Person'' > > > > > > #somehow update with Officer-based validations > > > > > > self > > > > > > end > > > > > > > > #careful of private statements > > > > > > private > > > > > > > > def self.encrypted_password(password, salt) > > > > > > string_to_hash = password + "Japan is an island of interest" > + > > > > > > salt > > > > > > Digest::SHA1.hexdigest(string_to_hash) > > > > > > end > > > > > > > > def create_new_salt > > > > > > self.salt = (self.object_id * rand).to_s + rand.to_s > > > > > > end > > > > > > end > > > > > > =======Admin.rb=======> > > > > > class Admin < Officer > > > > > > > > #Make sure there''s at least one admin > > > > > > def after_destroy > > > > > > if Admin.count.zero? > > > > > > raise "Can''t delete the last admin" > > > > > > end > > > > > > end > > > > > > > > #turn_to_person is inherited by Officer > > > > > > > > #Return nil, again > > > > > > def turn_to_admin > > > > > > nil > > > > > > end > > > > > > > > #turns an Admin to Officer > > > > > > def turn_to_officer > > > > > > self[:type] = ''Officer'' > > > > > > #somehow update with Officer-based validations > > > > > > self > > > > > > end > > > > > > end > > > > > > -- > > > > Appreciated my help? > > > > Recommend me on Working With Railshttp:// > > > workingwithrails.com/person/11030-ryan-bigg > > > > -- > > Appreciated my help? > > Recommend me on Working With Railshttp:// > workingwithrails.com/person/11030-ryan-bigg > > >-- Appreciated my help? Recommend me on Working With Rails http://workingwithrails.com/person/11030-ryan-bigg --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Oh, whoops. Anyway, it did work. I''m curious about why "person.type = " works. I read somewhere that the correct syntax should be "person[:type] = ", due to the fact that ".type" is a (deprecated) class method. On May 27, 9:33 pm, "Ryan Bigg (Radar)" <radarliste...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Your test is wrong. You should be doing: > > person = Person.find(id) > person.type = "Officer" > person.save > officer = Officer.find(id) > officer.class == Officer > > And that will return true. > > On Wed, May 28, 2008 at 9:55 AM, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Behold!!! > > > ----- > > def test_changing_officer_to_member > > officer = Officer.find(:first) > > assert officer > > assert officer.update_attributes(:type => ''Person'', > > :password => ''Ha, ha, you cannot login!!!'', > > :password_confirmation => ''Ha, ha, you cannot login!!!'') > > officer.reload > > assert_equal officer.class.to_s, ''Person'' > > end > > > def test_changing_officer_to_member2 > > officer = Officer.find(:first) > > assert officer > > officer.type = ''Person'' > > officer.reload > > assert_equal officer.class.to_s, ''Person'' > > end > > > def test_changing_officer_to_member3 > > officer = Officer.find(:first) > > assert officer > > officer[:type] = ''Person'' > > officer.reload > > assert_equal officer.class.to_s, ''Person'' > > end > > > def test_changing_officer_to_member4 > > officer = Officer.find(:first) > > assert officer > > officer[:type] = ''Person'' > > officer = Officer.find(officer.id) > > assert_equal officer.class.to_s, ''Person'' > > end > > > def test_changing_officer_to_member5 > > officer = Officer.find(:first) > > assert officer > > officer[:type] = ''Person'' > > officer = Person.find(officer.id) > > assert_equal officer.class.to_s, ''Person'' > > end > > > def test_changing_officer_to_member6 > > officer = Officer.find(:first) > > assert officer > > officer.type = ''Person'' > > officer = Person.find(officer.id) > > assert_equal officer.class.to_s, ''Person'' > > end > > ----- > > > 1) Failure: > > test_changing_officer_to_member(OfficerTest) > > [officer_test.rb:90:in `test_changing_officer_to_member'' > > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > > active_support/testing/default.rb:7:in `run'']: > > <"Officer"> expected but was > > <"Person">. > > > 2) Failure: > > test_changing_officer_to_member2(OfficerTest) > > [officer_test.rb:98:in `test_changing_officer_to_member2'' > > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > > active_support/testing/default.rb:7:in `run'']: > > <"Officer"> expected but was > > <"Person">. > > > 3) Failure: > > test_changing_officer_to_member3(OfficerTest) > > [officer_test.rb:106:in `test_changing_officer_to_member3'' > > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > > active_support/testing/default.rb:7:in `run'']: > > <"Officer"> expected but was > > <"Person">. > > > 4) Failure: > > test_changing_officer_to_member4(OfficerTest) > > [officer_test.rb:114:in `test_changing_officer_to_member4'' > > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > > active_support/testing/default.rb:7:in `run'']: > > <"Officer"> expected but was > > <"Person">. > > > 5) Failure: > > test_changing_officer_to_member5(OfficerTest) > > [officer_test.rb:122:in `test_changing_officer_to_member5'' > > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > > active_support/testing/default.rb:7:in `run'']: > > <"Officer"> expected but was > > <"Person">. > > > 6) Failure: > > test_changing_officer_to_member6(OfficerTest) > > [officer_test.rb:130:in `test_changing_officer_to_member6'' > > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > > active_support/testing/default.rb:7:in `run'']: > > <"Officer"> expected but was > > <"Person">. > > > On May 27, 8:19 pm, "Ryan Bigg (Radar)" <radarliste...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > > wrote: > > > Reinitialize the variable seems to be the only option then, switch the > > type > > > over to Officer and then do Officer.find(@person.id) and it may work > > that > > > way. > > > > On Wed, May 28, 2008 at 9:47 AM, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > Yeah, I did already know. It''s is why I was asking something > > > > else :-)! > > > > Anyway, I tried the reload method: > > > > ----- > > > > def test_changing_officer_to_member > > > > officer = Officer.find(:first) > > > > assert officer > > > > assert officer.update_attributes(:type => ''Person'', > > > > :password => ''Ha, ha, you cannot login!!!'', > > > > :password_confirmation => ''Ha, ha, you cannot login!!!'') > > > > officer.reload > > > > assert_equal officer.class.to_s, ''Person'' > > > > end > > > > ----- > > > > It failed miserably: > > > > ----- > > > > 1) Failure: > > > > test_changing_officer_to_member(OfficerTest) > > > > [officer_test.rb:89:in `test_changing_officer_to_member'' > > > > c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2-/lib/ > > > > active_support/testing/default.rb:7:in `run'']: > > > > <"Officer"> expected but was > > > > <"Person">. > > > > > 9 tests, 22 assertions, 1 failures, 0 errors > > > > Process ruby exited with code 1 > > > > ------ > > > > Any other solutions? > > > > > In addition, looking back at my test code, I noticed that: > > > > ------ > > > > def test_defective_new > > > > officer = Officer.new( :first_name => ''John'', > > > > :last_name => ''Doe'', :rin => ''doej'', > > > > :email => ''d...-IL7dBOYR4Vg@public.gmane.org'', :year => 2011, > > > > :password => ''forka'') > > > > assert officer.valid? > > > > assert_equal officer.class.to_s, ''Officer'' > > > > end > > > > ----- > > > > Passes. It shouldn''t. It should compare whether password and > > > > confirmation password is the same thing, then give out an error. Why > > > > by only giving a password, the model passes? After all, this test > > > > passes correctly: > > > > ---- > > > > def test_unequal_password_confirmation > > > > officer = Officer.new( :first_name => ''John'', > > > > :last_name => ''Doe'', :rin => ''doej'', > > > > :email => ''d...-IL7dBOYR4Vg@public.gmane.org'', :year => 2011, > > > > :password => ''jojoj'', :password_confirmation => ''kkkkk'') > > > > assert !officer.valid? > > > > assert officer.errors.invalid?(:password) > > > > end > > > > ---- > > > > Finally, random, but I''ll also like to test in "rake script/console > > > > testing". Unfortunately, the console doesn''t seem to realize I''ve > > > > downloaded the plugin "acts_as_list", nor does it seem to connect the > > > > Database really well. What can I do to fix this? I''m using > > > > InstantRails, by the way: does this have to do with anything? > > > > > On May 27, 12:26 am, "Ryan Bigg (Radar)" <radarliste...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > > > > wrote: > > > > > I think he''s got this already. > > > > > > What he''s trying to do is assign a person to be an Admin or an > > Officer. I > > > > > think all you do is self.type = "Admin and then self.reload and it > > might > > > > > work. > > > > > > On Tue, May 27, 2008 at 12:28 PM, Andres <pagla...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > > Single table inheritance applies perfectly to this need, > > > > > > basically you have to add a type column, > > > > > > and build the people table with all the columns that any of the > > three > > > > > > classes will do, > > > > > > then both admin and officer have to inherit from person, > > > > > > (I never tested double inheritance) > > > > > > so some repetition at admin and officer model may happen, > > > > > > (you can use a mixin if you want to avoid that) > > > > > > > On May 26, 4:05 pm, Taro <japtar10...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > > I''m trying to write an application that involves with three kinds > > of > > > > > > > inherited models: > > > > > > > > The lowest is Person, a model merely used as records, and nothing > > > > else > > > > > > > of importance. > > > > > > > Officer inherits from Person, and unlike Person, stores a > > password > > > > for > > > > > > > verification and logging in. > > > > > > > Admin inherits from Officer, and is the same as Officers except > > there > > > > > > > must be at least one of them. > > > > > > > > I want to make an internal method that allows me to turn a Person > > > > into > > > > > > > an Officer, an Officer to Admin, Admin to Person, etc. What''s a > > > > clean > > > > > > > method of upgrading/downgrading within this single-inheritance? > > > > > > > > Here''s the source file, as well as a quick template for what I > > want > > > > to > > > > > > > see happen: > > > > > > > =======Person.rb=======> > > > > > > class Person < ActiveRecord::Base > > > > > > > #first_name is required: must start with a capital > > > > > > > validates_presence_of :first_name > > > > > > > validates_format_of :first_name, > > > > > > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > > > > > #last_name is required: must start with a capital > > > > > > > validates_presence_of :last_name > > > > > > > validates_format_of :last_name, > > > > > > > :with => /^[A-Z][a-zA-Z0-9, .]+$/ > > > > > > > > #rin is required: must be unique; also, must all be lowercases > > > > > > > #with 0 to 2 numbers following the letters. > > > > > > > validates_presence_of :rin > > > > > > > validates_format_of :rin, > > > > > > > :with => /^[a-z]+[0-9]{0,2}$/ > > > > > > > validates_uniqueness_of :rin > > > > > > > > #email must be unique, and it is required. > > > > > > > validates_presence_of :email > > > > > > > validates_format_of :email, > > > > > > > :with => /^[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-z]{2,3}){1,2}$/ > > > > > > > validates_uniqueness_of :email > > > > > > > > #year is required, and must be a 4 digit number greater than > > 2000 > > > > > > > validates_presence_of :year > > > > > > > validates_numericality_of :year, > > > > > > > :only_integer => true > > > > > > > validates_length_of :year, > > > > > > > :is => 4 > > > > > > > > #turns a Person or Officer to Admin > > > > > > > def turn_to_admin > > > > > > > self[:type] = ''Admin'' > > > > > > > #somehow update with Admin-based validations > > > > > > > self > > > > > > > end > > > > > > > > #turns a Person or Admin to Officer > > > > > > > def turn_to_officer > > > > > > > self[:type] = ''Officer'' > > > > > > > #somehow update with Officer-based validations > > > > > > > self > > > > > > > end > > > > > > > > #technically, this does nothing > > > > > > > def turn_to_person > > ... > > read more »--~--~---------~--~----~------------~-------~--~----~ 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@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---