• (Gorails) activeStore模块,把一堆属性放在一个hash对象内。gem 'activerecord-typedstore'增强了store模块,更好用了


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

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

    我的git:  https://github.com/chentianwei411/embeddable_comments


          本次视频讲解使用ActiveRecord::Store 和增强插件 ActiveRecord-TypedStore来保存用户偏好设置,并把数据存储在一个单一的column中。

    ActiveRecord::Store

    Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column. It's like a simple key/value store baked into your record when you don't care about being able to query that store outside the context of a single record. 

    Store给你一个简单的包装把一系列相同目的的hash对象储存在一个column中。

    如果你不需要对这个store的内容进行检索的话,store就像是一个简单的key/value对儿,存储在你的record中。

    给这个store声明一个accessors.

    ⚠️注意存储类型是text。以便有足够的存储空间。

    你可以设置代码来编码/解码你的属性 从/到不同的formats。JSON, YAML等。

    ⚠️如果使用PostgreSQL来指定columns如hstore或json,无需为这些属性提供.store,只需要使用.store_accessor来生成accessor methods。(⚠️使用的是string key,不能用symbol)

    ⚠️验证选项 uniqueness 默认是启用的。

     

    视频的步骤:

    不同的用户进行自定义的设置 。可以把不同功能的设置以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

    如果使用PostgreSQL数据库,可以使用JSON格式的列,JSON格式的列是可以被查询的。而text格式不行。

    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>

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

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

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

    class Shop < ActiveRecord::Base
    
      typed_store :settings, coder: JSON 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: 'george@cyclim.se')
    shop.public?        # => false
    shop.email          # => 'george@cyclim.se'
    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'

    无需使用migration来增加/移除了。

    默认是不能查询这些属性的,(unless you use JSON or Postgres HStore types)

    使用JSON column 而不是text column的话, JSON column可以被查询:

    User.where("preferences ->> 'playback_rate' = '2.0'")

    另一种写法:

    User.where("preferences ->> :key = :value", key: "playback_rate", value: "2.0")

    ->>锯齿箭头: 在preferences内 查找playback_rate的值等于2.0的记录

    如果使用PostgreSQL数据库,可以使用JSON格式的列,JSON格式的列是可以被查询的。而text格式不行。

     

  • 相关阅读:
    Linux XZ格式的解压
    Linux eject弹出光驱
    什么是错误链接/死链接
    什么是相对地址和绝对地址
    网站被K或者降权后应该如何恢复
    网络营销怎么做才有“钱”途
    如何通过seo技术提高网站对用户的友好度
    如何利用微博客进行seo赚钱营销
    做SEO必须制定超越竞争对手网站的方案
    文章很快收录后又被删除的原因
  • 原文地址:https://www.cnblogs.com/chentianwei/p/9820817.html
Copyright © 2020-2023  润新知