I have the following models (these are the relevant pieces): class User < ActiveRecord::Base belongs_to :account, :foreign_key => ''account'' end class Account < ActiveRecord::Base has_many :users, :foreign_key => ''account'', :dependent => true, :order => ''username'' end I have a controller that looks like: class UserController < ApplicationController def index puts @user.inspect end end The tables for these classes are something like CREATE TABLE account ( id INT AUTO_INCREMENT PRIMARY KEY ) CREATE TABLE user ( id INT AUTO_INCREMENT PRIMARY KEY, account INT, username VARCHAR(50) ) An an application controller with: class ApplicationController < ActionController::Base model :user def process(request, response) @user = User.find_first [''username = ?'', request.env[''REMOTE_USER'']] super end end This basically just puts the current user in a local variable based on the HTTP Authentication. If I run this from the command line with REMOTE_USER env variables set to a valid user I get: #<User:0x4039a080 @attributes={"account"=>"1", "username"=>"realsimple", "id"=>"1"}> As you can see @user is a valid user retrieved from the database. Now if I change the controller to say: class UserController < ApplicationController def index @user.account end end I get the following when run from the command line: /web/account.realsimplehosting.com/vendor/activerecord/lib/active_record/associations.rb:511: [BUG] Segmentation fault ruby 1.8.2 (2004-11-06) [i686-linux] Aborted If I run under the debugger I eventually get the following stack trace: /usr/lib/ruby/1.8/debug.rb:727:in `trace_func'' /usr/lib/ruby/1.8/debug.rb:939 /usr/lib/ruby/1.8/debug.rb:938:in `account'' /vendor/activerecord/lib/active_record/associations.rb:511:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/activerecord/lib/active_record/associations.rb:514:in `account'' /vendor/actionpack/lib/action_controller/base.rb:585:in `send'' /vendor/actionpack/lib/action_controller/base.rb:585:in `perform_action_without_filters'' /vendor/actionpack/lib/action_controller/filters.rb:236:in `perform_action_without_benchmark'' /vendor/actionpack/lib/action_controller/benchmarking.rb:30:in `perform_action_without_rescue'' /vendor/actionpack/lib/action_controller/benchmarking.rb:30:in `measure'' /vendor/actionpack/lib/action_controller/benchmarking.rb:30:in `perform_action_without_rescue'' /vendor/actionpack/lib/action_controller/rescue.rb:75:in `perform_action'' /vendor/actionpack/lib/action_controller/base.rb:261:in `send'' /vendor/actionpack/lib/action_controller/base.rb:261:in `process'' /vendor/actionpack/lib/action_controller/base.rb:239:in `process'' /vendor/railties/lib/dispatcher.rb:39:in `dispatch'' dispatch.cgi:10 As you can see I am clearly getting a infinate recursive loop. I thought it was happening because I had a two way relationship "has_many" and "belongs_to", but when I remove the "has_many" relationship from Account I still get the same problem. Any ideas? I not sure which version of Rails I am running (it was a tgz). I think it is 0.9.1 but it may be 0.9.2. I know it is not the latest. I am going to try to upgrage to 0.9.3 to see if that helps. Thank you for any information you can provide. Eric _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Eric Anderson wrote:> I have the following models (these are the relevant pieces): > > class User < ActiveRecord::Base > belongs_to :account, :foreign_key => ''account''Try :foreign_key => ''account_id''.
Andreas Schwarz wrote:> Eric Anderson wrote: > >> I have the following models (these are the relevant pieces): >> >> class User < ActiveRecord::Base >> belongs_to :account, :foreign_key => ''account'' > > > Try :foreign_key => ''account_id''.But the field on the user table is "account" not account_id (I created these tables before I started using rails on the database). Here is the relevant parts of the user definition: CREATE TABLE user ( id INT AUTO_INCREMENT PRIMARY KEY, account INT, username VARCHAR(50) ) Eric _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Eric Anderson wrote:> I not sure which version of Rails I am running (it was a tgz). I think > it is 0.9.1 but it may be 0.9.2. I know it is not the latest. I am going > to try to upgrage to 0.9.3 to see if that helps.I have upgraded to Rails 0.9.3 and I now get the following when run from the command line: [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] [BUG] Segmentation fault ruby 1.8.2 (2004-11-06) [i686-linux] [BUG] [BUG] Segmentation fault ruby 1.8.2 (2004-11-06) [i686-linux] So it hasn''t gotten better. :) Does anybody have any good ideas on how to debug this problem. Why would the belongs_to relationship get in a infinite recursive loop when trying to access the generated accessor method? Eric _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
On Fri, 07 Jan 2005 18:58:02 -0500, Eric Anderson <eric-ANzg6odk14w@public.gmane.org> wrote:> Andreas Schwarz wrote: > > Eric Anderson wrote: > > > >> I have the following models (these are the relevant pieces): > >> > >> class User < ActiveRecord::Base > >> belongs_to :account, :foreign_key => ''account'' > > > > > > Try :foreign_key => ''account_id''.rename the column to account_id and see if it still happens.> But the field on the user table is "account" not account_id (I created > these tables before I started using rails on the database). Here is the > relevant parts of the user definition: > > CREATE TABLE user ( > id INT AUTO_INCREMENT PRIMARY KEY, > account INT, > username VARCHAR(50) > ) > > Eric > > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails > > > >-- Cheers Koz
Michael Koziarski wrote:> rename the column to account_id and see if it still happens.Renaming the column isn''t an option because other code (outside of rails) depends on it being "account" instead of "account_id". But I did add a column called "account_id" and copied the data from "account" to "account_id". I then changed the code to use "account_id" instead of "account". This gets around the problem! The problem is that I would really like to keep the field as "account". I have lots of other code that depends on it being called "account". Changing the field to "account_id" would be a major hassle. When choosing rails I didn''t realize this would be a problem because I thought the "foreign_key" option would take care of this for me. So I would GREATLY appreciate anyone that could clue me into why this problem is showing up so I could look for a work-around. Thanks, Eric _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Eric Anderson wrote:> So I would GREATLY appreciate anyone that could clue me into why this > problem is showing up so I could look for a work-around.I think I found the problem after lots of code searching. It looks like the :foreign_key option cannot be the same as the attribute name. This is because when finding the associated class it called the raw field name as a method to get the actual value of the field to search on. It is somewhat equivalent to: class User def account_id read_attribute "account_id" end def account Account.find( account_id ) end end Of course the real code is generated and more dynamic than above, but that is the essence of how it is working. If :foreign_key is equal to the attribute name then you effectively have: class User # This method is created by method_missing() def account read_attribute "account" end def account Account.find( account ) end end Obviously the first definition (which really doesn''t exist but is being created by method_missing) is irrelevant because the second definition is real (through a module_eval) and therefore when the second method is called it will keep recursively calling itself. So the next question is now that I have found the problem how do we fix it. It seems the obvious answer is to change line 338-340 of associations.rb to the following: association_finder = options[:conditions] ? "#{association_class_name}.find_on_conditions(read_attribute(\"#{association_class_primary_key_name}\"), \"#{options[:conditions]}\")" : "#{association_class_name}.find(read_attribute(\"#{association_class_primary_key_name}\"))" Email wrapping may mess this up but basically we want to make it use the underlying read_attribute method instead of the public accessor method. This shouldn''t break compatibility too much. The only harm is if a user has overwritten the account_id method to make it load a different object from what the database says it should load. But I imagine this would be rare (if used at all by anyone). I''m going to make the changes on my system to see if it works. I would appreciate any comments about better approaches or any comments about possible problems related to this. Thanks, Eric _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
On Fri, 2005-01-07 at 20:46 -0500, Eric Anderson wrote:> Michael Koziarski wrote: > > rename the column to account_id and see if it still happens. > > Renaming the column isn''t an option because other code (outside of > rails) depends on it being "account" instead of "account_id". But I did > add a column called "account_id" and copied the data from "account" to > "account_id". I then changed the code to use "account_id" instead of > "account". This gets around the problem!I think it is a bad idea to have a column be the same name as the table. So trying to fix the code may not be the best choice. On a constructive note though, as I also am dealing with trying to use the same database and data for more than one project at a time and it was designed without rails in mind, I have been learning how to get around the problem. Through the use of views and rules on the postgres database we use and the table name prepend in rails, I am making our data available in a way that rails is happy with. If you are not running postgres, I am sorry this suggestion probably won''t help but I will point it out for those who may be struggling the way I was before.>From your example you hadCREATE TABLE account ( id INT AUTO_INCREMENT PRIMARY KEY ) CREATE TABLE user ( id INT AUTO_INCREMENT PRIMARY KEY, account INT, username VARCHAR(50) ) To which I would suggest adding something like create view rails_account as select id from account; create rule rails_account_upd as on update to rails_account do instead update account set id = NEW.id where id = OLD.id; create rule rails_account_ins as on insert to rails_account do instead insert into account (id) values (NEW.id); create rule rails_account_del as on delete to rails_account do instead delete from account where id = OLD.city; create view rails_user as select id,account as account_id, username from user; create rule rails_user_ins as on insert to rails_user do instead insert into user (id, account, username) values ( NEW.id, NEW.account_id, NEW.username); create rule rails_user_upd as on update to rails_user do instead update user set id = NEW.id, account = NEW.account_id, username = NEW.username where id = OLD.id; create rule rails_user_del as on delete to rails_user do instead delete from user where id = OLD.id; After doing all that above, the views will act just like tables. You shouldn''t have any trouble then making your old tables look like tables rails is expecting and yet not giving up your old tables and your existing production code. -- Steven Critchfield <critch-wQLwMjUOumVBDgjK7y7TUQ@public.gmane.org>
Steven Critchfield wrote:> I think it is a bad idea to have a column be the same name as the table. > So trying to fix the code may not be the best choice.Hmm.. I feel the exact opposite. It seems perfectly natural to have a field named after the object it is storing. If you are referencing an account object in the user object I would expect the field to be named account. The only exception to this may be in the case where you have something like an employee who has a boss. The boss is also an employee, but you may name the field "boss" to make the type of relationship more apparent. I find the whole "<field_name>_id" to be a bit annoying. The idea is to encode information about what type of data it is storing in the name itself. But it is obvious you are storing a relationship when the type is an INT and there is another table in the database named "accounts". Plus you get into a case of where do you stop encoding information. I have seen some designs where they encode the table name in the field so it is apparent in joins. I have also seen designs where the referenced object type is encoded in the name. So if you keep this information encoding up you end up with variables named like "user_account_Account_id" or "employee_boss_Employee_id". Somehow people think this encoding of information is more legible than just "account". This is the same argument I have against the Hungarian notation that is so popular on Microsoft platforms. Why have "lpszFile" instead of just "file"? Obviously all this is style and preference and nobody is really "right". But the documentation clearly implies that the :foreign_key option will allow you to use any field name you want. To be consistent it should allow using the attribute name as the foreign key name.> On a constructive note though, as I also am dealing with trying to use > the same database and data for more than one project at a time and it > was designed without rails in mind, I have been learning how to get > around the problem.I agree that good view support can also help with this situation. Of course this also means that your application is tied to one database platform. To me it seems that rails should support a default design out of the box, but through options allow someone to specify a slightly different design. Working with legacy databases is important and if we can support 90% of them through the use of simple options such as :foreign_key, table_prefix, table_suffix, and the like then it will make rails that much more successful. Also the other problem I see with using views besides the loss of platform independence is that you now have more maintenance costs. Every time you want to change the database you might need to also update the views to account for this change. As always TIMTOWTDI and the creation of views is a very option when the database design is just too different from the design rails expects. Thanks for the suggestions, Eric _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
On Jan 8, 2005, at 20:03 Uhr, Eric Anderson wrote:> Steven Critchfield wrote: >> I think it is a bad idea to have a column be the same name as the >> table. >> So trying to fix the code may not be the best choice. > > Hmm.. I feel the exact opposite. It seems perfectly natural to have a > field named after the object it is storing.i think its a question of taste. however you have to consider: you are not storing a account object in the account field of user. you are specifing what''s the id of the account this user owns. so i think its perfectly fine to call it account_id.