【问题标题】:Getting rails3-autocomplete-jquery gem to work nicely with Simple_Form with multiple inputs让 rails3-autocomplete-jquery gem 与具有多个输入的 Simple_Form 很好地配合使用
【发布时间】:2013-02-22 07:52:11
【问题描述】:

所以我尝试使用 this gem 和 simple_form 实现多个自动完成功能,但出现错误。

我试过了:

<%= f.input_field :neighborhood_id, collection: Neighborhood.order(:name), :url => autocomplete_neighborhood_name_searches_path, :as => :autocomplete, 'data-delimiter' => ',', :multiple => true, :class => "span8" %>

这是我得到的错误:

undefined method `to_i' for ["Alley Park, Madison"]:Array

在我的参数中,它在neighborhood_id 发送这个:

"search"=>{"neighborhood_id"=>["Alley Park, Madison"],

所以它甚至没有使用这些值的 ID。

有人有什么想法吗?

编辑 1:

在回答@jvnill 的问题时,我没有明确地在控制器中对params[:search] 做任何事情。搜索会创建一条新记录,并且正在搜索 listings

在我的搜索控制器create 操作中,我只是这样做:

@search = Search.create!(params[:search])

然后我的search.rb(即搜索模型)有这个:

def listings
    @listings ||= find_listings
end

private
  def find_listings
    key = "%#{keywords}%"
    listings = Listing.order(:headline)
    listings = listings.includes(:neighborhood).where("listings.headline like ? or neighborhoods.name like ?", key, key) if keywords.present?
    listings = listings.where(neighborhood_id: neighborhood_id) if neighborhood_id.present?
    #truncated for brevity
    listings
  end

【问题讨论】:

  • 你在加入Gemfile之后有没有执行bundle
  • 是的。 gem 安装正确,因为我在其他地方的一些其他领域使用autocomplete 功能,它运行良好。此外,自动完成功能适用于该字段 - 只是多个功能不起作用。
  • 能否在您使用params[:search][:neighborhood_id]的地方包含部分控制器代码
  • @jvnill - 完成。更新了问题。
  • Search.create!(params[:search]) 使用来自参数的数组neighborhood_id。这就是导致您的错误的原因。你打算如何将多个邻域保存到数据库中?或者那是您要求的一部分?

标签: ruby-on-rails ruby-on-rails-3 autocomplete jquery-autocomplete


【解决方案1】:

首先,如果表单返回的是 id 而不是邻居的名称,这会更容易。我还没有使用过 gem,所以我不熟悉它是如何工作的。阅读自述文件说它会返回 ID,但我不知道为什么你只得到名字。我敢肯定,一旦您弄清楚如何返回 ID,您就可以更改下面的代码以适应这种情况。

您需要在邻域和搜索之间创建一个连接表。我们称之为 search_neighborhoods。

rails g model search_neighborhood neighborhood_id:integer search_id:integer
# dont forget to add indexes in the migration

之后,您需要设置模型。

# search.rb
has_many :search_neighborhoods
has_many :neighborhoods, through: :search_neighborhoods

# search_neighborhood.rb
belongs_to :search
belongs_to :neighborhood

# neighborhood.rb
has_many :search_neighborhoods
has_many :searches, through: :search_neighborhoods

现在我们已经设置了关联,我们需要设置设置器和属性

# search.rb
attr_accessible :neighborhood_names

# this will return a list of neighborhood names which is usefull with prepopulating
def neighborhood_names
  neighborhoods.map(&:name).join(',')
end

# we will use this to find the ids of the neighborhoods given their names
# this will be called when you call create!
def neighborhood_names=(names)
  names.split(',').each do |name|
    next if name.blank?
    if neighborhood = Neighborhood.find_by_name(name)
      search_neighborhoods.build neighborhood_id: neighborhood.id
    end
  end
end

# view
# you need to change your autocomplete to use the getter method
<%= f.input :neighborhood_names, url: autocomplete_neighborhood_name_searches_path, as: :autocomplete, input_html: { data: { delimiter: ',', multiple: true, class: "span8" } %>

最后但并非最不重要的是更新find_listings

def find_listings
  key = "%#{keywords}%"
  listings = Listing.order(:headline).includes(:neighborhood)

  if keywords.present?
    listings = listings.where("listings.headline LIKE :key OR neighborhoods.name LIKE :key", { key: "#{keywords}")
  end

  if neighborhoods.exists?
    listings = listings.where(neighborhood_id: neighborhood_ids)
  end

  listings
end

就是这样:)

更新:使用 f.input_field

# view
<%= f.input_field :neighborhood_names, url: autocomplete_neighborhood_name_searches_path, as: :autocomplete, data: { delimiter: ',' }, multiple: true, class: "span8" %>

# model
# we need to put [0] because it returns an array with a single element containing
# the string of comma separated neighborhoods
def neighborhood_names=(names)
  names[0].split(',').each do |name|
    next if name.blank?
    if neighborhood = Neighborhood.find_by_name(name)
      search_neighborhoods.build neighborhood_id: neighborhood.id
    end
  end
end

【讨论】:

  • 我不知道为什么我有一种感觉,一旦我弄清楚如何让它发送 ID,它就可以工作,而无需设置此连接表并执行所有这些操作。跨度>
  • 不,如果您能够发送 ID,您仍然需要设置一个连接表,因为您想与多个社区一起进行一次搜索。如果您不想设置连接表,可以查看将 ID 保存在序列化的文本列中。
  • Hrmm...好的...我如何在不使用它的情况下测试它 - 看看您的解决方案是否适合我?我无法从 gem 创建者那里得到关于这个问题的回复 - 所以我不确定我是否可以让它发送 ID,我已经尝试了我能想到的所有东西(以及其他人推荐的东西)。
  • 抱歉,更新后的代码应该是neighbor_names,而不是neighbor_id
  • 是的!完美的。做到了。谢谢你,先生。你,先生....应该得到全部的赏金和更多。我非常感谢您的耐心和完整的回答。非常感谢。
【解决方案2】:

您的问题是如何从邻域模型中收集值

 Neighborhood.order(:name)

将返回一个名称数组,您还需要收集 id,但只显示名称 使用收集并传递一个块,我相信这可能适合你

Neighborhood.collect {|n| [n.name, n.id]}

如果您想恢复剧院功能,请在 Neighborhood 类上声明一个范围以按名称对其进行排序,因为无论如何该行为也属于模型。

编辑> 要将范围/类方法添加到邻域模型,您通常会这样做

scope :desc, where("name DESC")

你可以这样写:

Neighborhood.desc.all

这将返回一个数组,从而允许 .collect 但还有其他方法可以获取 select 选项识别的那些 name 和 id 属性。

【讨论】:

  • 如果我声明了一个范围,我将如何在 collect 块中使用它? Neighborhood.ordered.collect ...?
  • 顺便说一句,这不起作用。我收到此错误:undefined method 'collect' for #&lt;Class:0x007fd05a383c18&gt;。请记住,simple_form 助手调用中的 collection 属性需要一个名称数组。
  • 非常正确,不能在 ActiveRecord 关系上调用 collect,我为得到 .all 道歉,Neighborhood.all 返回一个数组,Neighborhood.order("name DESC") 也应该返回一个数组.
  • 不...这行不通。范围错了,实际上应该是:scope :desc, order("name DESC")。而且,我尝试了Neighborhood.desc.all.collect {|n| [n.name, n.id]},它给了我同样的错误 - 这是undefined method 'to_i' for ["Madison,Alley Park,"]:Array Thoughts?
猜你喜欢
  • 2021-11-16
  • 2012-03-02
  • 2011-04-21
  • 2011-05-14
  • 2011-12-17
  • 2010-10-29
  • 2011-09-08
  • 1970-01-01
  • 2013-04-10
相关资源
最近更新 更多