代码之家  ›  专栏  ›  技术社区  ›  jamuraa

以多种方式之一标识项目

  •  1
  • jamuraa  · 技术社区  · 16 年前

    我正在设计一个表单,您需要在其中向另一个对象添加关系。好吧,这通常很好,但是我挂断的是一个干净的方式,让用户很容易进入对象。用户可以通过多种方式知道如何指定对象(唯一标识符)。

    让我们以将用户与任务关联为例。在这种情况下,模型的布局如下:

    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
    

    如果我想通过用户名、电子邮件或电话号码指定用户,我该如何编写控制器和视图表单?我可能知道其中的任何一个,并且只需一个就足以在 清洁的 方式?

    目前我的解决方案似乎很混乱。我的观点类似于:

    <% 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
    

    这似乎是非常具体的,在我的控制器中有很多代码,特别是当我在一个表单上有很多这样的代码时。当你需要动态地将多个用户添加到一个任务中时,甚至不要和我谈论这个问题——在控制器解析所有内容时,它会变得更加疯狂。

    2 回复  |  直到 16 年前
        1
  •  1
  •   EmFi    16 年前

    我认为最不引人注目的方法是使用几个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
    

    查看/选择用户.rjs:

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

    任务形式

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

    不能按广告工作。我做了假设,但还没有测试。但这会让你走上正轨。

    当涉及到多个用户时,真正需要更改的是隐藏字段标记和RJS文件。但不多。也没有什么能阻止你使用更强大的搜索机制。

        2
  •  0
  •   Hardryv    16 年前

    电话号码将是一个问题,除非您处理输入以去除炒作、括号等。

    尽管如此,这里有几个选择。

    一卷你自己的。

    用户:

    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%'"