Remove enum value with gem sequel - ruby

I have a db - Postgresql v11.3 and Sequel with pg_enum, so how I can remove value from enum type?
For example, need change column enum type :
Sequel.migration do
up do
removed_values = %w["val1" "val2"]
remove_enum_value= (:old_enum_type, removed_values)
create_enum(
:enum_column,
%w[val3 val4]
)
alter_table :users do
set_column_type(
:enum_column,
'enum_column[]',
using: 'old_enum_column::text[]:::enum_column[]'
)
set_column_default :enum_column, '{}'
end
end
end
New enum type same as previous, with little different - new type doesn't have a some values. But, may be situation if somebody use missing values - migration will be crashed.
Unfortunatly, pg_enum don't have a method, that will able simple remove enum value

If you review https://www.postgresql.org/docs/12/sql-altertype.html, you will see that PostgreSQL supports adding and renaming enum values, but not removing them.

Related

Access value from a Netsuite hash, Enumerator

Hi I am trying to extract a value from a Netsuite hash inside custom fields, and some others, which typically look like this - `
"custbody_delivery_ticket_number"=>
{
"script_id"=>"custbody_delivery_ticket_number",
"internal_id"=>"2701",
"type"=>"platformCore:DateCustomFieldRef",
"attributes"=> {
"value"=>"123abc"
}
}` and want the value of it inside of attributes.
Have tried many different ways, but one in particular -
delivery_ticket_number: "#{netsuite_sales_orders.custom_field_list.custom_fields.select['custbody_nef_meter_ticket_number']['attributes']['value']}",
throws error for class Enumerator, NoMethodError: undefined method `[]' for #Enumerator:0x00005589ec778730 which indicates may be getting close, but doing something wrong.
If anyone has any idea how to get values from these kind of hashes?
(Am told by the system admin that it is the correct custbody identifier)
Many Thanks
Eventually fixed this, grabbing Netsuite custom fields with a select of script_id by name,and map as below:
delivery_date:netsuite_sales_order.custom_fields_list.custom_fields.select { |field| field.script_id == 'custbody_delivery_date' }.map { |field| field.value }.first
First selecting the script_id by unique name, then mapping to the value. Was able to get any custom field like this, preferable as they can move and might not have the same index if use an index to grab them, fetching an incorrect value. This way ensures getting the correct data even if the item is moved up or down in the custom fields list.
Thanks for everyones help!

How to set a property in ruby datamapper that is a function of another property of the same object?

I want to add two new properties to a ruby datamapper model, one that is a date cast of a timestamp property and another that is a value from another object connected through a unique key.
So for the first case I have
property :date, DateTime
and I want to add another
property :date_date, Date
that by default will be equal to date.to_date
You should see the docs: https://datamapper.org/docs/properties.html
Specifically the sections on "Available Types" and "Setting default values".
You can do it like this:
property :date_date, Date, default: -> do |obj, prop|
obj.date.to_date
end
You can alternatively set it through a callback (https://datamapper.org/docs/callbacks.html), for example:
property :date_date, Date
before_save :set_date_date
def set_date_date
self.date_date = date.to_date
end
Note it works basically the same way in Rails' ActiveRecord as well.

pg gem: 'Warning: no type cast defined for type "numeric" '

I'm having trouble getting typed results out of the pg gem.
require 'pg'
require_relative 'spec/fixtures/database'
client = PG.connect( DB[:pg] )
client.type_map_for_queries = PG::BasicTypeMapForQueries.new(client)
client.type_map_for_results = PG::BasicTypeMapForResults.new(client)
client.exec( %|select * from testme;| ) do |query|
query.each {|r| puts r.inspect }
end
This program gives the output:
Warning: no type cast defined for type "money" with oid 790. Please cast this type explicitly to TEXT to be safe for future changes.
Warning: no type cast defined for type "numeric" with oid 1700. Please cast this type explicitly to TEXT to be safe for future changes.
{"string"=>"thing", "logical"=>true, "cash"=>"£1.23", "reel"=>"2.34", "day"=>#<Date: 2015-12-31 ((2457388j,0s,0n),+0s,2299161j)>, "float"=>3.45}
So: booleans and floats and dates (and integers) get converted, but not numerics or the money type.
Can anyone tell me how to "cast the type explicitly", assuming that I don't want to hard-code a solution for each table?
Hijacking this thread, as after some digging I finally found a way to add a custom decoder/encoder, so posting an example below:
require 'ipaddr'
require 'pg'
class InetDecoder < PG::SimpleDecoder
def decode(string, tuple=nil, field=nil)
IPAddr.new(string)
end
end
class InetEncoder < PG::SimpleEncoder
def encode(ip_addr)
ip_addr.to_s
end
end
# 0 if for text format, can also be 1 for binary
PG::BasicTypeRegistry.register_type(0, 'inet', InetEncoder, InetDecoder)
Here's a catch all for those seeking to cast strings by default:
client = PG.connect( DB[:pg] )
map = PG::BasicTypeMapForResults.new(conn)
map.default_type_map = PG::TypeMapAllStrings.new
client.type_map_for_results = map
Got the same problem with a text-ish field. Solved by duplicating a coder and editing its OID.
text_coder = client.type_map_for_results.coders.find { |c| c.name == 'text' }
new_coder = text_coder.dup.tap { |c| c.oid = 19 } # oid from the warning
conn.type_map_for_results.add_coder(new_coder)
How I got there: it might interest the next guy, if the problem is similar but not identical.
I read other people online talking about type_map_for_results, but how they didn't know how to define a coder. Since it was a text field in my case, I decided to try cloning an existing one. I knew I could find a textual pre-set in a Rails app, so I opened a rails console and searched:
adapter = ActiveRecord::Base.connection
connection = adapter.instance_variable_get("#connection")
mapping = connection.type_map_for_results
cd mapping # my console of choice is `pry`
ls # spotted a likely getter named `coders`
cd coders # again
ls # spotted getter `name` and setter `oid=`
So I put together the code in the solution. Gave it a try, and it worked.
It had not been straightforward to find, so I decided to exit lurker mode and share it on SO. Thereby: thanks #Andreyy for bringing me in :)
[pry cd and ls]
Google the error message: "Warning: no type cast defined for type"
You can find it's source github.
Reding the class, I would guess lines from 150 to 214 could be consiredered
examples:
register_type 0, 'text', PG::TextEncoder::String
alias_type 0, 'varchar', 'text'
Since register_type and alias_type are class methods of PG::BasicTypeRegistry::CoderMap I would play with them just and see if anything changes:
PG::BasicTypeRegistry::CoderMap.alias_type 0, 'money', 'text'
PG::BasicTypeRegistry::CoderMap.alias_type 0, 'numeric', 'text'
Reading the comments in the class it seems that the coding/decoding of those and some other fields is not implemented.
You might consider using a higher level ORM library like AvtiveRecord which implements more types (money).

uninitialized constant OCI8::Object::Mdsys::SdoGeometry

I need to patch oracle enhanced adapter for some reasons.
In my oracle_enhanced_adapter.rb file, I need to get OCI8::Object::Mdsys::SdoGeometry.new return value, but it returns uninitialized constant OCI8::Object::Mdsys::SdoGeometry.
But, if before executing OCI8::Object::Mdsys::SdoGeometry.new command, I execute OnlineGpsPoint.first command (OnlineGpsPoint contains an sdo_geometry column) and get one of the rows in the table, OCI8::Object::Mdsys::SdoGeometry will be initialized.
The problem is that I don't want hardcoded 'OnlineGpsPoint' in my program. I just need OCI8::Object::Mdsys::SdoGeometry value.
Is there a solution for the pain?
When ruby-oci8 finds an unknown object type, it automatically defines a ruby class under OCI8::Object. If you know the object type name, it is better to define the ruby class in advance as follows:
# Oracle object type name is *guessed* from the ruby class name.
# SdoGeometry => SDO_GEOMETRY ==(public synonym)=> MDSYS.SDO_GEOMETRY
class SdoGeometry < OCI8::Object::Base
end
or
# Set Oracle object type name explicitly
class AnyClassName < OCI8::Object::Base
set_typename('MDSYS.SDO_GEOMETRY')
end
If you want same name with the automatically generated class:
module OCI8::Object::Mdsys
class SdoGeometry < OCI8::Object::Base
set_typename('MDSYS.SDO_GEOMETRY')
end
end

Comma separated numbers in rails 3.0.5 project

In my rails project I have a form to enter a dollar amount. This amount is stored as an integer in a mysql database.
<%=f.label :Amount%><br/>
<%=f.text_field :amount%>
if the user enters the number using a "." separator like 2034.34 it works well. My problem is when someone uses a "," as in 2,034. This number is stored just as a 2 in the databases. How do I get the app to store number with both comma and decimal separators?
Update
Nkm put on the right track but I got a stack too deep error. I ended up using
def amount=(amt)
write_attribute(:amount,amt.gsub(",", ""))
end
Since the database column is decimal/float, we should process the data into the right format before saving.
You can either go with activerecord before_save callback or override the setter method of that attribute as follows,
#model.rb
def amount=(amt)
self.amount = amt.gsub(",", "")
end
You may add before_save callback in your Model to convert commas to dot .
before_save { self.amount.gsub!(/\,/, "." }
irb example:
"2,034".gsub!(/\,/, ".")
# => "2.034"
You ask to store the amount as a formatted String in the database. I think it's a really bad idea: it will be difficult to do calculation with this string (sums, comparison, etc...). Use a float column instead.
You can use a callback (I hope they're available in 3.0.5) on your ActiveRecord model to remove the comma before saving. For example
before_save :format_amount
def format_amount
self.amount.delete! ','
end
Use NumberHelper to display back the comma in your view.

Resources