rom-cassandra 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +9 -0
  4. data/.metrics +9 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +2 -0
  7. data/.travis.yml +26 -0
  8. data/.yardopts +3 -0
  9. data/CHANGELOG.md +3 -0
  10. data/Gemfile +7 -0
  11. data/Guardfile +14 -0
  12. data/LICENSE +21 -0
  13. data/README.md +83 -0
  14. data/Rakefile +34 -0
  15. data/config/metrics/STYLEGUIDE +230 -0
  16. data/config/metrics/cane.yml +5 -0
  17. data/config/metrics/churn.yml +6 -0
  18. data/config/metrics/flay.yml +2 -0
  19. data/config/metrics/metric_fu.yml +14 -0
  20. data/config/metrics/reek.yml +1 -0
  21. data/config/metrics/roodi.yml +24 -0
  22. data/config/metrics/rubocop.yml +84 -0
  23. data/config/metrics/saikuro.yml +3 -0
  24. data/config/metrics/simplecov.yml +6 -0
  25. data/config/metrics/yardstick.yml +37 -0
  26. data/lib/rom-cassandra.rb +3 -0
  27. data/lib/rom/cassandra.rb +33 -0
  28. data/lib/rom/cassandra/commands.rb +53 -0
  29. data/lib/rom/cassandra/commands/batch.rb +54 -0
  30. data/lib/rom/cassandra/commands/create.rb +38 -0
  31. data/lib/rom/cassandra/commands/delete.rb +38 -0
  32. data/lib/rom/cassandra/commands/update.rb +38 -0
  33. data/lib/rom/cassandra/dataset.rb +102 -0
  34. data/lib/rom/cassandra/gateway.rb +115 -0
  35. data/lib/rom/cassandra/migrations.rb +30 -0
  36. data/lib/rom/cassandra/migrations/generator.rb +68 -0
  37. data/lib/rom/cassandra/migrations/generator/migration.erb +32 -0
  38. data/lib/rom/cassandra/migrations/logger.rb +28 -0
  39. data/lib/rom/cassandra/migrations/migration.rb +107 -0
  40. data/lib/rom/cassandra/migrations/migrator.rb +103 -0
  41. data/lib/rom/cassandra/migrations/runner.rb +119 -0
  42. data/lib/rom/cassandra/migrations/runner_down.rb +49 -0
  43. data/lib/rom/cassandra/migrations/runner_up.rb +50 -0
  44. data/lib/rom/cassandra/query.rb +43 -0
  45. data/lib/rom/cassandra/relation.rb +88 -0
  46. data/lib/rom/cassandra/session.rb +50 -0
  47. data/lib/rom/cassandra/tasks.rb +6 -0
  48. data/lib/rom/cassandra/version.rb +15 -0
  49. data/lib/tasks/db.rake +16 -0
  50. data/rom-cassandra.gemspec +33 -0
  51. data/spec/config/reset_cluster.rb +28 -0
  52. data/spec/config/rom.rb +3 -0
  53. data/spec/config/test_module.rb +7 -0
  54. data/spec/integration/batch_spec.rb +36 -0
  55. data/spec/integration/create_spec.rb +33 -0
  56. data/spec/integration/delete_spec.rb +33 -0
  57. data/spec/integration/migrate/20150825142003_create_users.rb +24 -0
  58. data/spec/integration/migrate/20150825142024_create_logs.rb +17 -0
  59. data/spec/integration/migrate_spec.rb +47 -0
  60. data/spec/integration/relation_spec.rb +27 -0
  61. data/spec/integration/update_spec.rb +33 -0
  62. data/spec/shared/fake_migrate_folder.rb +21 -0
  63. data/spec/shared/users.rb +20 -0
  64. data/spec/spec_helper.rb +17 -0
  65. data/spec/unit/commands/batch_spec.rb +86 -0
  66. data/spec/unit/commands/create_spec.rb +77 -0
  67. data/spec/unit/commands/delete_spec.rb +77 -0
  68. data/spec/unit/commands/update_spec.rb +77 -0
  69. data/spec/unit/dataset_spec.rb +130 -0
  70. data/spec/unit/gateway_spec.rb +140 -0
  71. data/spec/unit/migrations/generator_spec.rb +31 -0
  72. data/spec/unit/migrations/logger_spec.rb +21 -0
  73. data/spec/unit/migrations/migration_spec.rb +59 -0
  74. data/spec/unit/migrations/migrator_spec.rb +120 -0
  75. data/spec/unit/migrations/runner_down_spec.rb +65 -0
  76. data/spec/unit/migrations/runner_spec.rb +142 -0
  77. data/spec/unit/migrations/runner_up_spec.rb +67 -0
  78. data/spec/unit/query_spec.rb +21 -0
  79. data/spec/unit/relation_spec.rb +142 -0
  80. data/spec/unit/session_spec.rb +55 -0
  81. data/spec/unit/tasks/create_migration_spec.rb +41 -0
  82. metadata +242 -0
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+
3
+ module ROM::Cassandra
4
+
5
+ # The dataset describes a table of the Cassandra cluster
6
+ #
7
+ # @api private
8
+ #
9
+ class Dataset
10
+
11
+ include Enumerable
12
+ include Equalizer.new(:session, :keyspace, :table, :query)
13
+
14
+ # @!attribute [r] session
15
+ #
16
+ # @return [ROM::Cassandra::Session] The open session to a Cassandra cluster
17
+ #
18
+ attr_reader :session
19
+
20
+ # @!attribute [r] keyspace
21
+ #
22
+ # @return [Symbol] The name of the current keyspace
23
+ #
24
+ attr_reader :keyspace
25
+
26
+ # @!attribute [r] table
27
+ #
28
+ # @return [Symbol] The name of the current table
29
+ #
30
+ attr_reader :table
31
+
32
+ # @!attribute [r] query
33
+ #
34
+ # @return [QueryBuilder::Statement] The lazy query to the current table
35
+ #
36
+ attr_reader :query
37
+
38
+ # Initializes the dataset for given column family and command options
39
+ #
40
+ # @param [ROM::Cassandra::Session] session
41
+ # @param [#to_sym] keyspace
42
+ # @param [#to_sym] table
43
+ # @param [ROM::Cassandra::Query] query
44
+ #
45
+ # @api private
46
+ #
47
+ def initialize(session, keyspace, table, query = nil)
48
+ @session = session
49
+ @keyspace = keyspace.to_sym if keyspace
50
+ @table = table.to_sym if table
51
+ @query = query || Query.new.keyspace(keyspace).table(table)
52
+ end
53
+
54
+ # Returns the new dataset carriyng the batch query
55
+ #
56
+ # The batch query doesn't restricted by any table or keyspace
57
+ #
58
+ # @return [ROM::Relation::Dataset]
59
+ #
60
+ def batch
61
+ reload nil, nil, Query.new.batch
62
+ end
63
+
64
+ # Returns new dataset with `select` method applied to the [#query]
65
+ #
66
+ # @param [Array, Hash, nil] args
67
+ #
68
+ # @return [ROM::Relation::Dataset]
69
+ #
70
+ def get(*args)
71
+ reload keyspace, table, query.select(*args)
72
+ end
73
+
74
+ # Sends the [#query] to Cassandra and iterates through results
75
+ #
76
+ # @return [Enumerator]
77
+ #
78
+ # @yieldparam [Hash] tuples from the dataset
79
+ # @yieldreturn [self] itself
80
+ #
81
+ def each
82
+ return to_enum unless block_given?
83
+ session.call(query).each { |item| yield(item) }
84
+ end
85
+
86
+ private
87
+
88
+ def reload(*args)
89
+ self.class.new(session, *args)
90
+ end
91
+
92
+ def method_missing(name, *args)
93
+ reload keyspace, table, query.public_send(name, *args)
94
+ end
95
+
96
+ def respond_to_missing?(name, *)
97
+ query.respond_to?(name)
98
+ end
99
+
100
+ end # class Dataset
101
+
102
+ end # module ROM::Cassandra
@@ -0,0 +1,115 @@
1
+ # encoding: utf-8
2
+
3
+ module ROM::Cassandra
4
+
5
+ # The gateway to the keyspace of the Cassandra cluster
6
+ #
7
+ # @api public
8
+ #
9
+ class Gateway < ROM::Gateway
10
+
11
+ include Equalizer.new(:options, :datasets)
12
+
13
+ # @!attribute [r] session
14
+ #
15
+ # @return [ROM::Cassandra::Session] The current session
16
+ #
17
+ attr_reader :session
18
+
19
+ # @!attribute [r] datasets
20
+ #
21
+ # @return [Hash] The list of registered datasets
22
+ #
23
+ attr_reader :datasets
24
+
25
+ # Initializes the ROM gateway to the Cassandra cluster
26
+ #
27
+ # @example
28
+ # ROM::Cassandra::Gateway.new(
29
+ # hosts: ["10.0.1.1", "10.0.1.2"],
30
+ # port: 9042,
31
+ # username: "admin",
32
+ # password: "foo"
33
+ # )
34
+ #
35
+ # @example
36
+ # ROM::Cassandra::Gateway.new(
37
+ # "http://10.0.1.1:9042",
38
+ # username: "admin",
39
+ # password: "foo"
40
+ # )
41
+ #
42
+ # @param [Hash] options
43
+ #
44
+ def initialize(*options)
45
+ @session = Session.new(*options)
46
+ @datasets = {}
47
+ end
48
+
49
+ # The options of the initialized session
50
+ #
51
+ # @return [Hash]
52
+ #
53
+ def options
54
+ session.uri
55
+ end
56
+
57
+ # Registers a new dataset
58
+ #
59
+ # @example
60
+ # dataset "foo.bar"
61
+ #
62
+ # @param [#to_sym] name The full name of the table
63
+ #
64
+ # @return [ROM::Cassandra::Dataset]
65
+ #
66
+ def dataset(name)
67
+ @datasets[name.to_sym] = Dataset.new(session, *split(name))
68
+ end
69
+
70
+ # Returns the registered dataset
71
+ #
72
+ # @param (see #dataset)
73
+ #
74
+ # @return (see #dataset)
75
+ #
76
+ def [](name)
77
+ datasets[name.to_sym]
78
+ end
79
+
80
+ # Checks whether the dataset is registered
81
+ #
82
+ # @param (see #dataset)
83
+ #
84
+ # @return [Boolean]
85
+ #
86
+ def dataset?(name)
87
+ self[name] ? true : false
88
+ end
89
+
90
+ # Migrates the Cassandra cluster to given version
91
+ #
92
+ # @option (see ROM::Cassandra::Migrations::Migrator#new)
93
+ # @option options [Integer, nil] :version
94
+ #
95
+ # @return [undefined]
96
+ #
97
+ def migrate(options = {})
98
+ settings = options.select { |key| [:path, :logger].include? key }
99
+ target = options.select { |key| key.equal? :version }
100
+
101
+ Migrations::Migrator.new(session, settings).apply(target)
102
+ end
103
+
104
+ private
105
+
106
+ def split(name)
107
+ list = name.to_s.split(".")
108
+ return list if 2.equal? list.count
109
+ fail ArgumentError.new "'#{name}' is not a valid full name of a table. " \
110
+ "Use format 'keyspace.table' with both keyspace and table parts."
111
+ end
112
+
113
+ end # class Gateway
114
+
115
+ end # module ROM::Cassandra
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ require "logger"
4
+
5
+ module ROM::Cassandra
6
+
7
+ # Migrations features for the Cassandra cluster
8
+ #
9
+ module Migrations
10
+
11
+ # The procedure that extracts version number from a migration filename
12
+ GET_VERSION = -> name { File.basename(name, ".rb")[/\d{14}/].to_i }
13
+
14
+ # The default path for migrations
15
+ DEFAULT_PATH = "db/migrate".freeze
16
+
17
+ # The biggest possible version for migrations
18
+ ALL_VERSIONS = ("9" * 14).to_i
19
+
20
+ require_relative "migrations/logger"
21
+ require_relative "migrations/migration"
22
+ require_relative "migrations/runner"
23
+ require_relative "migrations/runner_up"
24
+ require_relative "migrations/runner_down"
25
+ require_relative "migrations/migrator"
26
+ require_relative "migrations/generator"
27
+
28
+ end # module Migrations
29
+
30
+ end # module ROM::Cassandra
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+
3
+ module ROM::Cassandra
4
+
5
+ module Migrations
6
+
7
+ # Generates the migration with given name at the target folder
8
+ #
9
+ # @example
10
+ # ROM::Cassandra::Migrations::Generator.call "create_users", "/db/migrate"
11
+ # # => "/db/migrate/20150827133303_create_users.rb"
12
+ #
13
+ class Generator
14
+
15
+ # Initializes and calls the generator at once
16
+ #
17
+ # @param (see #initialize)
18
+ #
19
+ # @return (see #call)
20
+ #
21
+ def self.call(name, path)
22
+ new(name, path).call
23
+ end
24
+
25
+ # Initializes the generator with path to target folder and migration name
26
+ #
27
+ # @param [String] path
28
+ # @param [String] name
29
+ #
30
+ def initialize(name, path)
31
+ @path = path
32
+ @name = Inflecto.underscore(name)
33
+ @klass = Inflecto.camelize(name)
34
+ @version = Time.new.strftime "%Y%m%d%H%M%S"
35
+ end
36
+
37
+ # Generates the migration
38
+ #
39
+ # @return [String] the full path to the migration
40
+ #
41
+ def call
42
+ FileUtils.mkdir_p path
43
+ File.write target, content
44
+
45
+ target
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :name, :path, :version
51
+
52
+ def content
53
+ ERB.new(File.read source).result(binding)
54
+ end
55
+
56
+ def source
57
+ File.expand_path("../generator/migration.erb", __FILE__)
58
+ end
59
+
60
+ def target
61
+ File.join(path, "#{version}_#{name}.rb")
62
+ end
63
+
64
+ end # class Generator
65
+
66
+ end # module Migrations
67
+
68
+ end # module ROM::Cassandra
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ # ==============================================================================
4
+ # Define `up` and `down` methods, using `call` and `timestamp` helpers.
5
+ #
6
+ # @see http://rom-rb.org/guides/adapters/cassandra#migrations
7
+ # the example in the Cassandra Adapter Guide
8
+ # ==============================================================================
9
+
10
+ # Adds/discards changes to the Cassandra cluster and registers the migration
11
+ # at the rom.migrations table of the cluster.
12
+ #
13
+ # @example
14
+ # migration = <%= @klass %>.new(session)
15
+ # migration.up
16
+ # migration.down
17
+ #
18
+ class <%= @klass %> < ROM::Cassandra::Migrations::Migration
19
+ # Adds necessary changes to the Cassandra cluster
20
+ #
21
+ # @return [undefined]
22
+ #
23
+ def up
24
+ end
25
+
26
+ # Rolls back the changes to the Cassandra cluster
27
+ #
28
+ # @return [undefined]
29
+ #
30
+ def down
31
+ end
32
+ end # class ROM::Cassandra::Migrations::Migration
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ require "logger"
4
+
5
+ module ROM::Cassandra
6
+
7
+ module Migrations
8
+
9
+ # Default Logger for the migrator
10
+ #
11
+ # @example
12
+ # logger = Logger.new
13
+ # logger.info "some text"
14
+ # # => some text
15
+ #
16
+ class Logger < ::Logger
17
+
18
+ # @private
19
+ def initialize
20
+ super $stdout
21
+ self.formatter = proc { |_, _, _, message| "#{message}\n" }
22
+ end
23
+
24
+ end # Logger
25
+
26
+ end # module Migrations
27
+
28
+ end # module ROM::Cassandra
@@ -0,0 +1,107 @@
1
+ # encoding: utf-8
2
+
3
+ module ROM::Cassandra
4
+
5
+ module Migrations
6
+
7
+ # Base class for migrations, responcible for sending queries to the session
8
+ #
9
+ # @example Migration can be created in OOP-style
10
+ # class CreateAuthUsers < ROM::Cassandra::Migration
11
+ # def up
12
+ # call keyspace(:auth).create.if_not_exists
13
+ # call keyspace(:auth)
14
+ # .table(:users)
15
+ # .create(:id, :int)
16
+ # .add(:name, :text)
17
+ # .primary_key(:id)
18
+ # .if_not_exists
19
+ # end
20
+ #
21
+ # def down
22
+ # call keyspace(:auth).drop.if_exists
23
+ # end
24
+ # end
25
+ #
26
+ # @example The same migration in CQL style
27
+ # class CreateAuthUsers < ROM::Cassandra::Migration
28
+ # def up
29
+ # call "CREATE KEYSPACE IF NOT EXISTS auth;"
30
+ # call(
31
+ # "CREATE TABLE auth.users (id int, name text, PRIMARY KEY (text));"
32
+ # )
33
+ # end
34
+ #
35
+ # def down
36
+ # call "DROM KEYSPACE IF EXISTS auth;"
37
+ # end
38
+ # end
39
+ #
40
+ class Migration
41
+
42
+ # Makes all helper methods private
43
+ #
44
+ # @private
45
+ #
46
+ def self.inherited(klass)
47
+ klass.__send__(:private, :call, :keyspace, :up, :down)
48
+ end
49
+
50
+ # Initializes migration with session to the Cassandra cluster
51
+ #
52
+ # @param [ROM::Cassandra::Session] session
53
+ #
54
+ def initialize(session)
55
+ @session = session
56
+ @builder = Query.new
57
+ end
58
+
59
+ # @!attribute [r] session
60
+ #
61
+ # @return [ROM::Cassandra::Session] the session to send queries to
62
+ #
63
+ attr_reader :session
64
+
65
+ # By default does nothing
66
+ #
67
+ # @return [undefined]
68
+ #
69
+ # @abstract
70
+ #
71
+ def up
72
+ end
73
+
74
+ # By default does nothing
75
+ #
76
+ # @return [undefined]
77
+ #
78
+ # @abstract
79
+ #
80
+ def down
81
+ end
82
+
83
+ # Sends the query to Cassandra cluster
84
+ #
85
+ # @param [#to_s] query
86
+ #
87
+ # @return [Array]
88
+ #
89
+ def call(query)
90
+ session.call query.to_s
91
+ end
92
+
93
+ # Starts building the CQL query in the context of some keyspace
94
+ #
95
+ # @param [#to_s] name
96
+ #
97
+ # @return [ROM::Cassandra::Query]
98
+ #
99
+ def keyspace(name)
100
+ @builder.keyspace(name)
101
+ end
102
+
103
+ end # class Migration
104
+
105
+ end # module Migrations
106
+
107
+ end # module ROM::Cassandra