2010-02-24 32 views
1

我正在設計一個表單,您需要將關係添加到另一個對象。好吧,這通常很好,但是我所掛上的是一種乾淨的方式,以方便用戶輸入對象。用戶可以通過多種方式知道如何指定對象(唯一標識符)。以多種方式之一識別項目

讓我們舉個例子把用戶關聯到任務。在這種情況下,模特們制定了這樣的:

class User 
    has_many :tasks 
    # fields: phone_number, email, username 
    validates_uniqueness_of :phone_number 
    validates_uniqueness_of :email 
    validates_uniqueness_of :username 
    # other methods, validations, etc which are not important. 
end 

class Task 
    belongs_to :user 
    # other methods, validations, etc which are not important. 
end 

我怎麼會寫控制器和視圖的形式,如果我希望能夠通過用戶名,電子郵件,或PHONE_NUMBER指定用戶 - 我可能會知道這些中的任何一個,只要一個就足以明確指定我想要的用戶,在清潔的方式?

目前我的解決方案似乎很混亂。我也有類似的看法:

<% form_for @task do |f| %> 
... Other stuff 
User - choose one of the following ways: <br /> 
Username: <%= text_field_tag :user_name %> <br /> 
or phone number: <%= text_field_tag :user_phone %> <br /> 
or email: <%= text_field_tag :user_email %> <br /> 
... More other stuff 
<% end %> 

然後我處理這些領域中顯式控制器,尋找基於實際的用戶對哪些是填補了:

class TasksController 
    def create 
    @task = Task.new(params[:task]) 
    if params[:user_name] 
     @task.user = User.find_by_username(params[:user_name]) 
    elsif params[:user_phone] 
     @task.user = User.find_by_phone_number(params[:user_phone]) 
    elsif params[:user_email] 
     @task.user = User.find_by_email(params[:user_email]) 
    end 
    if @task.save 
     redirect_to @task 
    else 
     render :action => 'new' 
    end 
    end 
end 

這似乎是它是非常具體的,並且在我的控制器中有很多代碼,特別是如果我在表單上有很多這樣的代碼。當你需要動態地將多個用戶添加到任務中時,甚至不要和我談談 - 在控制器解析所有內容時,它甚至更加瘋狂。

回答

1

我認爲這樣做的最不顯眼的方式是一些AJAX調用。

我在想一個調用遠程函數的文本字段的觀察者。該功能應該用匹配的潛在關聯來更新你的表單,用戶可以用單選按鈕或其他來選擇。

它看起來好像是這樣的:

UserController中:

def select_user 
    @user = case params[:query] 
    when !/\w/ #phone no 
    User.find_by_phone(params[:query]) 
    when /@/ # email 
    User.find_by_email(params[:query]) 
    else 
    User.find_by_username(params[:query]) 
    end 
end 

的意見/ select_user.rjs:

page.replace_html :matched_user, :inline => <<"PARTIAL" 
<%=hidden_field_tag "task[user_id]", @user.id%> 
User: <%[email protected]%> 
PARTIAL 

任務形式

<%form_for @task do |f|%> 
    ... 
    <%= text_field_tag :query %> 
    <%= observe_field :query, {:controller => :users, :action => :select_user}%> 
    <div id="matched_user" /> 
<% end%> 

可能無法正常工作作爲adver tised。我做了假設,並沒有對它進行測試。但它應該把你放在正確的軌道上。

當涉及到多個用戶時,真正需要更改的是隱藏字段標籤和rjs文件。但不是太多。也沒有什麼能阻止你使用更強大的搜索機制。

+0

我喜歡這樣的解決方案,因爲它完全消除了控制器,這使得更加複雜的形式時,導致最頭疼的部分代碼。如果您希望製作3個字段而不是一個字段(如果您可能在搜索中有重疊,即用戶名帶有@),則它也可用。不幸的是,當不存在JS時,它不會退化,但這不是我當前*項目的要求。 – jamuraa 2010-02-24 16:17:21

+0

它可以稍作修改。讓搜索字段使用不同的提交值提交表單。然後,您的控制器可以重新顯示匹配用戶的表單,或者繼續基於提交值進行提交(例如:'查找用戶'與'提交') – EmFi 2010-02-24 16:33:51

+0

也可以不使用3個字段,爲什麼不用一個字段單選按鈕或描述查找類型的選擇框(用戶名vs電子郵件vs電話) – EmFi 2010-02-24 16:50:19

0

電話號碼將是一個問題,除非你處理這些輸入到剔除hypens,括號等

話雖如此,這裏有幾個選項。

1自己動手。

用戶:

def find_by_foo(search) 
    # TODO: Pre-process anything in search that looks like a phone number. 

    conditions = "username like ? or phone_number like ? or email like ?" 

    wildcard_search = "%#{search}%" 
    substitutions = [] 
    3.times do 
    substitutions << wildcard_search 
    end 

    User.find(:first, :conditions => ([conditions] + substitutions)) 
end 

2滾動自己是愚蠢的,當searchlogic已經存在。

從他們的例子在「合併範圍」:

User.username_or_first_name_like("ben") 
    => "username LIKE '%ben%' OR first_name like'%ben%'"