(Gorails) activeStore

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

https://gorails.com/episodes/preferences-settings-with-activerecord-store?autoplay=1


不同的用户进行自定义的设置 。可以把不同功能的设置以key/value的格式放入一个hash内。这样就只需要一个column在数据库了,无需多个column(显得很乱)。

 初始化一个表格:

def change
  create_table :users do |t|
    t.text :settings
    t.json :preferences
  end
end

 preferences which will be a JSON column in a PostgreSQL

class User < ActiveRecord::Base
  store :settings, accessors: [ :weekly_email, :monthly_newsletter], coder: JSON
end

settings将存储一个对象, :weekly_email是key,值是一个string。

可以直接定义user = User.new(weekly_email: "2 weeks")

user.settings 会得到这个hash对象。例如 : { "weekly_email" => "xx"}

可以用user.settings[:newcontent] = "xxx"的格式,增加任意的属性。

使用coder: JSON 选项来编码/解码你的序列的属性。

在控制台:

u = User.last

=> #<User id: 1, settings: {"weekly_email"=>"0", preferences: nil, ...}>

但是在log上查看:是一个JSON string, 因为我们定义了code: JSON

UPDATE "users" SET "settings" = $1, "updated_at" = $2 WHERE "users"."id" = $3 [["settings", "{\"weekly_email\":\"0\"}"], ["updated_at", "xxx"], ["id", 1]]

用JSON格式编码成一个JSON string存入database中的数据格式为text的column(weekly_email),

从database取出数据后,再把JSON格式转化为Ruby hash格式。

class User < ActiveRecord::Base
  store :settings, accessors: [ :weekly_email, :monthly_newsletter], coder: JSON

  //如果使用PostgreSQL数据库,则使用store_accessor代替store
  //需要使用a string keyed hash, 不能用symbol
  store_accessor :preferneces, :playback_rate   //默认coder: JSON
end

 ⚠️: weekly_email, playback_rate需要加入params_user白名单。

<div class="field">
  <%= form.label :playback_rate %>
  <%= form.select :playback_rate, [0.5, 1, 1.5, 2] %>
</div>

一个缺陷是不能自定义settings属性内的key的值的type类型。

因此gem 'activerecord-typedstore', 可以解决这个问题:

用法类似,也简单,和建立activerecord的migrations很像:

class Shop < ActiveRecord::Base

  typed_store :settings do |s|
    s.boolean :public, default: false, null: false
    s.string :email
    s.datetime :publish_at
    s.integer :age, null: false

    # You can define array attributes like in rails 4 and postgres
    s.string :tags, array: true, default: [], null: false

    # In addition to prevent null values you can prevent blank values
    s.string :title, blank: false, default: 'Title'

    # If you don't want to enforce a datatype but still like to have default handling
    s.any :source, blank: false, default: 'web'
  end

  # You can use any ActiveModel validator
  validates :age, presence: true

end

# 值可以像正常的model属性一样存取 
shop = Shop.new(email: '[email protected]')
shop.public?        # => false
shop.email          # => '[email protected]'
shop.published_at   # => nil

# Values are type casted,用update_attributes()方法更新
shop.update_attributes(
  age: '42',
  published_at: '1984-06-08 13:57:12'
)
shop.age                # => 42
shop.published_at.class #= DateTime

# 值是否变化,有对应的方法可以跟踪:
shop.age_changed? # => false
shop.age = 12
shop.age_changed? # => true
shop.age_was      # => 42

# You can still use it as a regular store,可以用标准的store存取属性,但多了save
shop.settings[:unknown] = 'Hello World'
shop.save
shop.reload
shop.settings[:unknown] # => 'Hello World'

猜你喜欢

转载自www.cnblogs.com/chentianwei/p/9820817.html