Rails 关于 Rails+Postgresql 的 Array 字段问题

brookepowell · 2022年03月17日 · 最后由 brookepowell 回复于 2022年03月18日 · 322 次阅读

数据库是 postgresql, 在articles表中创建了Array类型的字段tag_ids,接收数组类型的标签 id。

在网页上进行添加记录操作时,text_field中的值为字符型1,3,5,在进行create操作时需要预处理成数组才能正常添加到数据库。

目前使用的如下方法,感觉不优雅:

class ArticlesController < ApplicationController
  def new
    @article = Article.new
  end

  def create
    @article = Article.new(allowed_params)
    # 处理tag_ids为数组,再赋值一次
    # 如果不这样处理,tag_ids在数据库中的值会被错误解析
    if allowed_params[:tag_ids].is_a?(String) && allowed_params[:tag_ids].present?
      @article.tag_ids = allowed_params[:tag_ids].split(",").compact.uniq.map(&:to_i)
    end
    if @article.save
      redirect_to articles_path
    else
      render :new
    end
  end

  private

  def allowed_params
    params.require(:article).permit(
      :title, :tag_ids,
    )
  end
end

请问有没有更优雅的方式处理参数?


已解决:

还是通过修改前端提交的参数类型为数组解决了,这样比较优雅些。

写成这样也 ok。但为什么不直接传数组勒

spike76 回复

因为网页上的text_field的值是由 js 的多选输入框生成的,生成的值就是1,3,5这种形式,不能传数组。

brookepowell 回复

或者用模型的钩子处理?

class Article < ActiveRecord
  before_validation :convert_tag_ids_to_array, if: ->{ tag_ids.is_a?(String) && tag_ids.present?  }


  private 

  def convert_tag_ids_to_array
    self.tag_ids = tag_ids.split(",").compact.uniq.map(&:to_i)
  end
end
brookepowell 回复

提交之前处理一下呗。。。

brookepowell 回复

rails_param 这个 gem 倒是内置了你要的效果,在 action 中使用param! :tag_ids, Array 就能把逗号分隔的参数转为数组。不过单纯为了这个功能而引入一个 gem 有点划不来,可以考虑自己手动封装个类似的方法。

spike76 回复

能用 gem 解决的绝不手动写。。。

比较习惯用一个 permit 方法来处理


private
def allowed_params
    permitted_params = params.require(:article).permit(
      :title, :tag_ids,
    )
    permitted_params['tag_ids']  = permitted_params[:tag_ids].split(",").compact.uniq.map(&:to_i)
    permitted_params
  end

create方法可以短一点update方法也能直接用。

lanzhiheng 回复

试了一下这个方法,会报错: Unpermitted parameters: :tag_ids 最终的permitted_params中丢失了tag_ids参数

brookepowell 关闭了讨论。 03月18日 18:29
需要 登录 后方可回复, 如果你还没有账号请 注册新账号