【问题标题】:Rails virtual attribute search or sql combined column searchRails 虚拟属性搜索或 sql 组合列搜索
【发布时间】:2009-11-27 01:27:48
【问题描述】:

我有一个具有“first”和“last”属性的用户模型 所以例如 User.first.first #=> "查理" User.first.last #=> "棕色"

这个用户模型还有一个虚拟属性'full_name'

#user.rb
def full_name
  [first,last].join(' ')
end

def full_name=(name) #don't know what to do with people w/ middle names
  split = name.split(' ')
  self.first = split[0]
  self.last = split[1]
end

例如:

User.first.full_name = "Charlie Brown" #=> "Charlie Brown"
User.first.full_name = "Homer Simpson" #=> "Home Simpson"
User.first.save
User.first.first #=> "Homer"
User.first.last #=> "Simpson"

如果我能按那个虚拟属性搜索就好了 例如动态查找:

User.find_by_full_name('Home Simpson') # this doesn't work

查找条件示例:

User.all(:conditions => ['full_name LIKE ?', query]) #this doesn't work

我希望至少能在 SQL 语言中找到一些可以做到这一点的方法;如果也有动态虚拟属性查找,那就是馅饼上的额外香草来源。 (今年冬天有人过吗?)

我还担心要搜索的名称,例如,“Holmes”只能在“第一”列中搜索,而不能在“最后”列中搜索,例如,User.first.full_name #=> "Sherlock Holmes"

我确实尝试进行更全面的搜索:

user.rb

def self.find_by_full_name(name) #returns an array of User model
  return all if name.blank?
    
  split = name.split(' ', 2)
  output = []
  if split.length > 1
    with_scope( :find => { :conditions => ['first LIKE ?', "%#{split[0]}%"] }) do
      output << all(:conditions => ['last LIKE ?', "%#{split[1]}%"])
      output.flatten!
    end
  elsif split.length == 1
    output << all(:conditions => ['first LIKE ?', "%#{split[0]}%"])
    output << all(:conditions => ['last LIKE ?', "%#{split[0]}%"])
    output.flatten!
  end
end

例如

User.find_by_full_name("John").map(&:full_name) #=> ["John Resig", "John Doe"]
User.find_by_full_name("Doe").map(&:full_name) #=> ["John Doe", "Philips Doeringer"]
User.find_by_full_name("John Doe").map(&:full_name) #=> ["John Doe"]

但我只是觉得这里的 find_by_full_name 方法有点笨拙。

我的意思是,如果我有一个 full_name 列,它每次都由一个后保存过滤器设置,并带有 first 和 last 的 concat。所以找到一个人的名字,尤其是对这个人的模糊记忆,是有帮助的。因此,如果我记得那个人的名字或姓氏中的“Doe”,我总是可以做一个简单的 User.find_by_full_name('Doe') 来返回尽可能多的信息以进一步确定它。

由于它是一列,如果我必须执行类似Project.find(:all,:include =&gt; :users, :conditions=&gt;['users.full_name LIKE ?', query]) 之类的操作,我可以在 find(:conditions[...]) 子句中搜索它 在哪里

#project.rb
has_many :assignments
has_many :users, :through=>:assignments

#user.rb
has_many :assignments
has_many :projects, :through => :assignments

#assignment.rb
belongs_to :user
belongs_to :project

节日快乐 否

【问题讨论】:

    标签: sql ruby-on-rails find conditional-statements virtual-attribute


    【解决方案1】:

    您可以在 user.rb 中使用 named_scope:

    named_scope :find_by_full_name, lambda {|full_name| 
      {:conditions => {:first => full_name.split(' ').first, 
         :last => full_name.split(' ').last}}
    }
    

    那你就可以User.find_by_full_name('John Carver')

    响应需求变化的新东西

    named_scope :find_by_full_name, lambda {|full_name| 
      {:conditions => ["first LIKE '%?%' or last LIKE '%?%'", 
        full_name.split(' ').first, full_name.split(' ').last]}}
    

    【讨论】:

    • 我明白了。我想当我以这种方式搜索全名时它确实有效。 - 但再次感谢您的回答。最佳,N
    • 我明白了。对于那个很抱歉。我改了。
    【解决方案2】:

    我发现 Jim 的回答也很有帮助。谢谢。不过我会做些小改动。 当前的代码会使您丢失任何中间名。我下面的内容有点混乱,但保留了中间名和复合姓氏(想想 Jean-Claude van Damme)。名字之后的所有内容都在 last_name 字段中。

    named_scope :find_by_full_name, lambda { |full_name| 
     {:conditions => {:first_name => full_name.split(' ').first, 
       :last_name => full_name.split(' ')[1, full_name.split(' ').length-1].join(' ')}
       }
    }
    

    当然欢迎任何更简洁的方式来做到这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 2017-06-19
      • 2015-09-11
      • 2012-08-02
      • 2018-11-15
      • 2014-11-02
      • 1970-01-01
      相关资源
      最近更新 更多