2011-04-12 2 views
0

인사말 모든Rails habtm srief는 내가 멍청하거나 레일 버그입니까? (절망)

나는 HABTM 관계와 이상한 문제에 봉착하고 정직하게 내가 확실히 그래도 난 미쳤다고 내가 레일 3에서 몇 가지 이상한 버그가 우연히 발견했다고 생각하기 시작 해요 . 나는 3 일 동안이 벽에 머리를 때리고 있었고, 태양 아래에서 모든 것을 봤다. 나는 생각할 수 있고 여전히 답을 찾을 수 없다.

좋아, 상황 :

나는 자바 애플 리케이션과 PHP 응용 프로그램 (자바 애플리케이션과 PHP를 프런트 엔드)을 모두 대체 할 레일 응용 프로그램을 만드는거야. 이것은 Rails 애플리케이션이 등록과 청구를 대신하는 단계적 단계적 작업이 될 것입니다. 이렇게하기 위해 Rails 애플리케이션은 Java 및 PHP 애플리케이션 용 데이터베이스에 데이터를 작성해야한다. Rails 애플리케이션 자체가 Devise를 사용하여 인증합니다.

database.yml에는 표준 3 데이터베이스가 정의되어 있으며 Java 응용 프로그램 데이터베이스에 대해 정의 된 연결이 있습니다.

여기 (난 그냥 외부 데이터베이스에 얘기 일반 레일 모델을 만드는거야) 외부 객체 모델 정의의 조각입니다

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 

그리고 마지막으로 내 레일 응용 프로그램 사용자 개체 :

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 

꽤 바닐라 같아 보입니다. 여기에있는 유일한 별난 점은 네이티브 레일 데이터베이스에 없으며 필드 중 하나가 관계 테이블에서 재미 있다고 명명 된 것입니다. (모든 것이 복숭아입니다

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 => "[email protected]", 
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: "[email protected]", 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/[email protected]/gems/activesupport- 3.0.5/lib/active_support/whiny_nil.rb:48:in `method_missing' 
    from /Users/gander/.rvm/gems/[email protected]/gems/arel- 2.0.9/lib/arel/insert_manager.rb:22:in `insert' 
    from /Users/gander/.rvm/gems/[email protected]/gems/arel- 2.0.9/lib/arel/crud.rb:26:in `insert' 
    from /Users/gander/.rvm/gems/[email protected]/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/[email protected]/gems/activerecord- 3.0.5/lib/active_record/associations/association_proxy.rb:151:in `send' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/autosave_association.rb:306:in `block in  save_collection_association' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/associations/association_collection.rb:431:in `block in  method_missing' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/associations/association_proxy.rb:216:in `block in method_missing' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/associations/association_proxy.rb:216:in `each' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/associations/association_proxy.rb:216:in `method_missing' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/associations/association_collection.rb:431:in `method_missing' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/autosave_association.rb:297:in `save_collection_association' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/autosave_association.rb:163:in `block in add_autosave_association_callbacks' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activesupport-3.0.5/lib/active_support/callbacks.rb:415:in `_run_create_callbacks' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/callbacks.rb:281:in `create' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/persistence.rb:246:in `create_or_update' 
... 18 levels... 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/callbacks.rb:277:in `create_or_update' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/persistence.rb:56:in `save!' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/validations.rb:49:in `save!' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/attribute_methods/dirty.rb:30:in `save!' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/transactions.rb:245:in `block in save!' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord- 3.0.5/lib/active_record/transactions.rb:292:in `block in with_transaction_returning_status' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/connection_adapters/abstract/database_statements.rb:139:in  `transaction' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/transactions.rb:207:in `transaction' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/transactions.rb:290:in `with_transaction_returning_status' 
    from /Users/gander/.rvm/gems/[email protected]/gems/activerecord-3.0.5/lib/active_record/transactions.rb:245:in `save!' 
    from (irb):14 
    from /Users/gander/.rvm/gems/[email protected]/gems/railties-3.0.5/lib/rails/commands/console.rb:44:in `start' 
    from /Users/gander/.rvm/gems/[email protected]/gems/railties-3.0.5/lib/rails/commands/console.rb:8:in `start' 
    from /Users/gander/.rvm/gems/[email protected]/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 > 

을 나는 역할 할당을 제거하는 경우 :

그래서 여기 후 저장하려고, 외부 객체를 생성하는 메소드를 호출 난 레일 사용자를 만들 레일 콘솔 세션의 발견, 저장, 파괴 등)하지만 두 번째 역할을 저지하려고 시도하는 것은 솔직히 말해서이 메시지로 모든 것이 하늘 높이 날려 버린다. 그것은 그것의 역할을 알고, 내가 말할 수있는 아무 객체도 없습니다. . 근본적으로 내가 아직 대머리가 아니라면 나는 내 머리카락을 뽑아 낼 것이다.)

이것에 대한 통찰력은 극도로 높이 평가됩니다!

제랄드

P. 여기도 부탁드립니다 http://railsforum.com/viewtopic.php?id=43647 답변이있을 경우 중복됩니다.

+0

'create_pushbroom_user_account' 메소드 정의를 추가하십시오. – ctcherry

+0

어딘가에 잘라 붙이기에 빠졌습니다. 코드에 백업을 추가했습니다. 그것을 잡아 주셔서 감사합니다. – Gerald

답변

1

나는 4 일 동안 이걸로 바보짓을 한 끝에 마침내 문제를 발견했다. 레일스 (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 

를 그리고 thusly 히 사용됩니다 :

후세를 위해서

, 여기에 코드입니다

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 

덕분에 내가이 기차가 다시 움직 얻을 수 있도록하기위한 톤 사람들을! 모든 테스트가 끝나고 작동하는 것처럼 보이지만 잘못 본 것이 있으면 알려주세요.

감사합니다. Gerald

0

create_pushbroom_user_account(pb_user) 메서드와 같이 여러 위치에서 생성 된 개체의 일부 수동 저장을 시도해보십시오. 나는 "자동 저장"시스템에 의존 할 때 과거에 몇 가지 문제를 가지고있었습니다.

+0

나는 길을 따라 모든 단계를 저장하려고 시도했다. user_roles에 도착할 때까지 100 % 성공했다. 아무리 내가 직접 SQL insert (connection.execute/insert/etc)를 지정해도 같은 오류가 발생합니다. 그것은 거의 관계가 구성되는 방식이되어야합니다. 그러나 나는 100 번 이상 지나고 로켓 과학이 아닙니다 :/의견을 주셔서 감사합니다! – Gerald