Hypertable migration causing problem with rails 2.3.8 - ruby-on-rails

I am using Hypertable db with the front end of HyperRecord. There were some bugs that i fixed in it. But now migrations get stuck me. When ever i do migrate it shows the error:
rake aborted!
undefined method `select_rows' for #<ActiveRecord::ConnectionAdapters::HypertableAdapter:0xb6f791c4>
.rvm/gems/ruby-1.8.7-p352#r2.3.8/gems/activerecord-2.3.8/lib/active_record/connection_adapters/abstract/database_statements.rb:27:in `select_values'
When i look into the code or ruby on rails actice_record. It shows.
# Returns an array of arrays containing the field values.
# Order is the same as that returned by +columns+.
def select_rows(sql, name = nil)
end
undef_method :select_rows
I tried to remove these functions by adding a fix in initializes.
module ActiveRecord
module ConnectionAdapters
class HypertableAdapter
def select_rows(sql, name = nil)
end
end
end
end
Then it came with the error Nil value occurred while accepting array or hash. To fix it i added new method to the fix code.
module ActiveRecord
module ConnectionAdapters
class HypertableAdapter
def select_rows(sql, name = nil)
end
def select_values(sql, name = nil)
result = select_rows(sql, name)
result.map { |v| v[0] } unless result.nil?
end
end
end
end
then it came with the error:
rake aborted!
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.map
/.rvm/gems/ruby-1.8.7-p352#r2.3.8/gems/activerecord-2.3.8/lib/active_record/migration.rb:421:in `get_all_versions'
Does any one have an idea, what is going on with it?

This code removes all the errors. But now migrations runs well, but do not roll back.
module ActiveRecord
module ConnectionAdapters
class HypertableAdapter
def select_rows(sql, name = nil)
result = execute(sql)
rows = []
result.cells.each { |row| rows << row }
rows
end
def select_values(sql, name = nil)
result = select_rows(sql, name)
result.map { |v| v[0] } unless result.nil?
end
end
end
end
When i checked into schema file it shows the following error:
# Could not dump table "teams" because of following StandardError
# Unknown type '' for column 'ROW'

Related

Why do I get "uninitialized constant" when creating custom hash class?

In Rails, I'm trying to create a custom hash class, So I created a file in lib/core_ext/hash_with_variants.rb with this content
class VariantsHash < Hash
def []=(string, value)
all_variants(string).each do |variant|
super(variant, value)
end
end
def [](string)
all_variants(string).detect do |variant|
super(variant)
end
end
private
def all_variants(string)
downcase_string = string.downcase
string_length = string.length
variants = [downcase_string]
string_length.times do |i|
variants << downcase_string[0, i] + downcase_string[i + 1 , string_length]
end
variants
end
end
but when I try and initialize a new object using
VariantsHash.new
I get the error
NameError: uninitialized constant VariantsHash
What else do I need to be doing to get this right?
You need to require the file in your /config/application.rb.

how to set query timeout for oracle 11 in ruby

I saw other threads stating how to do it for mySql, and even how to do it in java, but not how to set the query timeout in ruby.
I'm trying to use the setQueryTimeout function in Jruby using OJDBC7, but can't find how to do it in ruby. I've tried the following:
#c.connection.instance_variable_get(:#connection).instance_variable_set(:#query_timeout, 1)
#c.connection.instance_variable_get(:#connection).instance_variable_set(:#read_timeout, 1)
#c.connection.setQueryTimeout(1)
I also tried modifying my database.yml file to include
adapter: jdbc
driver: oracle.jdbc.driver.OracleDriver
timeout: 1
none of the above had any effect, other then the setQueryTimeout which threw a method error.
Any help would be great
So I found a way to make it work, but I don't like it. It's very hackish and orphans queries on the database, but it at least allows my app to continue executing. I would still love to find a way to cancel the statement so i'm not orphaning queries that take longer then 10 seconds.
query_thread = Thread.new {
#execute query
}
begin
Timeout::timeout(10) do
query_thread.join()
end
rescue
Thread.kill(query_thread)
results = Array.new
end
Query timeout on Oracle-DB works for me with Rails 4 and JRuby
With JRuby you can use JBDC-function statement.setQueryTimeout to define query timeout.
Suddenly this requires patching of oracle-enhanced_adapter as shown below.
This example is an implementation of iterator-query without storing result in array, which also uses query timeout.
# hold open SQL-Cursor and iterate over SQL-result without storing whole result in Array
# Peter Ramm, 02.03.2016
# expand class by getter to allow access on internal variable #raw_statement
ActiveRecord::ConnectionAdapters::OracleEnhancedJDBCConnection::Cursor.class_eval do
def get_raw_statement
#raw_statement
end
end
# Class extension by Module-Declaration : module ActiveRecord, module ConnectionAdapters, module OracleEnhancedDatabaseStatements
# does not work as Engine with Winstone application server, therefore hard manipulation of class ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
# and extension with method iterate_query
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
# Method comparable with ActiveRecord::ConnectionAdapters::OracleEnhancedDatabaseStatements.exec_query,
# but without storing whole result in memory
def iterate_query(sql, name = 'SQL', binds = [], modifier = nil, query_timeout = nil, &block)
type_casted_binds = binds.map { |col, val|
[col, type_cast(val, col)]
}
log(sql, name, type_casted_binds) do
cursor = nil
cached = false
if without_prepared_statement?(binds)
cursor = #connection.prepare(sql)
else
unless #statements.key? sql
#statements[sql] = #connection.prepare(sql)
end
cursor = #statements[sql]
binds.each_with_index do |bind, i|
col, val = bind
cursor.bind_param(i + 1, type_cast(val, col), col)
end
cached = true
end
cursor.get_raw_statement.setQueryTimeout(query_timeout) if query_timeout
cursor.exec
if name == 'EXPLAIN' and sql =~ /^EXPLAIN/
res = true
else
columns = cursor.get_col_names.map do |col_name|
#connection.oracle_downcase(col_name).freeze
end
fetch_options = {:get_lob_value => (name != 'Writable Large Object')}
while row = cursor.fetch(fetch_options)
result_hash = {}
columns.each_index do |index|
result_hash[columns[index]] = row[index]
row[index] = row[index].strip if row[index].class == String # Remove possible 0x00 at end of string, this leads to error in Internet Explorer
end
result_hash.extend SelectHashHelper
modifier.call(result_hash) unless modifier.nil?
yield result_hash
end
end
cursor.close unless cached
nil
end
end #iterate_query
end #class_eval
class SqlSelectIterator
def initialize(stmt, binds, modifier, query_timeout)
#stmt = stmt
#binds = binds
#modifier = modifier # proc for modifikation of record
#query_timeout = query_timeout
end
def each(&block)
# Execute SQL and call block for every record of result
ActiveRecord::Base.connection.iterate_query(#stmt, 'sql_select_iterator', #binds, #modifier, #query_timeout, &block)
end
end
Use above class SqlSelectIterator like this example:
SqlSelectIterator.new(stmt, binds, modifier, query_timeout).each do |record|
process(record)
end

solr, sunspot, bad request, illegal character

I am introducing sunspot search into my project. I got a POC by just searching by the name field. When I introduced the description field and reindexed sold I get the following error.
** Invoke sunspot:reindex (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute sunspot:reindex
Skipping progress bar: for progress reporting, add gem 'progress_bar' to your Gemfile
rake aborted!
RSolr::Error::Http: RSolr::Error::Http - 400 Bad Request
Error: {'responseHeader'=>{'status'=>400,'QTime'=>18},'error'=>{'msg'=>'Illegal character ((CTRL-CHAR, code 11))
at [row,col {unknown-source}]: [42,1]','code'=>400}}
Request Data: "<?xml version=\"1.0\" encoding=\"UTF-8\"?><add><doc><field name=\"id\">ItemsDesign 1322</field><field name=\"type\">ItemsDesign</field><field name=\"type\">ActiveRecord::Base</field><field name=\"class_name\">ItemsDesign</field><field name=\"name_text\">River City Clocks Musical Multi-Colored Quartz Cuckoo Clock</field><field name=\"description_text\">This colorful chalet style German quartz cuckoo clock accurately keeps time and plays 12 different melodies. Many colorful flowers are painted on the clock case and figures of a Saint Bernard and Alpine horn player are on each side of the clock dial. Two decorative pine cone weights are suspended beneath the clock case by two chains. The heart shaped pendulum continously swings back and forth.
On every
I assuming that the bad char is 
 that you can see at the bottom. that 
 is littered in a lot of the descriptions. I'm not even sure what char that is.
What can I do to get solr to ignore it or clean the data so that sold can handle it.
Thanks
Put the following in an initializer to automatically clean sunspot calls of any UTF8 control characters:
# config/initializers/sunspot.rb
module Sunspot
#
# DataExtractors present an internal API for the indexer to use to extract
# field values from models for indexing. They must implement the #value_for
# method, which takes an object and returns the value extracted from it.
#
module DataExtractor #:nodoc: all
#
# AttributeExtractors extract data by simply calling a method on the block.
#
class AttributeExtractor
def initialize(attribute_name)
#attribute_name = attribute_name
end
def value_for(object)
Filter.new( object.send(#attribute_name) ).value
end
end
#
# BlockExtractors extract data by evaluating a block in the context of the
# object instance, or if the block takes an argument, by passing the object
# as the argument to the block. Either way, the return value of the block is
# the value returned by the extractor.
#
class BlockExtractor
def initialize(&block)
#block = block
end
def value_for(object)
Filter.new( Util.instance_eval_or_call(object, &#block) ).value
end
end
#
# Constant data extractors simply return the same value for every object.
#
class Constant
def initialize(value)
#value = value
end
def value_for(object)
Filter.new(#value).value
end
end
#
# A Filter to allow easy value cleaning
#
class Filter
def initialize(value)
#value = value
end
def value
strip_control_characters #value
end
def strip_control_characters(value)
return value unless value.is_a? String
value.chars.inject("") do |str, char|
unless char.ascii_only? and (char.ord < 32 or char.ord == 127)
str << char
end
str
end
end
end
end
end
Source (Sunspot Github Issues): Sunspot Solr Reindexing failing due to illegal characters
I tried the solution #thekingoftruth proposed, however it did not solve the problem. Found an alternative version of the Filter class in the same github thread that he links to and that solved my problem.
The main difference was the i use nested models through HABTM relationships.
This is my search block in the model:
searchable do
text :name, :description, :excerpt
text :venue_name do
venue.name if venue.present?
end
text :artist_name do
artists.map { |a| a.name if a.present? } if artists.present?
end
end
Here is the initializer that worked for me:
(in: config/initializers/sunspot.rb)
module Sunspot
#
# DataExtractors present an internal API for the indexer to use to extract
# field values from models for indexing. They must implement the #value_for
# method, which takes an object and returns the value extracted from it.
#
module DataExtractor #:nodoc: all
#
# AttributeExtractors extract data by simply calling a method on the block.
#
class AttributeExtractor
def initialize(attribute_name)
#attribute_name = attribute_name
end
def value_for(object)
Filter.new( object.send(#attribute_name) ).value
end
end
#
# BlockExtractors extract data by evaluating a block in the context of the
# object instance, or if the block takes an argument, by passing the object
# as the argument to the block. Either way, the return value of the block is
# the value returned by the extractor.
#
class BlockExtractor
def initialize(&block)
#block = block
end
def value_for(object)
Filter.new( Util.instance_eval_or_call(object, &#block) ).value
end
end
#
# Constant data extractors simply return the same value for every object.
#
class Constant
def initialize(value)
#value = value
end
def value_for(object)
Filter.new(#value).value
end
end
#
# A Filter to allow easy value cleaning
#
class Filter
def initialize(value)
#value = value
end
def value
if #value.is_a? String
strip_control_characters_from_string #value
elsif #value.is_a? Array
#value.map { |v| strip_control_characters_from_string v }
elsif #value.is_a? Hash
#value.inject({}) do |hash, (k, v)|
hash.merge( strip_control_characters_from_string(k) => strip_control_characters_from_string(v) )
end
else
#value
end
end
def strip_control_characters_from_string(value)
return value unless value.is_a? String
value.chars.inject("") do |str, char|
unless char.ascii_only? && (char.ord < 32 || char.ord == 127)
str << char
end
str
end
end
end
end
end
You need to get rid of control characters from UTF8 while saving your content. Solr will not reindex this properly and throw this error.
http://en.wikipedia.org/wiki/UTF-8#Codepage_layout
You can use something like this:
name.gsub!(/\p{Cc}/, "")
edit:
If you want to override it globally I think it could be possible by overriding value_for_methods in AttributeExtractor and if needed BlockExtractor.
https://github.com/sunspot/sunspot/blob/master/sunspot/lib/sunspot/data_extractor.rb
I wasn't checking this.
If you manage to add some global patch, please let me know.
I had lately same issue.

How can I hide a column from a model in Rails 3.2?

Prior to Rails 3.1, we could update the self.columns method of ActiveRecord::Base.
But that doesn't seem to work now.
Now it seems if I remove a column from a table, I am forced to restart the Rails server. If I don't I keep getting errors when INSERTs to the table happen. Rails still thinks the old column exists, even though it's not in the database anymore.
Active Record does not support this out of the box, because it queries the database to get the columns of a model (unlike Merb's ORM tool, Datamapper).
Nonetheless, you can patch this feature on Rails with (assuming, for instance, you want to ignore columns starting with "deprecated" string):
module ActiveRecord
module ConnectionAdapters
class SchemaCache
def initialize(conn)
#connection = conn
#tables = {}
#columns = Hash.new do |h, table_name|
columns = conn.columns(table_name, "#{table_name} Columns").reject { |c| c.name.start_with? "deprecated"}
h[table_name] = columns
end
#columns_hash = Hash.new do |h, table_name|
h[table_name] = Hash[columns[table_name].map { |col|
[col.name, col]
}]
end
#primary_keys = Hash.new do |h, table_name|
h[table_name] = table_exists?(table_name) ? conn.primary_key(table_name) : nil
end
end
end
end
end
You can clear the ActiveRecord schema cache:
ActiveRecord::Base.connection.schema_cache.clear_table_cache(:table_name)!
Then it'll be reloaded the next time you reference a model that uses that table.

Rails Method Ignoring Default Param - WHY?

I am at a loss as to why this is happening. I have the following function:
def as_json(options = {})
json = {
:id => id,
# ... more unimportant code
}
unless options[:simple]
# ... more unimportant code
end
json
end
It works most of the time, but in one particular partial where I call this:
window.JSONdata = <%= #day.to_json.html_safe %>
I get the following error:
ActionView::Template::Error (You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]):
Pointing to the line "unless options[:simple]". As far as I can tell, the options hash is nil - thus the method is ignoring the default param assignment. WHY? I can fix this by changing the method to:
def as_json(options)
options ||= {}
json = {
:id => id,
# ... more unimportant code
}
unless options[:simple]
# ... more unimportant code
end
json
end
Does this make any sense to anyone!? Most appreciative for your help.
This is because you're using to_json, which has a default options of nil. to_json will eventually call as_json and pass the nil as options.
Here's where it happens on the Rails source code. First, to_json is defined with the default options of nil.
# https://github.com/rails/rails/blob/v3.0.7/activesupport/lib/active_support/core_ext/object/to_json.rb#L15
def to_json(options = nil)
ActiveSupport::JSON.encode(self, options)
end
Eventually it will arrive here.
# https://github.com/rails/rails/blob/v3.0.7/activesupport/lib/active_support/json/encoding.rb#L41
def encode(value, use_options = true)
check_for_circular_references(value) do
jsonified = use_options ? value.as_json(options_for(value)) : value.as_json
jsonified.encode_json(self)
end
end
As you see, as_json is called with value.as_json(options_for(value)) and options_for(value) will return the default value of to_json, which is nil.

Resources