按has_one关联生成的字符串搜索对象

时间:2013-09-05 07:48:59

标签: ruby-on-rails search ruby-on-rails-4

我试图对生成的模型字符串进行搜索,该字符串由has_one关联组成。 我的模特在这里:

Street.rb

class Street < ActiveRecord::Base
  has_many :houses
  validates :street_type, presence: true
  validates :name, presence: true, uniqueness: {:scope => :street_type, :case_sensitive => false }
  def text
    street_type + " " + name
  end
end

House.rb

class House < ActiveRecord::Base
  belongs_to :street
  has_many :apartments
  validates :street_id, presence: true
  validates :number, presence: true
  def text
    street.text + ", " + number
  end
end

Apartment.rb

class Apartment < ActiveRecord::Base
  belongs_to :house
  has_one :street, through => :house
  has_many :accounts
  validates :house_id, presence: true
  validates :number, presence: true, uniqueness: {:scope => :house_id, :case_sensitive => false}
  def text
    house.text + ", ap. " + number
  end
end

Account.rb

class Account < ActiveRecord::Base
  belongs_to :appartment
  has_one :house, :through => :appartment
  belongs_to :resident
  validates :appartment_id, presence: true
  validates :resident_id, presence: true, uniqueness: {:scope => :appartment_id, :case_sensitive => false}
  def text
    uniq_id + " (" + appartment.text + ")"
  end
end

我必须通过匹配一些地址字符串来搜索所有帐户。我不知道该怎么做。

  • 示例第1帐户文字&#34; 123-1123-122(摄政街,51,ap.3)&#34;
  • 示例第2帐户文字&#34; 123-1123-155(摄政街,51,ap.6)&#34;
  • 搜索文本示例&#34; Regent street,51&#34;

有人可以帮我理解怎么做吗?

3 个答案:

答案 0 :(得分:3)

搜索已加入的字段

您正在搜索Account#text,这在DB中找不到,除非您将其存储在那里(请参阅“针对完整的公寓#文本搜索”),其中(通过代码判断)似乎不是案子。您不能在ActiveRecord查询中使用模型方法的返回值。首先,您需要从搜索字符串中解析街道类型和名称,门牌号和公寓号。

假设您知道街道类型和名称,门牌号码和公寓号码,您应该(减去错误,我实际上没有测试过)能够找到帐户

Account.
  joins(:apartment => { :house => :street }).
  where('apartment.number' => apt_num,
        'apartment.house.number' => house_num,
        'apartment.house.street.name' => street_name,
        'apartment.house.street.street_type' => street_type)

您的地址信息结构严谨。它可能会也可能不会很好。在不知道任何细节的情况下,我建议您检查结构与全文搜索相结合的结构化或非结构化地址信息(纯文本字段)是否适合您。

有关AR查询的更多信息,请参阅http://guides.rubyonrails.org/active_record_querying.html

搜索完整的Apartment#text

如果您不想从生成的公寓文本字段中解析名称和数字,则需要将其存储在db中。您可以通过挂钩before_save并更新文本字段(将其称为cached_text)来包含Apartment#text来完成此操作。

class Apartment < ActiveRecord::Base
  before_save :update_cached_text
  def update_cached_text
    self.cached_text = text
  end
end

如果您更改门牌号码或街道名称或类型,当然Apartment#cached_text当然会不同步。为了保持同步,您需要在每次保存房屋或街道时“重新保存”(请参阅​​#touch)所有相关公寓。

现在您可以使用完整的Apartment#text

进行搜索
Account.
  joins(:apartment).
  where('apartment.cached_text' => text)

或其子串

Account.
  joins(:apartment).
  where("apartment.cached_text LIKE '%?%'", text)

答案 1 :(得分:1)

尝试使用以下

Account.includes([:appartment => [:house => :street]]).where("CONCAT('accounts.uniq_id', ' (', 'streets.street_type', ' ', 'streets.name', ' ', 'houses.number', ', ap. ', 'houses.number', ')') like '%?%'", your_search_text)

答案 2 :(得分:1)

your_result = Account.includes(:apartment, :apartment => :house, :apartment => {:house => :street}).where(:apartment => {:number => ...}).where(:house => {:number => ...}).where(:street => {:name => ...})