whi-cassie 1.1.1 → 1.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 68fe9feda088a468e88c2bc6d49b5b56a48bb590
4
- data.tar.gz: 3ae674573e37aa5720d8d7bf679d17d40f843693
2
+ SHA256:
3
+ metadata.gz: cc03cb8a9fdac75018c3c31a5466a681a7e57f4584c5d3c4540d012da48c8bc9
4
+ data.tar.gz: 7576c9d2d998329cc918cc8c7dad45eda0012d420c123b7cfb9412c82873ab24
5
5
  SHA512:
6
- metadata.gz: 895d127cf90199a9f2b7d9f9d4743bd1c0772d3d1200c675531e55b485a09b9f2c950e49d963653b0ecef1db0678cf95e242b0e7c1154aa29bac147e641ed330
7
- data.tar.gz: 1491b655db43141efe27587f40ffa382cddecc44715ff79628129cc021ad36683ca9fc52c3b01d6ad5eef7df0d5e3c7d5984695f99905e741632a5ae31f17276
6
+ metadata.gz: c60020caa9c11330c2c5713bbd0962cf1682f07f351815b60975b608af50031627a08c27d50e1175ffc02d44da368cc64e71f7a337164cf1dddd75da415e6dc6
7
+ data.tar.gz: 2690d2fb060d226a11d81cba9db78251bce6ca0a744e27ddd1975e82b2db7376bc247c58b6a1af895da0b81a2d21e1e3b6f3eda64234e52a973b3d0ce221743b
@@ -0,0 +1,12 @@
1
+ # Dependabot update strategy
2
+ version: 2
3
+ updates:
4
+ - package-ecosystem: bundler
5
+ directory: "/"
6
+ schedule:
7
+ interval: daily
8
+ allow:
9
+ # Automatically keep all runtime dependencies updated
10
+ - dependency-name: "*"
11
+ dependency-type: "production"
12
+ versioning-strategy: lockfile-only
@@ -0,0 +1,63 @@
1
+ name: Continuous Integration
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+ - actions-*
7
+ tags:
8
+ - v*
9
+ pull_request:
10
+ env:
11
+ BUNDLE_CLEAN: "true"
12
+ BUNDLE_PATH: vendor/bundle
13
+ BUNDLE_JOBS: 3
14
+ BUNDLE_RETRY: 3
15
+ jobs:
16
+ specs:
17
+ name: ${{ matrix.job }} ruby-${{ matrix.ruby }} ${{ matrix.activemodel && format('activemodel-{0}', matrix.activemodel) }} cassandra-${{ matrix.cassandra_version }}
18
+ runs-on: ubuntu-latest
19
+ services:
20
+ cassandra:
21
+ image: cassandra:${{ matrix.cassandra_version }}
22
+ ports:
23
+ - 9042:9042
24
+ strategy:
25
+ fail-fast: false
26
+ matrix:
27
+ ruby: [2.7]
28
+ activemodel: [6]
29
+ job: [rspec]
30
+ cassandra_version: ["4.0"]
31
+ include:
32
+ - ruby: 2.6
33
+ activemodel: 5
34
+ job: rspec
35
+ cassandra_version: "3"
36
+ - ruby: 2.4
37
+ activemodel: 4
38
+ job: rspec
39
+ cassandra_version: "2"
40
+ - ruby: 2.7
41
+ job: standardrb
42
+ cassandra_version: "latest"
43
+ steps:
44
+ - name: checkout
45
+ uses: actions/checkout@v2
46
+ - name: set up Ruby
47
+ uses: ruby/setup-ruby@v1
48
+ with:
49
+ ruby-version: ${{ matrix.ruby }}
50
+ - name: inject activemodel ${{ matrix.activemodel }}
51
+ if: matrix.activemodel != 'original' && matrix.activemodel != null
52
+ run: | # inject a specific version of activemodel into the Gemfile
53
+ bundle update
54
+ bundle exec appraisal generate
55
+ bundle config set gemfile "gemfiles/activemodel_${{ matrix.activemodel }}.gemfile"
56
+ - name: install dependencies
57
+ run: bundle install
58
+ - name: specs
59
+ if: matrix.job == 'rspec'
60
+ run: bundle exec rake spec
61
+ - name: standardrb
62
+ if: matrix.job == 'standardrb'
63
+ run: bundle exec rake standard
data/.gitignore CHANGED
@@ -1,17 +1,6 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
1
  pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
2
  tmp
3
+ rdoc
4
+ *.rbc
5
+ .tm_properties
6
+ .DS_Store
@@ -0,0 +1,11 @@
1
+ # I really just have issues with the automatic "semantic blocks"
2
+
3
+ ruby_version: 2.4
4
+
5
+ format: progress
6
+
7
+ ignore:
8
+ - '**/*':
9
+ - Standard/SemanticBlocks
10
+ - 'spec/**/*':
11
+ - Lint/UselessAssignment
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ appraise "activemodel-6" do
4
+ gem "activemodel", "~> 6.0"
5
+ end
6
+
7
+ appraise "activemodel-5" do
8
+ gem "activemodel", "~> 5.0"
9
+ end
10
+
11
+ appraise "activemodel-4" do
12
+ gem "activemodel", "~> 4.0"
13
+ end
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem "rake"
7
+ gem "rspec"
8
+ gem "appraisal"
9
+ gem "standard", "~>0.8.1"
10
+ end
@@ -0,0 +1,89 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ whi-cassie (1.2.0)
5
+ activemodel (>= 4.0)
6
+ cassandra-driver (~> 3.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activemodel (6.0.3.4)
12
+ activesupport (= 6.0.3.4)
13
+ activesupport (6.0.3.4)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 0.7, < 2)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
18
+ zeitwerk (~> 2.2, >= 2.2.2)
19
+ appraisal (2.3.0)
20
+ bundler
21
+ rake
22
+ thor (>= 0.14.0)
23
+ ast (2.4.1)
24
+ cassandra-driver (3.2.5)
25
+ ione (~> 1.2)
26
+ concurrent-ruby (1.1.7)
27
+ diff-lcs (1.4.4)
28
+ i18n (1.8.5)
29
+ concurrent-ruby (~> 1.0)
30
+ ione (1.2.4)
31
+ minitest (5.14.2)
32
+ parallel (1.19.2)
33
+ parser (2.7.2.0)
34
+ ast (~> 2.4.1)
35
+ rainbow (3.0.0)
36
+ rake (13.0.1)
37
+ regexp_parser (1.8.2)
38
+ rexml (3.2.4)
39
+ rspec (3.9.0)
40
+ rspec-core (~> 3.9.0)
41
+ rspec-expectations (~> 3.9.0)
42
+ rspec-mocks (~> 3.9.0)
43
+ rspec-core (3.9.3)
44
+ rspec-support (~> 3.9.3)
45
+ rspec-expectations (3.9.3)
46
+ diff-lcs (>= 1.2.0, < 2.0)
47
+ rspec-support (~> 3.9.0)
48
+ rspec-mocks (3.9.1)
49
+ diff-lcs (>= 1.2.0, < 2.0)
50
+ rspec-support (~> 3.9.0)
51
+ rspec-support (3.9.4)
52
+ rubocop (1.0.0)
53
+ parallel (~> 1.10)
54
+ parser (>= 2.7.1.5)
55
+ rainbow (>= 2.2.2, < 4.0)
56
+ regexp_parser (>= 1.8)
57
+ rexml
58
+ rubocop-ast (>= 0.6.0)
59
+ ruby-progressbar (~> 1.7)
60
+ unicode-display_width (>= 1.4.0, < 2.0)
61
+ rubocop-ast (1.1.0)
62
+ parser (>= 2.7.1.5)
63
+ rubocop-performance (1.8.1)
64
+ rubocop (>= 0.87.0)
65
+ rubocop-ast (>= 0.4.0)
66
+ ruby-progressbar (1.10.1)
67
+ standard (0.8.1)
68
+ rubocop (= 1.0.0)
69
+ rubocop-performance (= 1.8.1)
70
+ thor (1.0.1)
71
+ thread_safe (0.3.6)
72
+ tzinfo (1.2.7)
73
+ thread_safe (~> 0.1)
74
+ unicode-display_width (1.7.0)
75
+ zeitwerk (2.4.0)
76
+
77
+ PLATFORMS
78
+ ruby
79
+
80
+ DEPENDENCIES
81
+ appraisal
82
+ bundler (~> 2.0)
83
+ rake
84
+ rspec
85
+ standard (~> 0.8.1)
86
+ whi-cassie!
87
+
88
+ BUNDLED WITH
89
+ 2.1.4
data/HISTORY.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 1.2.0
2
+
3
+ * Update schema queries to support Cassandra 3.x+
4
+ * Require Ruby 2.4 or greater
5
+
1
6
  ## 1.1.1
2
7
  * Update dependencies to support Rails 5.
3
8
 
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ ![Continuous Integration](https://github.com/weheartit/cassie/workflows/Continuous%20Integration/badge.svg)
2
+ [![Maintainability](https://api.codeclimate.com/v1/badges/129ede20094ea298c687/maintainability)](https://codeclimate.com/github/weheartit/cassie/maintainability)
3
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
4
+
1
5
  # Cassie
2
6
 
3
7
  The short and sweet Cassandra object mapper from [We Heart It](http://weheartit.com/)
@@ -8,34 +12,34 @@ The short and sweet Cassandra object mapper from [We Heart It](http://weheartit.
8
12
  class Thing
9
13
  # Your model must include this
10
14
  include Cassie::Model
11
-
15
+
12
16
  # Set the table name where the data lives.
13
17
  self.table_name = "things"
14
-
18
+
15
19
  # Set the keyspace where the table lives. Keyspaces can be defined abstractly and mapped
16
20
  # and mapped in a configuration file. This can allow you to have different keyspace names
17
21
  # between different environments and still use the same code.
18
22
  self.keyspace = "default"
19
-
23
+
20
24
  # You must defind the primary key. They columns must be listed in the order that they apper
21
25
  # in the Cassandra CQL PRIMARY KEY clause defining the table.
22
26
  self.primary_key = [:owner, :id]
23
-
27
+
24
28
  # All columns are explicitly defined with their name and data type and an optional
25
29
  # alias name.
26
30
  column :owner, :int
27
31
  column :id, :int, :as => :identifier
28
32
  column :val, :varchar, :as => :value
29
-
33
+
30
34
  # The ordering keys should also be defined along with how they are ordered.
31
35
  ordering_key :id, :desc
32
-
36
+
33
37
  # You can use all the standard ActiveModel validations.
34
38
  validates_presence_of :owner, :id
35
-
39
+
36
40
  # You also get before and after callbacks for create, update, save, and destroy.
37
41
  before_save :some_callback_method
38
-
42
+
39
43
  ...
40
44
  end
41
45
 
@@ -176,13 +180,13 @@ To use it with rspec you should add this code to your spec_helper.rb file:
176
180
  end
177
181
  Cassie::Testing.prepare!
178
182
  end
179
-
183
+
180
184
  config.after(:suite) do
181
185
  Cassie::Schema.all do |keyspace|
182
186
  Cassie::Schema.drop!(keyspace)
183
187
  end
184
188
  end
185
-
189
+
186
190
  config.around(:each) do |example|
187
191
  Cassie::Testing.cleanup! do
188
192
  example.run
data/Rakefile CHANGED
@@ -1,18 +1,19 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "standard/rake"
2
4
 
3
- desc 'Default: run unit tests.'
4
- task :default => :test
5
+ RSpec::Core::RakeTask.new(:spec)
5
6
 
6
- desc 'RVM likes to call it tests'
7
- task :tests => :test
7
+ task default: :spec
8
8
 
9
- begin
10
- require 'rspec'
11
- require 'rspec/core/rake_task'
12
- desc 'Run the unit tests'
13
- RSpec::Core::RakeTask.new(:test)
14
- rescue LoadError
15
- task :test do
16
- STDERR.puts "You must have rspec 2.0 installed to run the tests"
9
+ desc "run the specs using appraisal"
10
+ task :appraisals do
11
+ exec "bundle exec appraisal rake spec"
12
+ end
13
+
14
+ namespace :appraisals do
15
+ desc "install all the appraisal gemspecs"
16
+ task :install do
17
+ exec "bundle exec appraisal install"
17
18
  end
18
19
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.1
1
+ 1.2.0
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activemodel", "~> 4.0"
6
+
7
+ group :development, :test do
8
+ gem "rake"
9
+ gem "rspec"
10
+ gem "appraisal"
11
+ gem "standard", "~>0.8.1"
12
+ end
13
+
14
+ gemspec path: "../"
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activemodel", "~> 5.0"
6
+
7
+ group :development, :test do
8
+ gem "rake"
9
+ gem "rspec"
10
+ gem "appraisal"
11
+ gem "standard", "~>0.8.1"
12
+ end
13
+
14
+ gemspec path: "../"
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activemodel", "~> 6.0"
6
+
7
+ group :development, :test do
8
+ gem "rake"
9
+ gem "rspec"
10
+ gem "appraisal"
11
+ gem "standard", "~>0.8.1"
12
+ end
13
+
14
+ gemspec path: "../"
@@ -1,4 +1,6 @@
1
- require 'cassandra'
1
+ # frozen_string_literal: true
2
+
3
+ require "cassandra"
2
4
 
3
5
  # This class provides a lightweight wrapper around the Cassandra driver. It provides
4
6
  # a foundation for maintaining a connection and constructing CQL statements.
@@ -9,35 +11,35 @@ class Cassie
9
11
  require File.expand_path("../cassie/schema.rb", __FILE__)
10
12
  require File.expand_path("../cassie/testing.rb", __FILE__)
11
13
  require File.expand_path("../cassie/railtie.rb", __FILE__) if defined?(Rails)
12
-
14
+
13
15
  class RecordNotFound < StandardError
14
16
  end
15
-
17
+
16
18
  class RecordInvalid < StandardError
17
19
  attr_reader :record
18
-
20
+
19
21
  def initialize(record)
20
22
  super("Errors on #{record.class.name}: #{record.errors.to_hash.inspect}")
21
23
  @record = record
22
24
  end
23
25
  end
24
-
26
+
25
27
  # Message passed to subscribers with the statement, options, and time for each statement
26
28
  # to execute. Note that if statements are batched they will be packed into one message
27
29
  # with a Cassandra::Statements::Batch statement and empty options.
28
30
  class Message
29
31
  attr_reader :statement, :options, :elapsed_time
30
-
32
+
31
33
  def initialize(statement, options, elapsed_time)
32
34
  @statement = statement
33
35
  @options = options
34
36
  @elapsed_time = elapsed_time
35
37
  end
36
38
  end
37
-
39
+
38
40
  attr_reader :config, :subscribers
39
41
  attr_accessor :consistency
40
-
42
+
41
43
  class << self
42
44
  # A singleton instance that can be shared to communicate with a Cassandra cluster.
43
45
  def instance
@@ -47,7 +49,7 @@ class Cassie
47
49
  end
48
50
  @instance
49
51
  end
50
-
52
+
51
53
  # Call this method to load the Cassie::Config from the specified file for the
52
54
  # specified environment.
53
55
  def configure!(options)
@@ -58,7 +60,7 @@ class Cassie
58
60
  end
59
61
  @config = Cassie::Config.new(options)
60
62
  end
61
-
63
+
62
64
  # This method can be used to set a consistency level for all Cassandra queries
63
65
  # within a block that don't explicitly define them. It can be used where consistency
64
66
  # is important (i.e. on validation queries) but where a higher level method
@@ -72,18 +74,16 @@ class Cassie
72
74
  Thread.current[:cassie_consistency] = save_val
73
75
  end
74
76
  end
75
-
77
+
76
78
  # Get a Logger compatible object if it has been set.
77
79
  def logger
78
80
  @logger if defined?(@logger)
79
81
  end
80
-
82
+
81
83
  # Set a logger with a Logger compatible object.
82
- def logger=(value)
83
- @logger = value
84
- end
84
+ attr_writer :logger
85
85
  end
86
-
86
+
87
87
  def initialize(config)
88
88
  @config = config
89
89
  @monitor = Monitor.new
@@ -93,14 +93,14 @@ class Cassie
93
93
  @subscribers = Subscribers.new
94
94
  @consistency = ((config.cluster || {})[:consistency] || :local_one)
95
95
  end
96
-
96
+
97
97
  # Open a connection to the Cassandra cluster.
98
98
  def connect
99
99
  start_time = Time.now
100
100
  cluster_config = config.cluster
101
- cluster_config = cluster_config.merge(:logger => logger) if logger
101
+ cluster_config = cluster_config.merge(logger: logger) if logger
102
102
  cluster = Cassandra.cluster(cluster_config)
103
- logger.info("Cassie.connect with #{config.sanitized_cluster} in #{((Time.now - start_time) * 1000).round}ms") if logger
103
+ logger&.info("Cassie.connect with #{config.sanitized_cluster} in #{((Time.now - start_time) * 1000).round}ms")
104
104
  @monitor.synchronize do
105
105
  @session = cluster.connect(config.default_keyspace)
106
106
  @prepared_statements = {}
@@ -109,19 +109,19 @@ class Cassie
109
109
 
110
110
  # Close the connections to the Cassandra cluster.
111
111
  def disconnect
112
- logger.info("Cassie.disconnect from #{config.sanitized_cluster}") if logger
112
+ logger&.info("Cassie.disconnect from #{config.sanitized_cluster}")
113
113
  @monitor.synchronize do
114
- @session.close if @session
114
+ @session&.close
115
115
  @session = nil
116
116
  @prepared_statements = {}
117
117
  end
118
118
  end
119
-
119
+
120
120
  # Return true if the connection to the Cassandra cluster has been established.
121
121
  def connected?
122
122
  !!@session
123
123
  end
124
-
124
+
125
125
  # Force reconnection. If you're using this code in conjunction in a forking server environment
126
126
  # like passenger or unicorn you should call this method after forking.
127
127
  def reconnect
@@ -150,13 +150,13 @@ class Cassie
150
150
  end
151
151
  end
152
152
  end
153
-
153
+
154
154
  if cache_filled_up && logger && Time.now > @last_prepare_warning + 10
155
155
  # Set a throttle on how often this message is logged so we don't kill performance enven more.
156
156
  @last_prepare_warning = Time.now
157
157
  logger.warn("Cassie.prepare cache filled up. Consider increasing the size from #{config.max_prepared_statements}.")
158
158
  end
159
-
159
+
160
160
  statement
161
161
  end
162
162
 
@@ -210,22 +210,22 @@ class Cassie
210
210
  columns = []
211
211
  values = []
212
212
  values_hash.each do |column, value|
213
- if !value.nil?
213
+ unless value.nil?
214
214
  columns << column
215
215
  values << value
216
216
  end
217
217
  end
218
- cql = "INSERT INTO #{table} (#{columns.join(', ')}) VALUES (#{question_marks(columns.size)})"
219
-
220
- if options && options.include?(:ttl)
218
+ cql = "INSERT INTO #{table} (#{columns.join(", ")}) VALUES (#{question_marks(columns.size)})"
219
+
220
+ if options&.include?(:ttl)
221
221
  options = options.dup
222
222
  ttl = options.delete(:ttl)
223
223
  if ttl
224
- cql << " USING TTL ?"
224
+ cql += " USING TTL ?"
225
225
  values << Integer(ttl)
226
226
  end
227
227
  end
228
-
228
+
229
229
  batch_or_execute(cql, values, options)
230
230
  end
231
231
 
@@ -248,20 +248,20 @@ class Cassie
248
248
  end
249
249
  end
250
250
  values = update_values + key_values
251
-
251
+
252
252
  cql = "UPDATE #{table}"
253
-
254
- if options && options.include?(:ttl)
253
+
254
+ if options&.include?(:ttl)
255
255
  options = options.dup
256
256
  ttl = options.delete(:ttl)
257
257
  if ttl
258
- cql << " USING TTL ?"
258
+ cql += " USING TTL ?"
259
259
  values.unshift(Integer(ttl))
260
260
  end
261
261
  end
262
262
 
263
- cql << " SET #{update_cql.join(', ')} WHERE #{key_cql}"
264
-
263
+ cql += " SET #{update_cql.join(", ")} WHERE #{key_cql}"
264
+
265
265
  batch_or_execute(cql, values, options)
266
266
  end
267
267
 
@@ -281,31 +281,31 @@ class Cassie
281
281
  start_time = Time.now
282
282
  begin
283
283
  statement = nil
284
- if cql.is_a?(String)
284
+ statement = if cql.is_a?(String)
285
285
  if values.present?
286
- statement = prepare(cql)
286
+ prepare(cql)
287
287
  else
288
- statement = Cassandra::Statements::Simple.new(cql)
288
+ Cassandra::Statements::Simple.new(cql)
289
289
  end
290
290
  else
291
- statement = cql
291
+ cql
292
292
  end
293
-
293
+
294
294
  if values.present?
295
295
  values = Array(values)
296
- options = (options ? options.merge(:arguments => values) : {:arguments => values})
296
+ options = (options ? options.merge(arguments: values) : {arguments: values})
297
297
  end
298
-
298
+
299
299
  # Set a default consistency from a block context if it isn't explicitly set.
300
300
  statement_consistency = current_consistency
301
301
  if statement_consistency
302
302
  if options
303
- options = options.merge(:consistency => statement_consistency) if options[:consistency].nil?
303
+ options = options.merge(consistency: statement_consistency) if options[:consistency].nil?
304
304
  else
305
- options = {:consistency => statement_consistency}
305
+ options = {consistency: statement_consistency}
306
306
  end
307
307
  end
308
-
308
+
309
309
  session.execute(statement, options || {})
310
310
  rescue Cassandra::Errors::IOError => e
311
311
  disconnect
@@ -313,18 +313,18 @@ class Cassie
313
313
  ensure
314
314
  if statement.is_a?(Cassandra::Statement) && !subscribers.empty?
315
315
  payload = Message.new(statement, options, Time.now - start_time)
316
- subscribers.each{|subscriber| subscriber.call(payload)}
316
+ subscribers.each { |subscriber| subscriber.call(payload) }
317
317
  end
318
318
  end
319
319
  end
320
-
320
+
321
321
  # Return the current consistency level that has been set for statements.
322
322
  def current_consistency
323
323
  Thread.current[:cassie_consistency] || consistency
324
324
  end
325
325
 
326
326
  private
327
-
327
+
328
328
  def logger
329
329
  self.class.logger
330
330
  end
@@ -333,7 +333,7 @@ class Cassie
333
333
  connect unless connected?
334
334
  @session
335
335
  end
336
-
336
+
337
337
  def batch_or_execute(cql, values, options = nil)
338
338
  batch = Thread.current[:cassie_batch]
339
339
  if batch
@@ -345,9 +345,7 @@ class Cassie
345
345
  end
346
346
 
347
347
  def question_marks(size)
348
- q = '?'
349
- (size - 1).times{ q << ',?' }
350
- q
348
+ "?#{",?" * (size - 1)}"
351
349
  end
352
350
 
353
351
  def key_clause(key_hash)
@@ -357,9 +355,9 @@ class Cassie
357
355
  cql << "#{key} = ?"
358
356
  values << value
359
357
  end
360
- [cql.join(' AND '), values]
358
+ [cql.join(" AND "), values]
361
359
  end
362
-
360
+
363
361
  # Extract the CQL from a statement
364
362
  def statement_cql(statement, previous = nil)
365
363
  cql = nil
@@ -368,7 +366,7 @@ class Cassie
368
366
  elsif statement.respond_to?(:statements) && (previous.nil? || !previous.include?(statement))
369
367
  previous ||= []
370
368
  previous << statement
371
- cql = statement.statements.collect{|s| statement_cql(s, previous)}.join('; ')
369
+ cql = statement.statements.collect { |s| statement_cql(s, previous) }.join("; ")
372
370
  end
373
371
  cql
374
372
  end