在Rails(5.2)应用程序中,我有一个Project
模型,该模型的tags
属性定义为Postgresql数组。
create_table :projects do |t|
...
t.text :tags, array: true, default: []
...
end
我希望将标签转换为字符串,而不是将其转换为Tag
的对象
class Tag
...
attr_reader :name
def initialize(name)
@name = name
end
...
end
为此,我正在尝试使用Rails 5随附的属性API。
class Project < ApplicationRecord
attribute :tags, TagType.new, array: true
...
end
class TagType < ActiveRecord::Type::Value
def cast(names)
names.split(',').map { |name| Tag.new(name) }
end
end
这种工作会创建Tag
对象,但名称的第一个和最后一个都有方括号。
Project.create(tags: ['one', 'two', 'three'])
Project.first.tags.map(&:name) #=> ['{one', 'two', 'three}']
是否有比从names
中的TagType
手动删除括号来获得正确的Tag
更好的方法?
试图在Rails代码中找到解析数组值但到目前为止没有运气的地方。
答案 0 :(得分:1)
这是我正在寻找的更通用的版本:
# config/initializers/text_array.rb
class TextArrayType < ActiveRecord::Type::Value
include ActiveModel::Type::Helpers::Mutable
def cast(value)
case
when value.is_a?(Array)
value
when value.present?
value.split(/[\s,]+/)
else
[]
end
end
def deserialize(value)
PG::TextDecoder::Array.new.decode(value)
end
def serialize(value)
PG::TextEncoder::Array.new.encode(value)
end
end
ActiveRecord::Type.register(:text_array, TextArrayType)
这将使您能够添加标签,如:
create_table :projects do |t|
...
t.text :tags, array: true, default: []
...
end
class Project < ApplicationRecord
attribute :tags, :text_array
end
我想实现的目标是能够将标签既作为数组又作为逗号分隔的列表添加:
Project.new(tags: ["x", "y", "z"] # => tags: ["x", "y", "z"]
Project.new(tags: "x, y, z") # => tags: ["x", "y", "z"]
这将使您能够以逗号分隔列表的形式添加多个标签:
f.text_area :tags, value: @project.tags.join(", ")
以及在项目中其他任何地方将标签作为数组进行管理。
答案 1 :(得分:0)
这是我最终得到的代码
class TagType < ActiveRecord::Type::Value
include ActiveModel::Type::Helpers::Mutable
def cast(name)
Tag.new(name)
end
def deserialize(names)
PG::TextDecoder::Array.new.decode(names).map { |name| cast(name) }
end
def serialize(tags)
PG::TextEncoder::Array.new.encode(tags.map(&:name))
end
end
希望这会有所帮助。