# Class\_cache has got me stumped

**URL:** <https://www.ruby-forum.com/t/class-cache-has-got-me-stumped/110158>\
**Category:** Rails\
**Created:** [July 23, 2007, 9:13pm UTC](https://www.ruby-forum.com/t/class-cache-has-got-me-stumped/110158 "2007-07-23T21:13:32Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nicholas\_Barthelemy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/b77776/32.png) [@Nicholas\_Barthelemy](https://www.ruby-forum.com/u/Nicholas_Barthelemy)\
**Post date:** [July 23, 2007, 9:13pm UTC](https://www.ruby-forum.com/t/class-cache-has-got-me-stumped/110158/1 "2007-07-23T21:13:32Z")

</div>

I was working on a project this weekend and came across an issue that  
hung me up for hours. The application will have an area to manage  
contacts, so I have a Person model, which has\_many email\_addresses,  
among other things. So in order to add another email\_address to my  
form using rjs, I send a request to the ContactMethodsController with  
a the type param set to email\_address. It renders the rjs, which  
renders a partial and inserts it into my form. In order to accomplish  
this I needed to generate a temporary ID for each email address so I  
could use them in a form, generate urls with them, and when/if errors  
occur the id would remain the same so the form could pick up the  
errors. I do not want to save the models unless they are filled in.  
This scheme works wonderfully in development, but when I push it to  
production, it breaks because the generated id becomes nil after an  
action other than index/new is run in the PeopleController. The index  
action can be refreshed, but as soon as another action is called it  
blows up.

class Person \< ActiveRecord::Base

with\_options :dependent =\> :destroy do |person|  
person.has\_many :phone\_numbers, :as =\> :phoneable  
person.has\_many :email\_addresses, :as =\> :emailable  
person.has\_many :addresses, :as =\> :addressable  
end

def update\_contact\_methods(data)  
result = {}  
[:email\_addresses, :phone\_numbers, :addresses].collect do |c|  
klass = c.to\_s.classify.constantize  
x = c.to\_s.singularize.split(’\_’)[0]

```
klass.transaction do
unless new_record?
  klass.destroy_all("#{x}able_id = #{self.id} AND #{x}able_type =

```

‘#{self.class}’")  
end  
result[c] = data[c].values.collect{|v|  
klass.new(v) }.delete\_if(&:blank?)  
end  
end  
update\_attributes(result)  
end

def update\_from\_params(person\_params)  
contact\_params = person\_params.delete(:contact\_data)

update\_attributes(person\_params)  
reload

update\_contact\_methods(contact\_params)

errors.empty?  
end

def set\_place\_holder\_data

# give the person a temp id

self.id ||= 0

# add an address it there is none

self.addresses = [self.addresses.build] if self.addresses.empty?

# add phone numbers if we have none

self.email\_addresses = [self.email\_addresses.build] if  
self.email\_addresses.empty?

# add phone numbers if we have none

self.phone\_numbers = [self.phone\_numbers.build] if  
self.phone\_numbers.empty?  
end

end

Note that when set\_place\_holder\_data is called a temporary id of 0 is  
set if the id is not set and we add a dummy email\_address if one does  
not exist, so the fields show up on the form.

[code=]class EmailAddress \< ActiveRecord::Base

##### Associations

belongs\_to :emailable, :polymorphic =\> true

##### Attributes

cattr\_reader :locations  
@@locations = %w(HOME WORK OTHER)

##### Validation

validates\_length\_of :address, :within =\> 7…80  
validates\_format\_of :address, :with =\> /^([^@\s]+)@((?:[-a-z0-9]+.)+  
[a-z]{2,})$/

##### Class Methods

##### Instance Methods

def generated\_identifier  
@generated\_identifier ||= generate\_identifier  
end

def id\_with\_generated\_identifier  
new\_record? ? generated\_identifier : id\_without\_generated\_identifier  
end  
alias\_method\_chain :id, :generated\_identifier

def blank?  
address.blank?  
end

private

def generate\_identifier(len=10)  
chars = (“a”…“z”).to\_a + (1…9).to\_a  
identifier = “”  
1.upto(len){|i| identifier += chars[rand(chars.size-1)].to\_s }  
identifier  
end

end

Note that the EmailAddress model generates an ID for itself if it is a  
new record. this is done so I can generate urls using named routes and  
a dom\_id for the object on a form where there may be a couple “new”  
EmailAddresses. For example in a view I would:

\<%= link\_to "Delete", person\_contact\_method\_url(@person, email\_address) + "?type=email\_address", :method =\> :delete %\>
[/code] The dom\_id would be: email\_address\_894j5jksl The url would be: /person/0/contact\_methods/894j5jksl? type=email\_address

class PeopleController \< ApplicationController

helper :contact\_methods

# GET /people

def index

# preload the new form

@person = provider.new

# set place holder data for the form

@person.set\_place\_holder\_data

# get all of the contacts with eagerly loaded data

```
@people = provider.find_roots(:all)

respond_to do |format|
  format.html # index.rhtml
  format.xml { render :xml => @people.to_xml }
end

```

end

# GET /people/1

def show  
@person = provider.find\_with\_includes(params[:id])

```
respond_to do |format|
  format.html # show.rhtml
  format.xml { render :xml => @person.to_xml }
end

```

end

# POST /people

def create  
@person = provider.new

```
respond_to do |format|
  if @person.update_from_params(params[:person])
    flash[:notice] = 'Contact was successfully created.'
format.js {}
  else
format.js {
  render :update do |page|
  page[:new_person_form_errors].replace_html

```

error\_messages\_for(:person)  
end  
}  
end  
end  
end

# GET /people/1/edit

def edit  
@person = provider.find\_and\_set\_place\_holders(params[:id])  
end

# PUT /people/1

def update  
@person = provider.find(params[:id])

```
respond_to do |format|
  if @person.update_from_params(params[:person])
    flash[:notice] = 'Contact was successfully updated.'
format.js
    format.html { redirect_to people_url }
  else
    format.html { render :action => "edit" }
  end
end

```

end

private

def provider  
current\_account.people  
end

end

class ContactMethodsController \< ApplicationController

def new  
@object = provider.new  
respond\_to do |format|  
format.js  
end  
end

def destroy  
if params[:id].match(/^\d+$/)  
@object = provider.find(params[:id])  
@object.destroy  
end

@object = provider.new  
respond\_to do |format|  
format.js  
end  
end

private

def provider  
if params[:person\_id].eql?(‘0’)  
@person = current\_account.people.new  
@person.set\_place\_holder\_data  
end  
@person ||= current\_account.people.find(params[:person\_id])

case params[:type]  
when ‘phone\_number’  
return @person.phone\_numbers  
when ‘email\_address’  
return @person.email\_addresses  
when ‘address’  
return @person.addresses  
end  
end

end

This maybe a bit confusing, but the problem occurs when I put this  
code into production. The first time you load the “new” action in the  
PeopleController it works fine. The second time it gives me a 500  
error because the ID has disappeared from the EmailAddress and I am  
using named route functions to generated urls which require it. At  
first I though it had something to do with the generated\_identifier  
not being set the second time. Not the case, actually I put a raise  
statement in the aliased method id\_with\_generated\_identifier which  
never gets called after the first execution. After hours of debugging  
I figured out that if I turn off the cache\_classes setting in  
production/environment.rb it works great. Slow … but great. It seems  
that the alias\_method\_chain which creates an alias from  
id\_with\_generated\_identifier to id is broken after the first  
execution. I am not sure why this is. Does anyone have an idea why  
this would be happening? If not, does anyone have a better way of  
accomplishing this that would allow me to cache my classes again? If  
more clarification is needed please let me know.

Thanks,  
Nicholas
