simple-immutable 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ee7113a903d3124b8d4c64499cc3dcd3ae296d6d4b45c6178b5205c3baae8675
4
+ data.tar.gz: 722814d2e633c8a7ea57c71b5add682ee62f46bffc113ad2047bc1b281dc9516
5
+ SHA512:
6
+ metadata.gz: a6328926689c3ded5d5e6a3ae4f24b0fcc73663ef0d2aec26019c0ec6fc705c8f7da903fcb9aba8a917c75884b3299f603d3f521af95bf5cd4b7d7dd6f8c2c0c
7
+ data.tar.gz: adae1e19d19f7ce6a4c152b6137d27689c679d11ca91150bf04fd49115f8ba67ec080f1f2ba965e2e8111a08ce6ef3b58b4ef7bdefbb9730adadd63a6ff434b2
@@ -0,0 +1,10 @@
1
+ coverage
2
+ rdoc
3
+ pkg
4
+ log/test.log
5
+ .rspec.data
6
+ Gemfile.lock
7
+ .rake_t_cache
8
+ .rspec.status
9
+ .DS_Store
10
+ tmp
@@ -0,0 +1,9 @@
1
+ # Settings
2
+ fontName = "Menlo"
3
+ fontSize = 13
4
+ fileBrowserGlob = "{*,.tm_properties,.htaccess,}"
5
+ excludeDirectories = "{node_modules,coverage,log,}"
6
+
7
+ # Variables
8
+ PATH = "$PATH:$HOME/bin"
9
+ TM_GIT = "/opt/local/bin/git"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in {gemname}.gemspec
4
+ gemspec
@@ -0,0 +1,7 @@
1
+ default: test
2
+
3
+ test:
4
+ ruby lib/simple/immutable.rb
5
+
6
+ release:
7
+ scripts/release.rb
@@ -0,0 +1,38 @@
1
+ # simple-immutable
2
+
3
+ Turns a nested data structure into a immutable ruby object implementing dot and [] accessors.
4
+
5
+ ## Usage
6
+
7
+
8
+ Immutable = ::Simple::Immutable
9
+
10
+ data =
11
+ {
12
+ a: "a-value",
13
+ "b": "b-value",
14
+ "child": {
15
+ name: "childname",
16
+ grandchild: {
17
+ name: "grandchildname"
18
+ }
19
+ },
20
+ "children": [
21
+ "anna",
22
+ "arthur",
23
+ {
24
+ action: {
25
+ keep_your_mouth_shut: true
26
+ }
27
+ }
28
+ ]
29
+ }
30
+
31
+ imm = Immutable.create(data)
32
+
33
+ imm.a # -> 'a-value'
34
+ imm.children.class # -> Array
35
+ imm.children[2].action.keep_your_mouth_shut # -> true
36
+ imm.children.foo # NoMethodError (undefined method `foo' for #<Array:0x00007fb90f1be390>)
37
+ imm.children.first.foo # NoMethodError (undefined method `foo' for "anna":String)
38
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.1
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'bundle' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "rubygems"
12
+
13
+ m = Module.new do
14
+ module_function
15
+
16
+ def invoked_as_script?
17
+ File.expand_path($0) == File.expand_path(__FILE__)
18
+ end
19
+
20
+ def env_var_version
21
+ ENV["BUNDLER_VERSION"]
22
+ end
23
+
24
+ def cli_arg_version
25
+ return unless invoked_as_script? # don't want to hijack other binstubs
26
+ return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27
+ bundler_version = nil
28
+ update_index = nil
29
+ ARGV.each_with_index do |a, i|
30
+ if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31
+ bundler_version = a
32
+ end
33
+ next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34
+ bundler_version = $1 || ">= 0.a"
35
+ update_index = i
36
+ end
37
+ bundler_version
38
+ end
39
+
40
+ def gemfile
41
+ gemfile = ENV["BUNDLE_GEMFILE"]
42
+ return gemfile if gemfile && !gemfile.empty?
43
+
44
+ File.expand_path("../../Gemfile", __FILE__)
45
+ end
46
+
47
+ def lockfile
48
+ lockfile =
49
+ case File.basename(gemfile)
50
+ when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51
+ else "#{gemfile}.lock"
52
+ end
53
+ File.expand_path(lockfile)
54
+ end
55
+
56
+ def lockfile_version
57
+ return unless File.file?(lockfile)
58
+ lockfile_contents = File.read(lockfile)
59
+ return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60
+ Regexp.last_match(1)
61
+ end
62
+
63
+ def bundler_version
64
+ @bundler_version ||= begin
65
+ env_var_version || cli_arg_version ||
66
+ lockfile_version || "#{Gem::Requirement.default}.a"
67
+ end
68
+ end
69
+
70
+ def load_bundler!
71
+ ENV["BUNDLE_GEMFILE"] ||= gemfile
72
+
73
+ # must dup string for RG < 1.8 compatibility
74
+ activate_bundler(bundler_version.dup)
75
+ end
76
+
77
+ def activate_bundler(bundler_version)
78
+ if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
79
+ bundler_version = "< 2"
80
+ end
81
+ gem_error = activation_error_handling do
82
+ gem "bundler", bundler_version
83
+ end
84
+ return if gem_error.nil?
85
+ require_error = activation_error_handling do
86
+ require "bundler/version"
87
+ end
88
+ return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
89
+ warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
90
+ exit 42
91
+ end
92
+
93
+ def activation_error_handling
94
+ yield
95
+ nil
96
+ rescue StandardError, LoadError => e
97
+ e
98
+ end
99
+ end
100
+
101
+ m.load_bundler!
102
+
103
+ if m.invoked_as_script?
104
+ load Gem.bin_path("bundler", "bundle")
105
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ $: << "lib"
3
+ require "simple/immutable"
4
+
5
+ require "irb"
6
+ require "irb/completion"
7
+
8
+ IRB.start
@@ -0,0 +1 @@
1
+ require "simple/immutable"
@@ -0,0 +1,148 @@
1
+ module Simple
2
+ end
3
+
4
+ class Simple::Immutable
5
+ SELF = self
6
+
7
+ # turns an object, which can be a hash or array of hashes, arrays, and scalars
8
+ # into an object which you can use to access with dot methods.
9
+ def self.create(object, max_depth = 5)
10
+ case object
11
+ when Array
12
+ raise ArgumentError, "Object nested too deep (or inner loop?)" if max_depth < 0
13
+
14
+ object.map { |obj| create obj, max_depth - 1 }
15
+ when Hash
16
+ new(object)
17
+ else
18
+ object
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def initialize(hsh)
25
+ @hsh = hsh
26
+ end
27
+
28
+ def method_missing(sym, *args, &block)
29
+ if args.empty? && !block
30
+ begin
31
+ value = @hsh.fetch(sym.to_sym) { @hsh.fetch(sym.to_s) }
32
+ return SELF.create(value)
33
+ rescue KeyError
34
+ # STDERR.puts "Missing attribute #{sym} for Immutable w/#{@hsh.inspect}"
35
+ nil
36
+ end
37
+ end
38
+
39
+ super
40
+ end
41
+
42
+ public
43
+
44
+ def respond_to_missing?(method_name, include_private = false)
45
+ @hsh.key?(method_name.to_sym) ||
46
+ @hsh.key?(method_name.to_s) ||
47
+ super
48
+ end
49
+
50
+ def inspect
51
+ "<Immutable: #{@hsh.inspect}>"
52
+ end
53
+
54
+ def respond_to?(sym)
55
+ super || @hsh.key?(sym.to_s) || @hsh.key?(sym.to_sym)
56
+ end
57
+
58
+ def ==(other)
59
+ @hsh == other
60
+ end
61
+ end
62
+
63
+ if $PROGRAM_NAME == __FILE__
64
+
65
+ # rubocop:disable Metrics/AbcSize
66
+
67
+ require "test-unit"
68
+
69
+ class Simple::Immutable::TestCase < Test::Unit::TestCase
70
+ Immutable = ::Simple::Immutable
71
+
72
+ def hsh
73
+ {
74
+ a: "a-value",
75
+ "b": "b-value",
76
+ "child": {
77
+ name: "childname",
78
+ grandchild: {
79
+ name: "grandchildname"
80
+ }
81
+ },
82
+ "children": [
83
+ "anna",
84
+ "arthur",
85
+ {
86
+ action: {
87
+ keep_your_mouth_shut: true
88
+ }
89
+ }
90
+ ]
91
+ }
92
+ end
93
+
94
+ def immutable
95
+ Immutable.create hsh
96
+ end
97
+
98
+ def test_hash_access
99
+ assert_equal "a-value", immutable.a
100
+ assert_equal "b-value", immutable.b
101
+ end
102
+
103
+ def test_comparison
104
+ immutable = Immutable.create hsh
105
+
106
+ assert_equal immutable, hsh
107
+ assert_not_equal({}, immutable)
108
+ end
109
+
110
+ def test_child_access
111
+ child = immutable.child
112
+ assert_kind_of(Immutable, child)
113
+ assert_equal "childname", immutable.child.name
114
+ assert_equal "grandchildname", immutable.child.grandchild.name
115
+ end
116
+
117
+ def test_array_access
118
+ assert_kind_of(Array, immutable.children)
119
+ assert_equal 3, immutable.children.length
120
+ assert_equal "anna", immutable.children[0]
121
+
122
+ assert_kind_of(Immutable, immutable.children[2])
123
+ assert_equal true, immutable.children[2].action.keep_your_mouth_shut
124
+ end
125
+
126
+ def test_base_class
127
+ assert_nothing_raised do
128
+ immutable.object_id
129
+ end
130
+ end
131
+
132
+ def test_missing_keys
133
+ assert_raise(NoMethodError) do
134
+ immutable.foo
135
+ end
136
+ end
137
+
138
+ def test_skip_when_args_or_block
139
+ assert_raise(NoMethodError) do
140
+ immutable.a(1, 2, 3)
141
+ end
142
+ assert_raise(NoMethodError) do
143
+ immutable.a { :dummy }
144
+ end
145
+ end
146
+ end
147
+
148
+ end
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ $0.rb "$@"
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # -- helpers ------------------------------------------------------------------
4
+
5
+ def sys(cmd)
6
+ STDERR.puts "> #{cmd}"
7
+ system cmd
8
+ return true if $?.success?
9
+
10
+ STDERR.puts "> #{cmd} returned with exitstatus #{$?.exitstatus}"
11
+ $?.success?
12
+ end
13
+
14
+ def sys!(cmd, error: nil)
15
+ return true if sys(cmd)
16
+ STDERR.puts error if error
17
+ exit 1
18
+ end
19
+
20
+ def die!(msg)
21
+ STDERR.puts msg
22
+ exit 1
23
+ end
24
+
25
+ ROOT = File.expand_path("#{File.dirname(__FILE__)}/..")
26
+
27
+ GEMSPEC = Dir.glob("*.gemspec").first || die!("Missing gemspec file.")
28
+
29
+ # -- Version reading and bumping ----------------------------------------------
30
+
31
+ module Version
32
+ extend self
33
+
34
+ VERSION_FILE = "#{Dir.getwd}/VERSION"
35
+
36
+ def read_version
37
+ version = File.exist?(VERSION_FILE) ? File.read(VERSION_FILE) : "0.0.1"
38
+ version.chomp!
39
+ raise "Invalid version number in #{VERSION_FILE}" unless version =~ /^\d+\.\d+\.\d+$/
40
+ version
41
+ end
42
+
43
+ def auto_version_bump
44
+ old_version_number = read_version
45
+ old = old_version_number.split('.')
46
+
47
+ current = old[0..-2] << old[-1].next
48
+ current.join('.')
49
+ end
50
+
51
+ def bump_version
52
+ next_version = ENV["VERSION"] || auto_version_bump
53
+ File.open(VERSION_FILE, "w") { |io| io.write next_version }
54
+ end
55
+ end
56
+
57
+ # -- check, bump, release a new gem version -----------------------------------
58
+
59
+ Dir.chdir ROOT
60
+ $BASE_BRANCH = ENV['BRANCH'] || 'master'
61
+
62
+ # ENV["BUNDLE_GEMFILE"] = "#{Dir.getwd}/Gemfile"
63
+ # sys! "bundle install"
64
+
65
+ sys! "git diff --exit-code > /dev/null", error: 'There are unstaged changes in your working directory'
66
+ sys! "git diff --cached --exit-code > /dev/null", error: 'There are staged but uncommitted changes'
67
+
68
+ sys! "git checkout #{$BASE_BRANCH}"
69
+ sys! "git pull"
70
+
71
+ Version.bump_version
72
+ version = Version.read_version
73
+
74
+ sys! "git add VERSION"
75
+ sys! "git commit -m \"bump gem to v#{version}\""
76
+ sys! "git tag -a v#{version} -m \"Tag #{version}\""
77
+
78
+ sys! "git push origin #{$BASE_BRANCH}"
79
+ sys! 'git push --tags --force'
80
+
81
+ sys! "gem build #{GEMSPEC}"
82
+ sys! "mkdir -p pkg"
83
+ sys! "mv *.gem pkg"
84
+
85
+ gem_file = Dir.glob('pkg/*.gem').sort.last
86
+
87
+ sys! "gem install #{gem_file}"
88
+ sys! "gem push #{gem_file}"
89
+
90
+ STDERR.puts <<-MSG
91
+ ================================================================================
92
+ Thank you for releasing a new gem version. You made my day.
93
+ ================================================================================
94
+ MSG
@@ -0,0 +1,25 @@
1
+ # This file is part of the sinatra-sse ruby gem.
2
+ #
3
+ # Copyright (c) 2016, 2017 @radiospiel, mediapeers Gem
4
+ # Distributed under the terms of the modified BSD license, see LICENSE.BSD
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "simple-immutable"
8
+ gem.version = File.read "VERSION"
9
+
10
+ gem.authors = [ "radiospiel", "mediapeers GmbH" ]
11
+ gem.email = "eno@radiospiel.org"
12
+ gem.homepage = "http://github.com/radiospiel/simple-immutable"
13
+ gem.summary = "Immutable ruby objects"
14
+
15
+ gem.description = "Immutable ruby objects implementing dot and [] accessors."
16
+
17
+ gem.files = `git ls-files`.split($/)
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = %w(lib)
20
+
21
+ # executables are used for development purposes only
22
+ gem.executables = []
23
+
24
+ gem.required_ruby_version = '~> 2.3'
25
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple-immutable
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - radiospiel
8
+ - mediapeers GmbH
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2020-03-03 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Immutable ruby objects implementing dot and [] accessors.
15
+ email: eno@radiospiel.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".tm_properties"
22
+ - Gemfile
23
+ - Makefile
24
+ - README.md
25
+ - VERSION
26
+ - bin/bundle
27
+ - bin/console
28
+ - lib/simple-immutable.rb
29
+ - lib/simple/immutable.rb
30
+ - scripts/release
31
+ - scripts/release.rb
32
+ - simple-immutable.gemspec
33
+ homepage: http://github.com/radiospiel/simple-immutable
34
+ licenses: []
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - "~>"
43
+ - !ruby/object:Gem::Version
44
+ version: '2.3'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 3.0.6
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: Immutable ruby objects
55
+ test_files: []