A simple library that handles a few records easily. With this library can flexibly managed immutable data.
Install as a standalone gem
$ gem install memory_record
Or install within application using Gemfile
$ bundle add memory_record
$ bundle install
class Palette
include MemoryRecord
memory_record [
{ key: :coral, },
{ key: :tomato, },
{ key: :gold, },
]
end
Palette[:tomato].key # => :tomato
Palette[:tomato].name # => "tomato"
Palette[:tomato].code # => 1
class Palette
include MemoryRecord
memory_record [
{ key: :coral, r: 255, g: 127, b: 0 },
{ key: :tomato, r: 255, g: 99, b: 71 },
{ key: :gold, r: 255, g: 215, b: 0 },
]
end
Palette[:tomato].key # => :tomato
Palette[:tomato].name # => "tomato"
Palette[:tomato].code # => 1
Palette[:tomato].r # => 255
Palette[:tomato].g # => 99
Palette[:tomato].b # => 71
class Palette
include MemoryRecord
memory_record [
{ key: :coral, r: 255, g: 127, b: 0 },
{ key: :tomato, r: 255, g: 99, b: 71 },
{ key: :gold, r: 255, g: 215, b: 0 },
]
def rgb
[r, g, b]
end
def hex
"#" + rgb.collect { |e| "%02X" % e }.join
end
def name
super.capitalize
end
end
Palette[:tomato].key # => :tomato
Palette[:tomato].name # => "Tomato"
Palette[:tomato].code # => 1
Palette[:tomato].rgb # => [255, 99, 71]
Palette[:tomato].hex # => "#FF6347"
Palette.collect(&:hex) # => ["#FF7F00", "#FF6347", "#FFD700"]
Enumerable extended, so that each method is available
Palette.each { |e| ... }
Palette.collect { |e| ... }
form.collection_select(:pallet_key, Palette, :key, :name) // object[pallet_key]=tomato
form.collection_select(:pallet_key, Palette, :code, :name) // object[pallet_key]=1
Either way can see it with Palette[pallet_key]
Since it has a hash internally using the key value as a key, it can be acquired with O (1).
Palette[1].name # => "Tomato"
Palette[:tomato].name # => "Tomato"
object = Palette[:tomato]
object.key # => :tomato
object.code # => 1
For that, I am creating a new class so I need to define it normally
If name is not defined, it defines a name method that returns key.to_s
Alias of name, to_s is defined.
Palette.fetch(:xxx) # => <KeyError: ...>
The following are all the same
Palette[:xxx] || :default # => :default
Palette.fetch(:xxx, :default} # => :default
Palette.fetch(:xxx) { :default } # => :default
Palette.fetch_if(nil) # => nil
Palette.fetch_if(:tomato) # => #<Palette:... @attributes={...}>
Palette.fetch_if(:xxx) # => <KeyError: ...>
Palette.lookup_key(:tomato) # => :tomato
Palette.lookup_key("tomato") # => :tomato
Palette.lookup_key(1) # => :tomato
Palette.lookup_key(:xxx) # => nil
Palette.lookup_key(:xxx, :tomato) # => :tomato
Palette.lookup_key(:xxx) { :tomato } # => :tomato
Palette.lookup_key(:xxx, :tomato) # => :tomato
Palette.lookup_key(:xxx, :black) rescue $! # => #<KeyError: Palette.fetch(:black) does not match anything
palette_key = Palette.lookup_key(params[:palette_key], :tomato)
class Foo
include MemoryRecord
memory_record [
{ key: :a, other_key: :x },
{ key: :b, other_key: :y },
{ key: :c, other_key: :z },
]
class << self
def lookup(v)
super || invert_table[v]
end
private
def invert_table
@invert_table ||= inject({}) {|a, e| a.merge(e.other_key => e) }
end
end
end
Foo[:a] == Foo[:x] # => true
Foo[:b] == Foo[:y] # => true
Foo[:c] == Foo[:z] # => true
Use attr_reader: false
or attr_reader: {only: ...}
or attr_reader: {except: ...}
class Foo
include MemoryRecord
memory_record attr_reader: {only: :y} do
[
{ x: 1, y: 1, z: 1 },
]
end
end
Foo.first.x rescue $! # => #<NoMethodError: undefined method `x' for #<Foo:0x007fcc861ff108>>
Foo.first.y rescue $! # => 1
Foo.first.z rescue $! # => #<NoMethodError: undefined method `z' for #<Foo:0x007fcc861ff108>>
class Foo
include MemoryRecord
memory_record [
{ code: 1, key: :a, name: "A" },
{ code: 2, key: :b, name: "B" },
]
end
Foo.collect(&:code) # => [1, 2]
It is not recommended to specify it explicitly. It is useful only when refactoring legacy code with compatibility in mind.
Similar to ActiveModel's serialization, there is an only
except
methods
include
method.
class ColorInfo
include MemoryRecord
memory_record [
{ key: :blue, rgb: [ 0, 0, 255], },
{ key: :red, rgb: [255, 0, 0], },
]
def hex
"#" + rgb.collect { |e| "%02X" % e }.join
end
def children
[
{x: 1, y: 2},
{x: 3, y: 4},
]
end
end
color_info = ColorInfo.first
color_info.as_json # => {:key=>:blue, :rgb=>[0, 0, 255], :a=>1, :code=>0}
color_info.as_json(only: :key) # => {:key => :blue}
color_info.as_json(except: [:rgb, :code]) # => {:key => :blue}
color_info.as_json(only: [], methods: :hex) # => {:hex => "#0000FF"}
color_info.as_json(only: [], include: {children: {only: :x}} ) # => {:children => [{"x" => 1}, {"x" => 3}]}
ColorInfo.as_json(only: :key) # => [{:key=>:blue}, {:key=>:red}]
ColorInfo.to_json(only: :key) # => "[{\"key\":\"blue\"},{\"key\":\"red\"}]"
class ColorInfoSerializer < ActiveModel::Serializer
attributes :key
end
ActiveModelSerializers::SerializableResource.new(ColorInfo.first).as_json # => { :key => :blue }