2013-02-05 68 views
4

我知道我不是想要這樣做,但我不知道我該怎麼做。 我想在此基礎上用戶loged使用不同的數據庫,所以我想最好的辦法是,如果我成立了第一個用戶登錄會話變量...設置與會話變量的數據庫連接

這是它的樣子:

class Stuff < ActiveRecord::Base 
    establish_connection(
     :adapter => "mysql2", 
     :host  => "127.0.0.1", 
     :username => session["dbuser"], 
     :password => session["dbuserpass"], 
     :database => session["dbname"]) 

這當然不起作用。有誰知道如何做到這一點? 謝謝。

+2

規則一,不要給用戶「root」的訪問權限。不要。規則二,不要將連接建立在用戶可以在其計算機上更改的某些內容上,例如會話cookie或變量。用戶很聰明,不知道他們會做什麼。 –

+0

這只是一個例子,每個用戶都會有它的db用戶權限...... – user899119

+1

然後請在你的示例代碼中顯示,或者在你的問題中解釋它。 –

回答

1

您可以選擇在模型數據庫是這樣的:

establish_connection "db_name_#{session[:something]}" 

這樣,你的模型知道拉的數據庫/推送數據。

看看這個:http://m.onkey.org/how-to-access-session-cookies-params-request-in-model

+0

hm ...我仍然得到未定義的局部變量或方法'會話' – user899119

+0

對不起,我修改了答案。這樣做不好,但這是一個有效的實驗。 – Kaeros

+0

謝謝,但它似乎並沒有工作......當我訪問establish_connection「#{會話[:dbname]}」我有你沒有對象,當你沒有想到它!...但我相信會話[:dbname]已設置... – user899119

2

你可以重寫你的方法爲:

class Stuff < ActiveRecord::Base 
def establish_connection_user(user, pass, database) 
    establish_connection(
    :adapter => "mysql2", 
    :host  => "127.0.0.1", 
    :username => user, 
    :password => pass, 
    :database => database) 
    end 
end 

,並在你的控制器:

class StuffController < ApplicationController 
    def login #example 
     stuff = Stuff.new 
     stuff.establish_connection_user(
     session[:dbuser], 
     session[:dbuserpass], 
     session[:dbname]) 
    end 

這樣你還封裝,並做出詳細信息少明顯。我建議你也 加密你的cookie,所以你沒有如此暴露的憑據。你可以從這個答案需要一個想法 :

Storing an encrypted cookie with Rails

0

正如暗示通過對原問題的評論權,我會通過使用會話只保留用戶的身份接近它。然後,我會從模型和中央數據庫(默認的導軌數據庫)中的邏輯中提取所需的數據庫連接,並保留用戶詳細信息和用戶連接信息。

開始與修改您的用戶模型(假設用戶具有被在中央數據庫中持續一個模型)

  • 添加到用戶表示數據的屬性中使用
  • 在您的應用程序控制器設置用戶在的before_filter,基於會話密鑰
  • 與用戶參數

然後,您可以查找你的d初始化你的東西模型基於database.yml的數據庫連接。或者,如果每個用戶都有一個數據庫,並且需要這種數據庫是動態數據庫,則可以創建第二個模型(在中央數據庫中),該數據庫表示與用戶模型上的外鍵數據庫連接。

以下是一些代碼,可能在現實中可能不起作用,但希望爲您提供一個入門模板。

class ApplicationController < ActionController::Base 
    before_filter :set_user 

    def set_user 
    begin 
     @user = UserProfile.find(session[:usernumber]) if session[:usernumber]   
    rescue 
     logger.warn "Possible error in set_user. Resetting session: #{$!}" 
     @user=nil 
     session[:usernumber]=nil 
     reset_session 
    end 
    end 

end 

class StuffController < ApplicationController 
    def show 
    @stuff = Stuff.user_get(@user, params[:id]) 
    end 
end 

class Stuff < ActiveRecord::Base 
    # This would be better moved to a module to reuse across models 
    def self.establish_connection_user(user) 
    establish_connection(user.connection_hash) 
    end 
    def establish_connection_user(user) 
    establish_connection(user.connection_hash) 
    end 

    def self.user_get user, item_id   
    establish_connection_user(user) 
    find(id) 
    end 

    def self.user_where user, *query_args   
    establish_connection_user(user) 
    where(query_args) 
    end 
    # Even better than replicating 'where', create model methods 
    # that are more representative of your desired functionality 
end 

class User < ActiveRecord::Base 
    has_one :user_connection 
    def connection_hash 
    uc = self.user_connection 
    {:database=>uc.db, :password=>uc.pass, :user=>uc.username, :host=>uc.dbhost, :adapter=>uc.adapter} 
    end 
    # User probably contains other user-facing details 
end 
0

如果你有使用PostgreSQL,你可以使用PostgreSQL的架構特性,有效地對於每個用戶都有單獨的表的命名空間(模式)的選項。這樣做的好處是你仍然連接到相同的數據庫(從而避免了對rails API的攻擊),但是就數據庫分離而言,您可以從多個DB獲得相同的好處。

如果你有RailsCasts專業版($ 9 /月)瑞恩·貝茨對這個問題的優秀的視頻:http://railscasts.com/episodes/389-multitenancy-with-postgresql

傑羅德城主也做了很大的向上寫在他的博客:http://blog.jerodsanto.net/2011/07/building-multi-tenant-rails-apps-with-postgresql-schemas/

在這兩個他們使用子域在租戶/架構之間切換的示例,但您可以輕鬆將其鏈接到用戶記錄。