datastax_rails 1.0.16.3 → 1.0.17.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.
@@ -44,11 +44,11 @@ module DatastaxRails
44
44
  model.attribute_definitions.values.each do |attr|
45
45
  coder = attr.coder
46
46
  if coder.options[:solr_type] && (coder.options[:indexed] || coder.options[:stored])
47
- @fields.push({ :name => attr.name,
48
- :type => coder.options[:solr_type].to_s,
49
- :indexed => coder.options[:indexed].to_s,
50
- :stored => coder.options[:stored].to_s,
51
- :multi_valued => coder.options[:multi_valued].to_s })
47
+ @fields.push({ :name => attr.name,
48
+ :type => coder.options[:solr_type].to_s,
49
+ :indexed => coder.options[:indexed].to_s,
50
+ :stored => coder.options[:stored].to_s,
51
+ :multi_valued => coder.options[:multi_valued].to_s })
52
52
  end
53
53
  if coder.options[:sortable] && coder.options[:tokenized]
54
54
  @fields.push({ :name => "sort_" + attr.name,
@@ -76,7 +76,7 @@ module DatastaxRails
76
76
  column_family ||= :all
77
77
  # Ensure schema migrations CF exists
78
78
  unless connection.schema.column_families['schema_migrations']
79
- connection.execute_cql_query(DatastaxRails::Cql::CreateColumnFamily.new('schema_migrations').key_type(:text).to_cql)
79
+ connection.execute_cql_query(DatastaxRails::Cql::CreateColumnFamily.new('schema_migrations').key_type(:text).columns(:digest => :text, :solrconfig => :text, :stopwords => :text).to_cql)
80
80
  end
81
81
 
82
82
  solrconfig = File.read(File.join(File.dirname(__FILE__),"..","..","..","config","solrconfig.xml"))
@@ -100,61 +100,89 @@ module DatastaxRails
100
100
  puts "models: #{models_to_upload.collect(&:to_s).join(",")}"
101
101
 
102
102
  models_to_upload.each do |model|
103
- schema = generate_solr_schema(model)
104
- schema_digest = Digest::SHA1.hexdigest(schema)
105
-
106
- results = DatastaxRails::Cql::Select.new(SchemaMigration, ['*']).conditions(:key => model.column_family).execute
107
- sm_digests = CassandraCQL::Result.new(results).fetch.to_hash
108
-
109
- solr_url = "#{DatastaxRails::Base.solr_base_url}/resource/#{DatastaxRails::Base.config[:keyspace]}.#{model.column_family}"
110
- uri = URI.parse(solr_url)
111
- http = Net::HTTP.new(uri.host, uri.port)
112
- if uri.scheme == 'https'
113
- http.use_ssl = true
114
- http.cert = OpenSSL::X509::Certificate.new(Rails.root.join("config","pow.crt").read)
115
- http.key = OpenSSL::PKey::RSA.new(Rails.root.join("config","pow.key").read)
116
- http.ca_path = Rails.root.join("config","sade_ca.crt").to_s
117
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
118
- end
119
- http.read_timeout = 300
120
- if force || solrconfig_digest != sm_digests['solrconfig']
121
- loop do
122
- puts "Posting Solr Config file to '#{solr_url}/solrconfig.xml'"
123
- http.post(uri.path+"/solrconfig.xml", solrconfig)
124
- if Rails.env.production?
125
- sleep(5)
126
- resp = http.get(uri.path+"/solrconfig.xml")
127
- continue unless resp.message == 'OK'
103
+ if model.payload_model?
104
+ next if model == DatastaxRails::PayloadModel
105
+ unless connection.schema.column_families[model.column_family.to_s]
106
+ puts "Creating payload model #{model.column_family}"
107
+ columns = {:chunk => :int, :payload => :text}
108
+ cql = DatastaxRails::Cql::CreateColumnFamily.new(model.column_family).key_name(:digest).key_columns("digest\", \"chunk").key_type(:text).columns(columns).with("COMPACT STORAGE").to_cql
109
+ puts cql
110
+ connection.execute_cql_query(cql)
111
+ end
112
+ else
113
+ unless connection.schema.column_families[model.column_family.to_s]
114
+ puts "Creating normal model #{model.column_family}"
115
+ cql = DatastaxRails::Cql::CreateColumnFamily.new(model.column_family).key_type(:text).columns(:updated_at => :text, :created_at => :text).to_cql
116
+ puts cql
117
+ connection.execute_cql_query(cql)
118
+ end
119
+ schema = generate_solr_schema(model)
120
+ schema_digest = Digest::SHA1.hexdigest(schema)
121
+
122
+ results = DatastaxRails::Cql::Select.new(SchemaMigration, ['*']).conditions(:KEY => model.column_family).execute
123
+ sm_digests = CassandraCQL::Result.new(results).fetch.try(:to_hash) || {}
124
+
125
+ solr_url = "#{DatastaxRails::Base.solr_base_url}/resource/#{DatastaxRails::Base.config[:keyspace]}.#{model.column_family}"
126
+ uri = URI.parse(solr_url)
127
+ http = Net::HTTP.new(uri.host, uri.port)
128
+ if uri.scheme == 'https'
129
+ http.use_ssl = true
130
+ http.cert = OpenSSL::X509::Certificate.new(Rails.root.join("config","datastax_rails.crt").read)
131
+ http.key = OpenSSL::PKey::RSA.new(Rails.root.join("config","datastax_rails.key").read)
132
+ http.ca_path = Rails.root.join("config","sade_ca.crt").to_s
133
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
134
+ end
135
+ http.read_timeout = 300
136
+ if force || solrconfig_digest != sm_digests['solrconfig']
137
+ loop do
138
+ puts "Posting Solr Config file to '#{solr_url}/solrconfig.xml'"
139
+ http.post(uri.path+"/solrconfig.xml", solrconfig)
140
+ if Rails.env.production?
141
+ sleep(5)
142
+ resp = http.get(uri.path+"/solrconfig.xml")
143
+ continue unless resp.message == 'OK'
144
+ end
145
+ break
128
146
  end
129
- break
147
+ DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:solrconfig => solrconfig_digest).execute
130
148
  end
131
- DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:solrconfig => solrconfig_digest).execute
132
- end
133
- if force || stopwords_digest != sm_digests['stopwords']
134
- loop do
135
- puts "Posting Solr Stopwords file to '#{solr_url}/stopwords.txt'"
136
- http.post(uri.path+"/stopwords.txt", stopwords)
137
- if Rails.env.production?
138
- sleep(5)
139
- resp = http.get(uri.path+"/stopwords.txt")
140
- continue unless resp.message == 'OK'
149
+ if force || stopwords_digest != sm_digests['stopwords']
150
+ loop do
151
+ puts "Posting Solr Stopwords file to '#{solr_url}/stopwords.txt'"
152
+ http.post(uri.path+"/stopwords.txt", stopwords)
153
+ if Rails.env.production?
154
+ sleep(5)
155
+ resp = http.get(uri.path+"/stopwords.txt")
156
+ continue unless resp.message == 'OK'
157
+ end
158
+ break
141
159
  end
142
- break
160
+ DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:stopwords => stopwords_digest).execute
143
161
  end
144
- DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:stopwords => stopwords_digest).execute
145
- end
146
- if force || schema_digest != sm_digests['digest']
147
- loop do
148
- puts "Posting Solr Schema file to '#{solr_url}/schema.xml'"
149
- http.post(uri.path+"/schema.xml", schema)
150
- if Rails.env.production?
151
- sleep(5)
152
- resp = http.get(uri.path+"/schema.xml")
153
- continue unless resp.message == 'OK'
162
+ if force || schema_digest != sm_digests['digest']
163
+ loop do
164
+ puts "Posting Solr Schema file to '#{solr_url}/schema.xml'"
165
+ http.post(uri.path+"/schema.xml", schema)
166
+ if Rails.env.production?
167
+ sleep(5)
168
+ resp = http.get(uri.path+"/schema.xml")
169
+ continue unless resp.message == 'OK'
170
+ end
171
+ break
172
+ end
173
+ DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:digest => schema_digest).execute
174
+ end
175
+
176
+ # Check for unindexed columns
177
+ model.attribute_definitions.each do |attribute, definition|
178
+ if !connection.schema.column_families[model.column_family.to_s].columns.has_key?(attribute.to_s)# &&
179
+ #!definition.coder.options[:stored] &&
180
+ #!definition.coder.options[:indexed]
181
+
182
+ puts "Adding column '#{attribute}' to '#{model.column_family}'"
183
+ DatastaxRails::Cql::AlterColumnFamily.new(model.column_family).add(attribute => :text).execute
154
184
  end
155
- break
156
185
  end
157
- DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:digest => schema_digest).execute
158
186
  end
159
187
  end
160
188
  end
@@ -7,12 +7,18 @@ module DatastaxRails
7
7
  # attribute :updated_at, :type => :time#_with_zone
8
8
 
9
9
  before_create do #|r|
10
- self.created_at ||= Time.current
11
- self.updated_at ||= Time.current
10
+ if self.respond_to?(:created_at=)
11
+ self.created_at ||= Time.current
12
+ end
13
+ if self.respond_to?(:updated_at=)
14
+ self.updated_at ||= Time.current
15
+ end
12
16
  end
13
17
 
14
18
  before_update :if => :changed? do #|r|
15
- self.updated_at = Time.current
19
+ if self.respond_to?(:updated_at=)
20
+ self.updated_at = Time.current
21
+ end
16
22
  end
17
23
  end
18
24
  end
@@ -7,7 +7,7 @@ module DatastaxRails
7
7
  #
8
8
  # That would give you all the posts that have Technology somewhere in the tags array.
9
9
  class ArrayType < BaseType
10
- DEFAULTS = {:solr_type => 'array', :indexed => true, :stored => true, :multi_valued => false, :sortable => false, :tokenized => true, :fulltext => false}
10
+ DEFAULTS = {:solr_type => 'array', :indexed => true, :stored => true, :multi_valued => false, :sortable => false, :tokenized => true, :fulltext => true}
11
11
 
12
12
  # An extension to normal arrays that allow for tracking of dirty values. This is
13
13
  # used by ActiveModel's change tracking framework.
@@ -4,27 +4,11 @@ module DatastaxRails
4
4
  DEFAULTS = {:solr_type => false, :indexed => false, :stored => false, :multi_valued => false, :sortable => false, :tokenized => false, :fulltext => false}
5
5
  def encode(str)
6
6
  raise ArgumentError.new("#{self} requires a String") unless str.kind_of?(String)
7
- io = StringIO.new(Base64.encode64(str))
8
- #io = StringIO.new(str)
9
- chunks = []
10
- while chunk = io.read(1.megabyte)
11
- chunks << chunk
12
- end
13
- chunks
7
+ Base64.encode64(str)
14
8
  end
15
9
 
16
- def decode(arr)
17
- if(arr.is_a?(Array))
18
- io = StringIO.new("","w+")
19
- arr.each do |chunk|
20
- io.write(chunk)
21
- end
22
- io.rewind
23
- Base64.decode64(io.read)
24
- #io.read
25
- else
26
- arr
27
- end
10
+ def decode(str)
11
+ Base64.decode64(str)
28
12
  end
29
13
 
30
14
  def wrap(record, name, value)
@@ -1,4 +1,4 @@
1
1
  module DatastaxRails
2
2
  # The current version of the gem
3
- VERSION = "1.0.16.3"
3
+ VERSION = "1.0.17.1"
4
4
  end
@@ -18,6 +18,7 @@ module DatastaxRails
18
18
  autoload :GroupedCollection
19
19
  autoload :Identity
20
20
  autoload :Migrations
21
+ autoload :PayloadModel
21
22
  autoload :Persistence
22
23
  autoload :Reflection
23
24
  autoload :Relation
@@ -77,7 +78,12 @@ require "thrift"
77
78
  module Thrift
78
79
  class BinaryProtocol
79
80
  def write_string(str)
80
- write_i32(str.bytesize)
81
+ if(str.respond_to?(:bytesize))
82
+ size = str.bytesize
83
+ else
84
+ size = str.size
85
+ end
86
+ write_i32(size)
81
87
  trans.write(str)
82
88
  end
83
89
  end
@@ -14,8 +14,6 @@ describe DatastaxRails::Base do
14
14
  end
15
15
 
16
16
  it "should raise RecordNotFound when finding a bogus ID" do
17
- pending "Datastax Enterprise 2.2 should fix this" do
18
- lambda { Person.find("xyzzy") }.should raise_exception(DatastaxRails::RecordNotFound)
19
- end
17
+ lambda { Person.find("xyzzy") }.should raise_exception(DatastaxRails::RecordNotFound)
20
18
  end
21
19
  end
@@ -7,8 +7,8 @@ describe DatastaxRails::Cql::Select do
7
7
 
8
8
  it "should generate valid CQL" do
9
9
  cql = DatastaxRails::Cql::Select.new(@model_class, ["*"])
10
- cql.using(DatastaxRails::Cql::Consistency::QUORUM).conditions(:key => '12345').limit(1)
11
- cql.to_cql.should == "SELECT * FROM users USING CONSISTENCY QUORUM WHERE key = '12345' LIMIT 1"
10
+ cql.using(DatastaxRails::Cql::Consistency::QUORUM).conditions(:KEY => '12345').limit(1)
11
+ cql.to_cql.should == "SELECT * FROM users USING CONSISTENCY QUORUM WHERE \"KEY\" = '12345' LIMIT 1 "
12
12
  end
13
13
 
14
14
  it_has_behavior "default_consistency"
@@ -8,7 +8,7 @@ describe DatastaxRails::Cql::Update do
8
8
  it "should generate valid CQL" do
9
9
  cql = DatastaxRails::Cql::Update.new(@model_class, "12345")
10
10
  cql.using(DatastaxRails::Cql::Consistency::QUORUM).columns(:name => 'John', :age => '23')
11
- cql.to_cql.should match(/update users using consistency QUORUM SET (name = 'John', age = '23'|age = '23', name = 'John') WHERE KEY IN \('12345'\)/)
11
+ cql.to_cql.should match(/update users using consistency QUORUM SET ("name" = 'John', "age" = '23'|"age" = '23', "name" = 'John') WHERE "KEY" IN \('12345'\)/)
12
12
  end
13
13
 
14
14
  it_has_behavior "default_consistency"
@@ -4,7 +4,6 @@ describe "DatastaxRails::Base" do
4
4
  describe "persistence" do
5
5
  describe "#create" do
6
6
  it "should persist at the given consistency level" do
7
- DatastaxRails::Base.connection.stub(:execute_cql_query)
8
7
  DatastaxRails::Base.connection.should_receive(:execute_cql_query).with(/USING CONSISTENCY LOCAL_QUORUM/i).and_return(true)
9
8
  Person.create({:name => 'Steven'},{:consistency => 'LOCAL_QUORUM'})
10
9
  end
@@ -12,7 +11,6 @@ describe "DatastaxRails::Base" do
12
11
 
13
12
  describe "#save" do
14
13
  it "should persist at the given consistency level" do
15
- DatastaxRails::Base.connection.stub(:execute_cql_query)
16
14
  DatastaxRails::Base.connection.should_receive(:execute_cql_query).with(/USING CONSISTENCY LOCAL_QUORUM/i).and_return(true)
17
15
  p=Person.new(:name => 'Steven')
18
16
  p.save(:consistency => 'LOCAL_QUORUM')
@@ -22,10 +20,32 @@ describe "DatastaxRails::Base" do
22
20
  describe "#remove" do
23
21
  it "should remove at the given consistency level" do
24
22
  p=Person.create(:name => 'Steven')
25
- DatastaxRails::Base.connection.stub(:execute_cql_query)
26
23
  DatastaxRails::Base.connection.should_receive(:execute_cql_query).with(/USING CONSISTENCY LOCAL_QUORUM/i).and_return(true)
27
24
  p.destroy(:consistency => :local_quorum)
28
25
  end
29
26
  end
27
+
28
+ describe "#store_file" do
29
+ it "should store a file" do
30
+ file = "abcd"*1.megabyte
31
+ CarPayload.create(:digest => 'limo', :payload => file)
32
+ CarPayload.find('limo').payload.should == file
33
+ end
34
+
35
+ it "should store really large files" do
36
+ file = IO.read("/dev/urandom", 25.megabyte)
37
+ CarPayload.create(:digest => 'limo', :payload => file)
38
+ CarPayload.find('limo').payload.should == file
39
+ end
40
+
41
+ it "should successfully overwrite a larger file with a smaller one" do
42
+ file = "abcd"*1.megabyte
43
+ car = CarPayload.create(:digest => 'limo', :payload => file)
44
+ smallfile = "e"*1.kilobyte
45
+ car.payload = smallfile
46
+ car.save
47
+ CarPayload.find('limo').payload.should == smallfile
48
+ end
49
+ end
30
50
  end
31
51
  end
@@ -6,12 +6,8 @@ development:
6
6
  connection_options:
7
7
  timeout: 10
8
8
  solr:
9
- port: 8984
9
+ port: 8983
10
10
  path: /solr
11
- ssl:
12
- use_ssl: true
13
- cert: config/datastax_rails.crt
14
- key: config/datastax_rails.key
15
11
 
16
12
  test:
17
13
  servers: ["127.0.0.1:9160"]
@@ -19,11 +15,7 @@ test:
19
15
  strategy_class: "org.apache.cassandra.locator.SimpleStrategy"
20
16
  strategy_options: {"replication_factor": "1"}
21
17
  connection_options:
22
- timeout: 10
18
+ timeout: 30
23
19
  solr:
24
- port: 8984
20
+ port: 8983
25
21
  path: /solr
26
- ssl:
27
- use_ssl: true
28
- cert: config/datastax_rails.crt
29
- key: config/datastax_rails.key