使用字符串格式的输出创建多个选择框

时间:2017-11-17 13:44:47

标签: ruby-on-rails

我正在尝试在我的项目中设置一个多选框,它将输出到sql表中的一个字符串字段中。到目前为止,我已经想到了<%f.select%>使用多个设置为true尝试传递数组而不是字符串,这对我的项目不起作用(过去这是一个文本字段,但现在需要只允许选择预设值,它是在现场项目,所以没有剧烈的变化)。我发现做这样的事情

@keywords = params['keywords']['keywords'].join(', ')

会解决我的问题,但我不知道如何在我的控制器中实现它。

我目前在视图中选择的代码片段是:

<%= f.select :keywords, ['kw1', 'kw2', 'kw3', 'kw4', 'kw5'], {}, { :multiple => true, :size => 10, :class => 'form-control' } %>

来自控制器的用于创建新文章的代码段目前非常基本:

@article = Article.new

“keywords”是文章表中的字符串字段。

编辑:这是整个控制器:

class ArticlesController < ApplicationController
  PRIORITY_COUNTRIES = %w[RU BR IN CN ZA]
  http_basic_authenticate_with name: "***", password: "***", except: [:index, :show]

  def index
    if params[:search] == nil
      @articles = Article.filter(params.slice(:category, :country, :src_url, :date, :lang, :keywords, :title, :rel)).where(is_active: true).order('id DESC').paginate(:page => params[:page])
    else
      @articles = Article.search(params[:search], :without => {:is_active => false}, :page => params[:page], :per_page => 9, :order => :id)
    end

    @countries = ISO3166::Country.countries.sort_by do |country|
      priority_index = PRIORITY_COUNTRIES.index(country.alpha2)
      priority_index.present? ? priority_index.to_s : country.name
    end
  end

  def show
    @article = Article.find(params[:id])
  end

  def new
    @article = Article.new
  end

  def edit
    @article = Article.find(params[:id])
  end

  def create
    @article = Article.new(article_params)

    if @article.save
      redirect_to @article
    else
      render 'new'
    end
  end

  def update
    @article = Article.find(params[:id])

    if @article.update(article_params)
      redirect_to @article
    else
      render 'edit'
    end
  end

  def destroy
    @article = Article.find(params[:id])
    @article.update(:is_active => false)

    redirect_to articles_path
  end

  def undelete
    @articles = Article.where(is_active: false).paginate(:per_page => 15, :page => params[:page])
  end

  def undestroy
    @article = Article.find(params[:id])
    @article.update(:is_active => true)

    redirect_to undelete_articles_path
  end


  private
    def article_params
      params.require(:article).permit(:title, :date, :src_url, :country, :author, :category, :keywords, :keywords2, :text, :lang, :rel)
    end
end

模特:

class Article < ApplicationRecord
  before_validation do |article| 
    article.keywords.reject!(&:blank?) if article.keywords 
  end

  self.per_page = 9
  include Filterable
  validates :country, presence: true, length: { minimum: 2 }
  validates :category, presence: true
  validates :src_url, presence: true

  validates :keywords2, presence: true
  validates :text, presence: true, length: { minimum: 5 }
  validates :date, presence: true

  scope :country, -> (country) { where country: country }
  scope :category, -> (category) { where category: category }
  scope :src_url, -> (src_url) { where('src_url like ?', "%#{src_url}%")}
  scope :date, -> (date) { where date: date }
  scope :keywords, -> (keywords) { where('keywords like ?', "%#{keywords}%")}
  scope :title, -> (title) { where('title LIKE ?', "%#{title}%")}
  scope :rel, -> (rel) { where rel: rel }
end

2 个答案:

答案 0 :(得分:0)

您正走在正确的轨道上,加入了关键字。但是,您可能会更好地处理模型层的字符串要求。

由于列需要字符串,但表单和控制器传递数组,您可以考虑执行以下操作:

class Article < ApplicationRecord
  ...
  def keywords=(value)
    return super value.join(", ") if value.is_a?(Array)

    super
  end
end

这将覆盖模型中的keywords setter,在传递数组的情况下传递连接的字符串。

答案 1 :(得分:0)

我相信在传递给控制器​​时,对字符串字段使用多重选择将被格式化为JSON数组。

因此,击中控制器的参数类似于以下内容:

{ keywords: { keywords: '["kw1", "kw12"]' } }

因此,要将它作为逗号分隔的字符串存储在数据库中,您需要先使用以下内容解析它:

JSON.parse(params[:keywords][:keywords]).reject(&:blank?).join(', ')

这里有几个问题:

使用像这样的多选通常(总是?)首先返回一个空值,因此reject(&:blank?)

如果params返回nil,尝试解析这会引发错误,因此您可能希望定义一个方法来处理此问题,例如:

def string_from_json(vals)
  return unless vals.present?
  JSON.parse(vals).reject(&:blank?).join(', ')
end

或者你可以救出JSON::ParseError或其他东西。

最后,你打电话给keywords = string_from_json(params[:keywords][:keywords])来获取字符串。

希望有所帮助!

编辑:

那将处理解析,然后您可以在控制器中使用控制器中的简单@article.keywords = keywords@article.update_attribute(:keywords, keywords)或Daniel推荐的方法进行解析。