Rails Habtm悲伤是我愚蠢还是Rails错误? (绝望;)

| 大家问候, 我在与habtm的关系中遇到一个奇怪的问题,老实说,我开始认为自己可能偶然发现了Rails 3中的一些奇怪的错误。尽管如此,我当然疯了。我已经连续三天在墙上撞头了,用谷歌搜索了我能想到的一切,但仍然找不到答案。 好的,情况: 我正在创建一个Rails应用程序以替换Java应用程序和PHP应用程序(Java应用程序和php前端)。这将是一个分阶段的操作,第一阶段是Rails应用程序接管注册和计费。为此,Rails应用程序必须在数据库中为Java和PHP应用程序创建数据。 Rails应用程序本身正在使用Devise进行身份验证。 在database.yml中,我定义了我的标准3数据库,还为Java apps数据库定义了一个连接。 以下是外部对象的模型定义(我只是创建常规的Rails模型以与外部数据库对话):
class Pushbroom::UserAccount < ActiveRecord::Base
  require \'digest/md5\'
  require \'base64\'

  establish_connection :pushbroom
  set_table_name :user_account
  set_primary_key :id

  has_and_belongs_to_many :user_roles, :join_table => \'pb_prod.users_roles\', :class_name => \'Pushbroom::UserRole\', :foreign_key => \'user_account_id\', :association_foreign_key => \'user_role_id\'
  belongs_to :user, :dependent => :destroy


  attr_accessible :user_roles, :admin_notes, :enabled, :username, :password_hash, :prefStore, :accepted_tos, :do_not_contact
end


class Pushbroom::UserRole < ActiveRecord::Base

  establish_connection :pushbroom
  set_table_name :user_role
  set_primary_key :id

  has_and_belongs_to_many :user_accounts, :join_table => \'pb_prod.users_roles\', :class_name => \'Pushbroom::UserAccount\', :foreign_key => \'user_role_id\', :association_foreign_key => \'user_account_id\'


end
最后是我的Rails应用程序用户对象:
class User < ActiveRecord::Base

  after_create :send_welcome_email
  before_save :create_pushbroom_user_data

  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  belongs_to :pb_user_account, :class_name => \"Pushbroom::UserAccount\", :foreign_key => \"pb_user_account_id\", :dependent => :destroy, :autosave => true

  # Setup accessible (or protected) attributes for your model
  attr_accessible :first_name, :last_name, :username, :dob, :email, :password,         :password_confirmation, :remember_me

  validates_presence_of :first_name, :last_name, :username, :dob
  validates_date :dob, :on_or_after => lambda { 100.years.ago }, :on_or_after_message => \"must be on or after #{100.years.ago.strftime(\'%m-%d-%Y\')}\" 
  validates_date :dob, :on_or_before => lambda { 13.years.ago }, :on_or_before_message => \"must be on or before #{13.years.ago.strftime(\'%m-%d-%Y\')}\"

  def create_pushbroom_user_data
    pb_user = create_pushbroom_user
    pb_user_account = create_pushbroom_user_account(pb_user)
    pb_user_account.user_roles << Pushbroom::UserRole.find_by_name(\'user\')
    self.pb_user_account = pb_user_account
  end

  def create_pushbroom_user
    pb_user = Pushbroom::User.new
    pb_user.attributes = self.attributes.slice(
      \"email\",
      \"first_name\",
      \"last_name\",
      \"dob\")

    pb_user
  end

def create_pushbroom_user_account(pb_user)
    pb_user_account = Pushbroom::UserAccount.new
    pb_user_account.enabled = true
    pb_user_account.password_hash =                 Pushbroom::UserAccount.create_password_digest(@plaintext_password, self.username)
    pb_user_account.username = self.username
    pb_user_account.user = pb_user

    pb_user_account
  end
好像应该是香草。唯一奇怪的是,它们不在本地rails数据库中,并且在关系表中将这些字段之一命名为funny。 所以这是一个Rails控制台会话,我在其中创建一个Rails用户,调用该方法来创建外部对象,然后尝试保存:
ruby-1.9.2-p180 :001 > def user_fred
ruby-1.9.2-p180 :002?>       { 
ruby-1.9.2-p180 :003 >             :first_name => \"Fred\",
ruby-1.9.2-p180 :004 >             :last_name => \"Flinstone\",
ruby-1.9.2-p180 :005 >             :username => \"fflint\",
ruby-1.9.2-p180 :006 >             :dob => \"1986-06-01\",
ruby-1.9.2-p180 :007 >             :email => \"fred@mydomain.org\",
ruby-1.9.2-p180 :008 >             :password => \"badpass\"
ruby-1.9.2-p180 :009?>         }
ruby-1.9.2-p180 :010?>     end
 => nil 
ruby-1.9.2-p180 :011 > user = User.new(user_fred)
 => #<User id: nil, email: \"fred@mydomain.org\", encrypted_password:     \"$2a$10$IiEOEoSnXIrP7VJAQYckfOVXuzm7Y5ZGo20ayLpSkHhz...\", reset_password_token: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: nil, updated_at: nil, first_name: \"Fred\", last_name: \"Flinstone\", username: \"fflint\", dob: \"1986-06-01\", pb_user_account_id: nil> 
ruby-1.9.2-p180 :012 > user.create_pushbroom_user_data
=> #<Pushbroom::UserAccount id: nil, created_by: nil, created_at: nil, updated_by: nil,     updated_at: nil, admin_notes: nil, enabled: true, username: \"fflint\", password_hash: \"blah     blah\", user_id: nil, prefStore: nil, accepted_tos: nil, do_not_contact: nil> 
ruby-1.9.2-p180 :013 > user.pb_user_account.user_roles
 => [#<Pushbroom::UserRole id: 1, created_by: \"script\", created_at: \"2008-11-10     12:10:44\", updated_by: \"script\", updated_at: \"2008-11-10 12:10:44\", admin_notes: \"\", name:     \"user\", description: \"Generic User Role\", conditional: false>] 
ruby-1.9.2-p180 :014 > user.save!
NoMethodError: undefined method `relation\' for nil:NilClass
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activesupport-    3.0.5/lib/active_support/whiny_nil.rb:48:in `method_missing\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/arel-    2.0.9/lib/arel/insert_manager.rb:22:in `insert\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/arel-    2.0.9/lib/arel/crud.rb:26:in `insert\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-    3.0.5/lib/active_record/associations/has_and_belongs_to_many_association.rb:76:in     `insert_record\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-    3.0.5/lib/active_record/associations/association_proxy.rb:151:in `send\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/autosave_association.rb:306:in `block in     save_collection_association\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/associations/association_collection.rb:431:in `block in     method_missing\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/associations/association_proxy.rb:216:in `block in method_missing\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/associations/association_proxy.rb:216:in `each\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/associations/association_proxy.rb:216:in `method_missing\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/associations/association_collection.rb:431:in `method_missing\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/autosave_association.rb:297:in `save_collection_association\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/autosave_association.rb:163:in `block in add_autosave_association_callbacks\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activesupport-3.0.5/lib/active_support/callbacks.rb:415:in `_run_create_callbacks\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/callbacks.rb:281:in `create\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/persistence.rb:246:in `create_or_update\'
... 18 levels...
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/callbacks.rb:277:in `create_or_update\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/persistence.rb:56:in `save!\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/validations.rb:49:in `save!\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/attribute_methods/dirty.rb:30:in `save!\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/transactions.rb:245:in `block in save!\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-    3.0.5/lib/active_record/transactions.rb:292:in `block in with_transaction_returning_status\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/connection_adapters/abstract/database_statements.rb:139:in     `transaction\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/transactions.rb:207:in `transaction\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/transactions.rb:290:in `with_transaction_returning_status\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/activerecord-3.0.5/lib/active_record/transactions.rb:245:in `save!\'
  from (irb):14
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/railties-3.0.5/lib/rails/commands/console.rb:44:in `start\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/railties-3.0.5/lib/rails/commands/console.rb:8:in `start\'
  from /Users/gander/.rvm/gems/ruby-1.9.2-p180@sms2/gems/railties-3.0.5/lib/rails/commands.rb:23:in `<top (required)>\'
  from script/rails:6:in `require\'
  from script/rails:6:in `<main>\'ruby-1.9.2-p180 :015 > 
如果我删除了角色分配,则一切都只是繁琐的(查找,保存,销毁等),但是第二个我尝试保存角色时,一切都因此消息而飞速发展,坦率地说,我没有得到。它知道它扮演的角色,没有nil对象可以告诉我。 。如果我还没秃头的话,基本上我会把头发拔掉; ) 非常感谢对此有任何见解! 杰拉尔德 附言还在此处询问http://railsforum.com/viewtopic.php?id=43647如果找到,将重复答案。     
已邀请:
在愚弄了自己四天之后,我终于找到了问题:Rails(habtm)无法确定用于外部关系表的数据库。我也找到了答案,它甚至没有难闻的气味!这里有整个流程:http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/c5655d0442039ccd 答案? has_many:through-我从没看过很多东西,但这实际上是一个非常不错的功能(即使在其他情况下)。 基本上,这只允许我创建一个表示关系的模型类。并且由于我有一个模型类,因此我可以显式指定要连接的数据库。 为了后代,以下是代码:
class Pushbroom::UsersRolesRelationship < ActiveRecord::Base

  establish_connection :pushbroom
  set_table_name :users_roles

  belongs_to :user_account
  belongs_to :user_role
end

class Pushbroom::UserAccount < ActiveRecord::Base

  establish_connection :pushbroom
  set_table_name :user_account
  set_primary_key :id

  has_many :users_roles_relationships
  has_many :user_roles, :through => :users_roles_relationships, :source => :user_role
end

class Pushbroom::UserRole < ActiveRecord::Base

  establish_connection :pushbroom
  set_table_name :user_role
  set_primary_key :id

  has_many :users_roles_relationships
  has_many :user_accounts, :through => :users_roles_relationships, :source => :user_account
end
因此被使用:
def add_subscription_plan_roles_to_pb_user_account(pb_user_account)
    roles_granted = pb_user_account.user.subscriptions.first.subscription_plan.roles_granted
    pb_user_account.user_roles = roles_granted
end
感谢无数的人帮助我让这辆火车再次行驶!我所有的测试都通过了,而且似乎可以正常工作,但是如果您发现有问题,请仍然让我知道。 谢谢! 杰拉尔德     
尝试对在各个位置创建的对象进行一些手动保存,例如“ 5”方法。过去,在依靠“自动保存”系统时遇到了一些问题。     

要回复问题请先登录注册