Gem hash_map_attributes 将 JSON 类型的字段映射为具体的方法,方便 CRUD

SuMingXuan · 2020年11月04日 · 最后由 SuMingXuan 回复于 2021年04月09日 · 548 次阅读

项目地址:

https://github.com/SuMingXuan/hash_map_attributes/

写这个插件是因为目前在我做写业务的时候,需要预留一个 json 字段方便以后数据的扩展,并且方便 CRUD。比如我有一个 pages 表包含了一个 jsonb 类型的字段(extra_data),extra_data 里面可能存很多额外的属性或者是目前我们没有考虑到的属性。让我痛苦的是,对这种类型的字段操作 CRUD 会让代码变得非常难看。

Usage

class Page < ApplicationRecord
    # == Schema Information
    #
    # Table name: special_channels
    #
    #  id          :bigint           not null, primary key
    #  description :string
    #  title       :string
    #  extra_data  :jsonb
    #  created_at  :datetime         not null
    #  updated_at  :datetime         not null
  include HashMapAttributes
  hash_map_attributes :image_url, to: :extra_data
  hash_map_attributes :background_url, prefix: :content, to: :extra_data

end

page = Page.new(image_url: 'http://www.image.com/example1.png', content_background_url: 'http://www.image.com/example2.png')
page.save
page.image_url #=> http://www.image.com/example1.png
page.content_background_url #=> http://www.image.com/example2.png
page.update(image_url: ' http://www.image.com/example3.png')
page.image_url #=> http://www.image.com/example3.png

查询

如果是 jsonb 的话,那么则支持查询

Page.where_hash(image_url: 'http://www.baidu.com', content_background_url: 'http://www.baklib.com')

控制台会打印如下查询语句

SELECT "pages".* FROM "pages" WHERE (pages.extra_data->>'image_url' = 'http://www.baidu.com' and pages.extra_data->>'background_url' = 'http://www.baklib.com')

补充:现在支持嵌套 json 的查询和修改了,但是取消了指定前缀的参数。

pynix 回复

😀 是这样的,笔误了

这个是 ActiveRecord::Store 可以完成的事情呀

https://api.rubyonrails.org/v5.2.0/classes/ActiveRecord/Store.html

class User < ActiveRecord::Base
  store :settings, accessors: [ :color, :homepage ], coder: JSON
  store :parent, accessors: [ :name ], coder: JSON, prefix: true
  store :spouse, accessors: [ :name ], coder: JSON, prefix: :partner
  store :settings, accessors: [ :two_factor_auth ], suffix: true
  store :settings, accessors: [ :login_retry ], suffix: :config
end

u = User.new(color: 'black', homepage: '37signals.com', parent_name: 'Mary', partner_name: 'Lily')
u.color                          # Accessor stored attribute
u.parent_name                    # Accessor stored attribute with prefix
u.partner_name                   # Accessor stored attribute with custom prefix
u.two_factor_auth_settings       # Accessor stored attribute with suffix
u.login_retry_config             # Accessor stored attribute with custom suffix
u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor

# There is no difference between strings and symbols for accessing custom attributes
u.settings[:country]  # => 'Denmark'
u.settings['country'] # => 'Denmark'

# Dirty tracking
u.color = 'green'
u.color_changed? # => true
u.color_was # => 'black'
u.color_change # => ['black', 'red']
huacnlee 回复

啊 是的,当时不知道有这个东西所以就写了这个东西去处理 😹

需要 登录 后方可回复, 如果你还没有账号请 注册新账号