jashmenn / activeuuid Goto Github PK
View Code? Open in Web Editor NEWBinary uuid keys in Rails
License: MIT License
Binary uuid keys in Rails
License: MIT License
Hi,
For the normal id key (int(11)) we can use the following command:
class AddIdToProducts < ActiveRecord::Migration
def change
add_column :products, :id, :primary_key
end
end
How can we do it for uuid primary key?
Best
On this line:
https://github.com/jashmenn/activeuuid/blob/master/lib/activeuuid/uuid.rb#L146
self.class.columns_hash[primary_key].type => binary
which != :uuid
The db is mysql, i'm using the mysql2 gem and the field is a binary 16 field in the DB.
activeuuid (0.6.0)
activerecord (>= 3.1)
uuidtools
Currently an .to_yaml of a activeuuid::UUID looks like
The human-readable (.to_s) version would be much better for serialization and inter-database compatibility. In my specific case, moving data from MySQL with activeuuid to Postgres with integrated UUID support with the yaml_db plugin.
In my research so far, it looks like the answer may be defining the datatype in the style of lib/yaml/rubytypes.rb - but the versions I can find look like outdated code.
I'm integrating Ahoy with Rails 4.2.0.beta2 and thus using the git version of activeuuid. Given this migration:
class CreateAhoyEvents < ActiveRecord::Migration
def change
create_table :ahoy_events, id: false do |t|
t.uuid :id, primary_key: true
t.uuid :visit_id
t.integer :user_id
t.string :name
t.text :properties
t.timestamp :time
end
add_index :ahoy_events, [:visit_id]
add_index :ahoy_events, [:user_id]
add_index :ahoy_events, [:time]
end
end
Creates a schema like this:
create_table "ahoy_events", force: true do |t|
t.uuid "visit_id", limit: 16
t.integer "user_id"
t.string "name"
t.text "properties"
t.datetime "time"
end
add_index "ahoy_events", ["id"], name: "sqlite_autoindex_ahoy_events_1", unique: true
add_index "ahoy_events", ["time"], name: "index_ahoy_events_on_time"
add_index "ahoy_events", ["user_id"], name: "index_ahoy_events_on_user_id"
add_index "ahoy_events", ["visit_id"], name: "index_ahoy_events_on_visit_id"
Which causes an error like this on schema loading (e.g. when running tests):
gems/sqlite3-1.3.8/lib/sqlite3/database.rb:91:in `initialize': SQLite3::SQLException: object name reserved for internal use: sqlite_autoindex_ahoy_events_1: CREATE UNIQUE INDEX "sqlite_autoindex_ahoy_events_1" ON "ahoy_events" ("id") (ActiveRecord::StatementInvalid)
I've been unsuccessful in figuring out where that sqlite_autoindex line comes from, but changing t.uuid
to t.binary
seems to prevent it from happening. Is this a valid fix for sqlite? On the other hand, I'd very much like a migration that works both on our PostgreSQL servers and local development SQLites.
I seem to receive the same error as #60, but in a different function, stack trace below.
This worked fine with Rails 4.1. Please let me know how I can help to debug and fix this.
activerecord-4.2.4/lib/active_record/connection_adapters/abstract/quoting.rb:34→ rescue in type_cast
activerecord-4.2.4/lib/active_record/connection_adapters/abstract/quoting.rb:23→ type_cast
activeuuid-0.6.1/lib/activeuuid/patches.rb:154→ type_cast_with_visiting
activerecord-4.2.4/lib/active_record/connection_adapters/postgresql_adapter.rb:602→ block in exec_cache
activerecord-4.2.4/lib/active_record/connection_adapters/postgresql_adapter.rb:601→ map
activerecord-4.2.4/lib/active_record/connection_adapters/postgresql_adapter.rb:601→ exec_cache
activerecord-4.2.4/lib/active_record/connection_adapters/postgresql_adapter.rb:589→ execute_and_clear
activerecord-4.2.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:160→ exec_query
activerecord-4.2.4/lib/active_record/connection_adapters/abstract/database_statements.rb:351→ select
activerecord-4.2.4/lib/active_record/connection_adapters/abstract/database_statements.rb:32→ select_all
activerecord-4.2.4/lib/active_record/connection_adapters/abstract/query_cache.rb:68→ block in select_all
activerecord-4.2.4/lib/active_record/connection_adapters/abstract/query_cache.rb:83→ cache_sql
activerecord-4.2.4/lib/active_record/connection_adapters/abstract/query_cache.rb:68→ select_all
activerecord-4.2.4/lib/active_record/querying.rb:39→ find_by_sql
activerecord-4.2.4/lib/active_record/relation.rb:639→ exec_queries
activerecord-4.2.4/lib/active_record/relation.rb:515→ load
activerecord-4.2.4/lib/active_record/relation.rb:243→ to_a
activerecord-4.2.4/lib/active_record/relation/finder_methods.rb:500→ find_nth_with_limit
activerecord-4.2.4/lib/active_record/relation/finder_methods.rb:484→ find_nth
activerecord-4.2.4/lib/active_record/relation/finder_methods.rb:127→ first
ahoy_matey-1.2.1/lib/ahoy/stores/active_record_store.rb:46→ visit
ahoy_matey-1.2.1/lib/ahoy/stores/base_store.rb:19→ authenticate
ahoy_matey-1.2.1/lib/ahoy/tracker.rb:51→ authenticate
ahoy_matey-1.2.1/lib/ahoy/warden.rb:4→ block in <top (required)>
When I run my rails specs I see that the primary key is of type int(11) instead of being binary(16) and then the id field is of type int instead of being an uuid.
class CreateProducts < ActiveRecord::Migration
def change
create_table :products, :id => false do |t|
t.uuid :id, :primary_key => true
end
end
end
ActiveRecord::Schema.define(version: 201570707070) do
create_table "products", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
end
end
Development version of MySql
CREATE TABLE `products` (
`id` binary(16) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Test version of MySql
CREATE TABLE `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Dose any body have a clue on what is going on hear?
The add_column call doesn't work starting with Rails 4.2.0.
I am using the mysql2 adapter -- I've not test the issue with other adapters, and using the master branch after the merge of pull request #52 (4.2 support).
The resulting MySQL expression for add_column :table_name, :column_name, :uuid
is:
ALTER TABLE `table_name` ADD `column_name` uuid
Similarily, for a change_column
ALTER TABLE `table_name` CHANGE `column_name` `column_name` uuid
This naturally results in a Mysql2::Error: You have an error in your SQL syntax near 'uuid'
.
I went hunting through ActiveRecord for the appropriate change, but couldn't find the right place, apologies.
@pyromaniac - trying to following the example in the documentation that indicates
let(:guid) { "1dd74dd0-d116-11e0-99c7-5ac5d975667e" }
it "should be able to find an email by the uuid" do
Email.find(guid).id.to_s.should == guid
end
This doesn't appear to work. When I try this myself I get ...
All examples were filtered out; ignoring {:focus=>true}
Models::Cognito::User
[6, 15] in /home/vagrant/dwapi/spec/models/cognito/user_spec.rb
6: user.id = "b465e6ed-34c5-4535-b26e-07de241b0d30"
7:
8: user.save!
9:
10: byebug
=> 11: found_user = described_class.find "b465e6ed-34c5-4535-b26e-07de241b0d30"
12:
13: expect(found_user).to eq user
14: end
15: end
(byebug) user
#<Models::Cognito::User id: #<UUID:0x53a6588 UUID:b465e6ed-34c5-4535-b26e-07de241b0d30>, account_id: nil, created_at: "2016-08-02 16:54:36", updated_at: "2016-08-02 16:54:36">
(byebug) user.id
#<UUID:0x53a6588 UUID:b465e6ed-34c5-4535-b26e-07de241b0d30>
(byebug) user.id.to_s
"b465e6ed-34c5-4535-b26e-07de241b0d30"
(byebug) Models::Cognito::User.find "b465e6ed-34c5-4535-b26e-07de241b0d30"
ActiveRecord::RecordNotFound Exception: Couldn't find Models::Cognito::User with 'id'=b465e6ed-34c5-4535-b26e-07de241b0d30
nil
(byebug) Models::Cognito::User.all
#<ActiveRecord::Relation [#<Models::Cognito::User id: #<UUID:0x55e8580 UUID:b465e6ed-34c5-4535-b26e-07de241b0d30>, account_id: nil, created_at: "2016-08-02 16:54:36", updated_at: "2016-08-02 16:54:36">]>
Advice?
I'm using Rails 4.1.6 on sqlite3.
On the default (generated) controllers, show operation does not work.
The sql generated is the following:
SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", "84857d86-9700-4bc2-b934-63ffedd76bee"]]
But the working one is:
SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", "\x84\x85}\x86\x97\x00K\xC2\xB94c\xFF\xED\xD7k\xEE"]]
I've solved the problem modifing the set method on the controller, to ensure String is used
def set_post
@post = Post.find(params[:id].to_s)
end
We were considering using this gem for our project, but our client is very specific about the OSS licensing.. you might want to pick one for others that might be in the same boat. ( little nudge, MIT seems popular among gems, and also seems to be the more permissive one regarding commercial applications.. afaik)
I get this error which I guess is caused by :type_cast_code becoming obsolete? Anyway, it seems to be solved by unaliasing it (see mahemoff@4a8b2e6), but I don't know the details and it would need a check for compatibility purposes.
I'm getting the following error when I try to create a model with a UUID primary key in rails 4.0.2:
ActiveRecord::StatementInvalid: PG::CharacterNotInRepertoire: ERROR: invalid byte sequence for encoding "UTF8": 0xd6 0x40
running reload!
from the console seems to fix the problem so I'm wondering if this is a race condition in startup. I know rails added uuid's in 4 at some point and so I'm wondering if it's a conflict with the new uuid column type. Any ideas?
Full error: https://gist.github.com/D1plo1d/1f5a57b90e2a0d331a94
Backstory: We have an app that uses a bunch of serialization to store relationships. Converting the entire DB to UUIDs is kind of a non-starter if we can find a way around it. We are moving to UUIDs to support multi-master replication of new records, so we are hoping to maintain support of our old integer IDs.
I just tried a test install of this gem and it (predictably) breaks the old integer IDs. Is there a workaround to make preexisting integer IDs backward compatible, or are we stuck with a string-based strategy?
Hi,
I have the following models:
class UserGrant < ActiveRecord::Base
belongs_to :permission
end
class Permission < ActiveRecord::Base
self.primary_key = :id
include ActiveUUID::UUID
has_many :user_grants
end
As soon as I do something like UserGrant.includes(:permission)
I get the following errors:
ERROR: invalid input syntax for uuid: "--- !ruby/object:UUIDTools::UUID
time_low: 3596406877
time_mid: 22434
time_hi_and_version: 23521
clock_seq_hi_and_reserved: 163
clock_seq_low: 196
nodes:
- 231
- 120
- 27
- 208
- 88
- 54
" at character 108
STATEMENT: SELECT "permissions".* FROM "permissions" WHERE "holman_auth_permissions"."id" IN ('--- !ruby/object:UUIDTools::UUID ...)
If I remove the includes
and do UserGrant.first.permission
, I get the joined record just fine.
This started happening as I upgraded to Rails 4.2.10.
Any help is appreciated, thanks!
I have some problem after installing the gem (Rails 4.1.8).
When I make the first request to the controller after starting the server.
Rails looks for record id as a string (!):
Host Load (0.4ms) SELECT
hosts. * FROM
hostsWHERE
hosts.
id= '67e5f9ba88aa464898214a1112d0d5a6' LIMIT 1
And I get the error:
Could not find Host with 'id' = 67e5f9ba88aa464898214a1112d0d5a6
I found a bad solution. I think that the problem with the cache Rails.
Host Load (0.4ms) SELECT
hosts. * FROM
hostsWHERE
hosts.
id= x'67e5f9ba88aa464898214a1112d0d5a6 'LIMIT 1
4. It work
activeuuid raises follwing error on inclusion:
NameError: undefined method``type_cast' for class``ActiveRecord::ConnectionAdapters::Column'
The offending line seems to be activeuuid-0.5.0/lib/activeuuid/patches.rb:36
From what I figured out, the api was changed completely in the Column class:
Amongst this and other commits:
rails/rails@0b682e4
type_cast
seems to be replaced by type_cast_for_database
simplified_type seems to be gone altogether...
I'd like to generate a uuid for the id in memory, such that it has a valid id as I pass it around before it gets to the database. Any thought about supporting that option?
Hi There,
Could you be so kind as to release a 0.5.1 version - it would be nice to have a version with 4.2 support without needed to the git path the Gemfile.
Thank you!
I was wondering if this was still maintained? I see a lot of open issues, PR's, and forks.
Hi!
I am currently trying to get this gem to work with sqlite so that it can be used in a default rails development environment. I have already worked on some issues that prevented a new entry from being saved and now I am having issues retrieving data from the database by its uuid. This is what I am currently using:
> Person.find(UUIDTools::UUID.parse("0320cdfa-04d2-11e1-a1a1-14dae903e06a"))
/home/florian/.rvm/gems/ruby-1.8.7-p352@contacts/gems/activerecord-3.1.1/lib/active_record/connection_adapters/abstract/quoting.rb:46: warning: Object#id will be deprecated; use Object#object_id
Person Load (0.2ms) SELECT "people".* FROM "people" WHERE "people"."id" = ? LIMIT 1 [["id", #<UUID:0x3fbf87905e1c UUID:0320cdfa-04d2-11e1-a1a1-14dae903e06a>]]
ActiveRecord::RecordNotFound: Couldn't find Person with id=0320cdfa-04d2-11e1-a1a1-14dae903e06a
from /home/florian/.rvm/gems/ruby-1.8.7-p352@contacts/gems/activerecord-3.1.1/lib/active_record/relation/finder_methods.rb:339:in `find_one'
from /home/florian/.rvm/gems/ruby-1.8.7-p352@contacts/gems/activerecord-3.1.1/lib/active_record/relation/finder_methods.rb:310:in `find_with_ids'
from /home/florian/.rvm/gems/ruby-1.8.7-p352@contacts/gems/activerecord-3.1.1/lib/active_record/relation/finder_methods.rb:107:in `find'
from /home/florian/.rvm/gems/ruby-1.8.7-p352@contacts/gems/activerecord-3.1.1/lib/active_record/base.rb:441:in `__send__'
from /home/florian/.rvm/gems/ruby-1.8.7-p352@contacts/gems/activerecord-3.1.1/lib/active_record/base.rb:441:in `find'
from (irb):1
From my tests I can say that the Arel::Visitor is never used and it looks like ActiveRecord is trying to use the to_s method of the UUID object. This, of course, is then not the right way to retrieve an entry...
Maybe someone can help me with that ... I will put a fork on github a little later.
Edit: Just FYI, here is my fork: https://github.com/Raven24/activeuuid
I have a new Rails 4.2.1 app, followed usual Readme setup with Gemfile and placed "include ActiveUUID::UUID" line in my model. However, every time I run specs or rails console, the activeuuid patches have not been applied.
I added a break to the .apply method in ActiveUUID::Patches, and the mysql2 adapter,
ActiveRecord::ConnectionAdapters::Mysql2Adapter
is not defined at that point.
The result, if I start a console, is that I need to do a manual "ActiveUUID::Patches.apply!" to get things working.
Anybody else see this? Am I doing something wrong?
Odd part is, I have a Rails 4.2.0 app using activeuuid and all is good.
So I have a Rails project and UUIDs as primary key is a requirement and I'm giving this gem a shot.
One issue I've ran into is the relational ids. Take your Email example...
class Email < ActiveRecord::Base
include ActiveUUID::UUID
belongs_to :sender
end
Let's also assume :sender
is using ActiveUUID.
If I was editing an Email object using a typical Rails form I'd probably list a bunch of senders in a pull down and use the full string UUID in the option tag. When coming back in through mass assignment in a typical form the sender_id on the Email instance would be a string object. Are there any plans to add a flag or something to have this gem auto process mass assignment ids and rebuild them as UUID objects.
For now I've added the follow as a before_validation
method:
# Because these ids come back in as strings from froms we need to reparse them to become UUID objects
def fix_uuid_strings
if !self.session_description_id.nil? && self.session_description_id.class != UUIDTools::UUID
self.session_description_id = UUIDTools::UUID.parse(self.session_description_id)
end
end
@Items = @items.where("id > ?", UUIDTools::UUID::parse_hexdigest(params[:since_id])) if params[:since_id]
In a clean Rails 5.0.0.beta3 project, adding
gem 'activeuuid', '>= 0.5.0'
to the Gemfile
causes the following failure to start the Rails server.
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from require at /var/lib/gems/2.3.0/gems/bundler-1.11.2/lib/bundler/runtime.rb:77)
/var/lib/gems/2.3.0/gems/bundler-1.11.2/lib/bundler/runtime.rb:80:in `rescue in block (2 levels) in require': There was an error while trying to load the gem 'activeuuid'. (Bundler::GemRequireError)
from /var/lib/gems/2.3.0/gems/bundler-1.11.2/lib/bundler/runtime.rb:76:in `block (2 levels) in require'
from /var/lib/gems/2.3.0/gems/bundler-1.11.2/lib/bundler/runtime.rb:72:in `each'
from /var/lib/gems/2.3.0/gems/bundler-1.11.2/lib/bundler/runtime.rb:72:in `block in require'
from /var/lib/gems/2.3.0/gems/bundler-1.11.2/lib/bundler/runtime.rb:61:in `each'
from /var/lib/gems/2.3.0/gems/bundler-1.11.2/lib/bundler/runtime.rb:61:in `require'
from /var/lib/gems/2.3.0/gems/bundler-1.11.2/lib/bundler.rb:99:in `require'
from /home/simon/Projects/rails5-activeuuid-test/config/application.rb:7:in `<top (required)>'
from /home/simon/.bundler/gems/railties-5.0.0.beta3/lib/rails/commands/commands_tasks.rb:88:in `require'
from /home/simon/.bundler/gems/railties-5.0.0.beta3/lib/rails/commands/commands_tasks.rb:88:in `block in server'
from /home/simon/.bundler/gems/railties-5.0.0.beta3/lib/rails/commands/commands_tasks.rb:85:in `tap'
from /home/simon/.bundler/gems/railties-5.0.0.beta3/lib/rails/commands/commands_tasks.rb:85:in `server'
from /home/simon/.bundler/gems/railties-5.0.0.beta3/lib/rails/commands/commands_tasks.rb:49:in `run_command!'
from /home/simon/.bundler/gems/railties-5.0.0.beta3/lib/rails/command.rb:20:in `run'
from /home/simon/.bundler/gems/railties-5.0.0.beta3/lib/rails/commands.rb:18:in `<top (required)>'
from /home/simon/Projects/rails5-activeuuid-test/bin/rails:9:in `require'
from /home/simon/Projects/rails5-activeuuid-test/bin/rails:9:in `<top (required)>'
from /home/simon/.bundler/gems/spring-1.6.4/lib/spring/client/rails.rb:28:in `load'
from /home/simon/.bundler/gems/spring-1.6.4/lib/spring/client/rails.rb:28:in `call'
from /home/simon/.bundler/gems/spring-1.6.4/lib/spring/client/command.rb:7:in `call'
from /home/simon/.bundler/gems/spring-1.6.4/lib/spring/client.rb:28:in `run'
from /home/simon/.bundler/gems/spring-1.6.4/bin/spring:49:in `<top (required)>'
from /home/simon/.bundler/gems/spring-1.6.4/lib/spring/binstub.rb:11:in `load'
from /home/simon/.bundler/gems/spring-1.6.4/lib/spring/binstub.rb:11:in `<top (required)>'
from /home/simon/Projects/rails5-activeuuid-test/bin/spring:13:in `require'
from /home/simon/Projects/rails5-activeuuid-test/bin/spring:13:in `<top (required)>'
from bin/rails:3:in `load'
from bin/rails:3:in `<main>'
I'd prefer to use the type 4 UUID (random). Any thoughts about supporting this? I should have mentioned in the other issue that I'm happy to code up a solution for either of these if they don't fit in your roadmap.
Rails 4.2
Ruby 2.2.0
The error happens when I execute Model.create.
With SQLite works fine.
TypeError: can't cast UUIDTools::UUID to uuid
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/quoting.rb:34:in `rescue in type_cast'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/quoting.rb:23:in `type_cast'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activeuuid-0.6.0/lib/activeuuid/patches.rb:128:in `type_cast_with_visiting'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `block in exec_cache'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql_adapter.rb:597:in `map'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql_adapter.rb:597:in `exec_cache'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql_adapter.rb:585:in `execute_and_clear'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:160:in `exec_query'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:192:in `exec_insert'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/database_statements.rb:108:in `insert'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `insert'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/relation.rb:64:in `insert'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/persistence.rb:521:in `_create_record'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/counter_cache.rb:139:in `_create_record'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/attribute_methods/dirty.rb:127:in `_create_record'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/callbacks.rb:306:in `block in _create_record'
... 20 levels...
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/transaction.rb:188:in `within_new_transaction'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/transactions.rb:220:in `transaction'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/transactions.rb:344:in `with_transaction_returning_status'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/transactions.rb:286:in `block in save'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/transactions.rb:301:in `rollback_active_record_state!'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/transactions.rb:285:in `save'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/persistence.rb:34:in `create'
from (irb):4
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/railties-4.2.0/lib/rails/commands/console.rb:110:in `start'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/railties-4.2.0/lib/rails/commands/console.rb:9:in `start'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:68:in `console'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
from /opt/code/lista_compras_server/shared/bundle/ruby/2.2.0/gems/railties-4.2.0/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:8:in `require'
from bin/rails:8:in `<main>'2.2.0 :005
After update of activeuuid 0.5.0 to 0.6.1 my schema.rb file changed from:
- create_table "ahoy_events", force: true do |t|
- t.uuid "visit_id"
+ create_table "ahoy_events", force: :cascade do |t|
+ t.uuid "visit_id", limit: 16
force: true
changed to force: :cascade
because of update of activerecord. However, I can't find any explanation for addition of limit: 16
. Finding this kind of info would have been trivial if activeuuid
maintained a changelog as well.
Read more on why?
I'm looking at my MySQL table after I set :primary_key => true
, and it's saying instead of PRI it's "MUL". Is this okay?
For development, sqlite doesn't seem support in the latest version of this gem.
My schema shows this:
Instead of type binary(16) could we instead use:
t.binary, :limit => 16
for sqlite?
Is there some reason this wouldn't work?
A common rails action response might look something like this:
def create
@ad = Ad.new(ad_params)
@ad.advertiser_id = current_user.advertiser.id
respond_to do |format|
if @ad.save
format.html { redirect_to @ad, notice: 'Ad was successfully created.' }
format.json { render status: :created, json: { success: true, info: @response[:success], data: @ad }}
else
format.html { render :new }
format.json { render status: :unprocessable_entity, json: { success: false, info: @response[:error], errors: @ad.errors } }
end
end
end
In the successful Create case
format.json { render status: :created, json: { success: true, info: @response[:success], data: @ad
The ad.id is sent back to my API as the hex value for ex: 2B77F7F7B1C84130B875E09DE0693329
What am I missing? I need it to be the UUID format.
Also, when running DB queries like in NaviCat, how do you do queries that lookup or join on these binary values?
Hi,
I've been having issues with ActiveUUID producing incorrect SQL queries with fairly complex query sets. It looks like the query is being built with an unquoted string representation of the UUID. I suspect that the UUID should at least be quoted, if not a binary string.
The particular issue here involves a where clause with a list of uuids (ie where(id: uuid_array)
) - so possibly the array of UUIDs in the where clause is being output as to_s
rather than than the raw
output
Sample problem (bad SQL is in where clause):
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column '031cb9ba' in 'where clause':
SELECT
COUNT(*) AS count_all,
state_id AS state_id,
entry_from AS entry_from
FROM `state_periods`
INNER JOIN `states` ON `states`.`id` = `state_periods`.`state_id`
INNER JOIN `state_machines` ON `state_machines`.`id` = `states`.`state_machine_id`
WHERE (states.state_machine_id in (031cb9ba-b3dd-44b3-b1a1-09906540274b,eac88a3c-af18-4dfa-9707-25f2ac469d50))
GROUP BY `state_periods`.`state_id`, `state_periods`.`entry_from`
Hi,
I'm getting this error when running rake db:migrate
. My migration looks like this
class CreateArticles < ActiveRecord::Migration
def change
create_table :articles do |t|
t.uuid :uuid, :primary_key => false
t.string :title
t.text :text
t.timestamps null: false
end
add_index :articles, :id
end
end
and my model class is
require 'activeuuid'
class Article < ActiveRecord::Base
include ActiveUUID::UUID
end
If i don't set the :id
as primary key, the db is migrated correctly but the id is not generated using UUID.
what did I do wrong ?
There is currently an issue on rails 4.2 and mysql where children of a has_one relationship are having their UUID updated at the same time as the parent. The strange thing is that a mysql UPDATE
query is run overwriting the exact same data.
To replicate the issue I have created a dummy app with a failing test suite. In the example we have Owner has_one Dog which does not use activeuuid and displays the rails default behaviour. We also have User has_one Car which does use uuid.
If we first take Owner has_one Dog we can confirm that the Dog
record is never touched when updating the Owner
.
o = Owner.create
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO `owners` (`created_at`, `updated_at`) VALUES ('2015-06-03 21:05:23', '2015-06-03 21:05:23')
(0.2ms) COMMIT
=> #<Owner id: 1, name: nil, created_at: "2015-06-03 21:05:23", updated_at: "2015-06-03 21:05:23">
irb(main):005:0> o.create_dog
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO `dogs` (`owner_id`, `created_at`, `updated_at`) VALUES (1, '2015-06-03 21:05:27', '2015-06-03 21:05:27')
(0.3ms) COMMIT
Dog Load (0.2ms) SELECT `dogs`.* FROM `dogs` WHERE `dogs`.`owner_id` = 1 LIMIT 1
=> #<Dog id: 1, owner_id: 1, created_at: "2015-06-03 21:05:27", updated_at: "2015-06-03 21:05:27">
irb(main):006:0> o.update name: 'George'
(0.2ms) BEGIN
SQL (0.5ms) UPDATE `owners` SET `name` = 'George', `updated_at` = '2015-06-03 21:05:34' WHERE `owners`.`id` = 1
(6.4ms) COMMIT
=> true
Next lets try again with User has_one Car which does use activeuuid. Our Car
record should not be touched when updating the Owner
.
u = User.create
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO `users` (`id`, `created_at`, `updated_at`) VALUES (x'69704d2f29cd4bc484fa9545b8c54a55', '2015-06-03 21:04:54', '2015-06-03 21:04:54')
(0.2ms) COMMIT
=> #<User id: #<UUID:0x3ff7ae5768f0 UUID:69704d2f-29cd-4bc4-84fa-9545b8c54a55>, name: nil, created_at: "2015-06-03 21:04:54", updated_at: "2015-06-03 21:04:54">
irb(main):002:0> c = u.create_car
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO `cars` (`id`, `user_id`, `created_at`, `updated_at`) VALUES (x'f92659de32814c7f8e05d95bc13fab72', x'69704d2f29cd4bc484fa9545b8c54a55', '2015-06-03 21:05:03', '2015-06-03 21:05:03')
(0.3ms) COMMIT
Car Load (0.2ms) SELECT `cars`.* FROM `cars` WHERE `cars`.`user_id` = x'69704d2f29cd4bc484fa9545b8c54a55' LIMIT 1
=> #<Car id: #<UUID:0x3ff7adb9276c UUID:f92659de-3281-4c7f-8e05-d95bc13fab72>, user_id: #<UUID:0x3ff7ae5768f0 UUID:69704d2f-29cd-4bc4-84fa-9545b8c54a55>, make: nil, created_at: "2015-06-03 21:05:03", updated_at: "2015-06-03 21:05:03">
irb(main):003:0> u.update name: 'George'
(0.2ms) BEGIN
SQL (0.4ms) UPDATE `users` SET `id` = x'69704d2f29cd4bc484fa9545b8c54a55', `name` = 'George', `updated_at` = '2015-06-03 21:05:15' WHERE `users`.`id` = x'69704d2f29cd4bc484fa9545b8c54a55'
######################################
SQL (0.2ms) UPDATE `cars` SET `id` = x'f92659de32814c7f8e05d95bc13fab72', `user_id` = x'69704d2f29cd4bc484fa9545b8c54a55', `updated_at` = '2015-06-03 21:05:15' WHERE `cars`.`id` = x'f92659de32814c7f8e05d95bc13fab72'
######################################
(6.2ms) COMMIT
=> true
From the logs we can see that the Car
had its id
and user_id
updated along with the timestamps.
Has anyone else experienced this problem or come up with a fix?
Is there some trick to making this work outside of Rails?
I've tried many permutations of load order and explicit calling "ActiveUUID::Patches.apply!".
All to no avail.
The uuid's keep coming out of MySQL looking like:
"\x9F\x03\xBCS@$M\x05\x91t\xE3c\xA3#\xDC\xE2"
And when I attempt to save into MySQL I get:
ActiveRecord::StatementInvalid: Mysql2::Error: Data too long for column 'guid' at row 1: INSERT INTO things
(guid
) VALUES (x'38306334366136352d646238622d343663332d613135322d363435646231643631613563')
What am I doing wrong here?
My migrations are not creating the correct entires in my schema.rb file.
See my example migration:
create_table :my_table, { id: false } do |t|
t.uuid :id, primary_key: true
t.timestamps
end
And this generates an entry in my schema.rb, without my uuid primary key
create_table "my_table", force: :cascade do |t|
t.datetime "created_at"
t.datetime "updated_at"
end
I then need to manually change my shema.rb to the following in order for it to work correctly:
create_table "my_table", id: false, force: :cascade do |t|
t.uuid "id", limit: 16, primary_key: true
t.datetime "created_at"
t.datetime "updated_at"
end
Is there something existing I can enter into my migrations to get this to work?
Either undocumented, or doesn't work - can't tell.
Sample:
add_column :some_table, :some_field, :uuid
Since there also appears to be no way to create a MySQL BINARY(16) with add_column (:binary creates a BLOB), have to resort to raw SQL migrations. Would prefer not to.
pretty please 😻
I believe below code must be added to your gem, because whenever I did something like post.comments.empty? I got a TypeError: Cannot visit UUIDTools::UUID.
module Arel
module Visitors
class DepthFirst < Arel::Visitors::Visitor
def visit_UUIDTools_UUID(o)
o.quoted_id
end
end
end
end
With Rails 3.2.17, If parent model and children model are both uuid model.
Child.where(parent_id: xxx).find(SecureRandom.hex)
gives correct RecordNotFound error
However,
parent.children.find(SecureRandom.hex)
gives TypeError.
I had to fix it with a monkey-patch
module Arel
class SelectManager < Arel::TreeManager
def where_sql
return if @ctx.wheres.empty?
viz = Visitors::WhereSql.new @engine.connection
Nodes::SqlLiteral.new viz.accept @ctx
rescue TypeError => e
nil
end
end
end
This works but is not clean. I also see that this issue does not apply to Rails 4. I tried to submit a PR for activeuuid but I realize it is using activerecord v4 in the spec. What is the guideline on this type of error. Will you guys try to have your code compatible with Rails 3.2.x?
Failure/Error: specify { parent.uuid_articles.find(SecureRandom.hex.to_s).should == article }
TypeError:
Cannot visit UUIDTools::UUID
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/visitor.rb:25:in `rescue in visit'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/visitor.rb:19:in `visit'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/to_sql.rb:407:in `visit_Arel_Nodes_Equality'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/visitor.rb:19:in `visit'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/to_sql.rb:389:in `block in visit_Arel_Nodes_And'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/to_sql.rb:389:in `map'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/to_sql.rb:389:in `visit_Arel_Nodes_And'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/visitor.rb:19:in `visit'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/where_sql.rb:5:in `block in visit_Arel_Nodes_SelectCore'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/where_sql.rb:5:in `map'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/where_sql.rb:5:in `visit_Arel_Nodes_SelectCore'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/visitor.rb:19:in `visit'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/visitor.rb:5:in `accept'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/visitors/to_sql.rb:19:in `accept'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/arel-3.0.3/lib/arel/select_manager.rb:177:in `where_sql'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.17/lib/active_record/relation/finder_methods.rb:342:in `find_one'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.17/lib/active_record/relation/finder_methods.rb:315:in `find_with_ids'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.17/lib/active_record/relation/finder_methods.rb:107:in `find'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.17/lib/active_record/associations/collection_association.rb:95:in `find'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.2.17/lib/active_record/associations/collection_proxy.rb:46:in `find'
# ./spec/lib/activerecord_spec.rb:147:in `block (4 levels) in <top (required)>'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_exec'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_eval_with_args'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example.rb:116:in `block in run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example.rb:248:in `with_around_each_hooks'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example.rb:113:in `run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:515:in `block in run_examples'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:511:in `map'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:511:in `run_examples'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:496:in `run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:497:in `block in run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:497:in `map'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:497:in `run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:497:in `block in run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:497:in `map'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:497:in `run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/command_line.rb:24:in `block (2 levels) in run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/command_line.rb:24:in `map'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/command_line.rb:24:in `block in run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/reporter.rb:58:in `report'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/command_line.rb:21:in `run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/runner.rb:103:in `run'
# /Users/ben/.rvm/gems/ruby-1.9.3-p551/gems/rspec-core-2.99.2/lib/rspec/core/runner.rb:17:in `block in autorun'
Activeuuid defaults the primary key of new records to a UUID with a value of "00000000-0000-0000-0000-000000000000" whereas ActiveRecord expects all keys of new records to be nil.
This breaks accepts_nested_attributes_for because, seeing the non-nil UUID, ActiveRecord tries to find the non-existent record (with "00000000-0000-0000-0000-000000000000" as an ID).
I'm trying to use activeuuid with rails 4.0.0. I have created migration according to example, then run it and got a error: "undefined method `adapter_name' for nil:NilClass".
Then I checke stacktrace and found next:
undefined method adapter_name' for nil:NilClass at /activeuuid-0.4.0/lib/activeuuid/patches.rb:11:in
block in uuid'
/activeuuid-0.4.0/lib/activeuuid/patches.rb:10:in each' /activeuuid-0.4.0/lib/activeuuid/patches.rb:10:in
uuid'
When I opened patches.rb file I have found next row:
type = @base.adapter_name.downcase == 'postgresql' ? 'uuid' : 'binary(16)'
It seems like @base variable have not been initialized and I have no idea whre it from! Since I'm working with mysql, I just commented this row and inserted new one:
type = 'binary(16)'
But this is just a ugly hack, which should be fixed.
In a clean Rails 5.0.0.beta1 project, adding
gem 'activeuuid'
to the Gemfile
causes the following failure to start the server.
$ bundle exec rails s
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from require at /var/lib/gems/2.2.0/gems/bundler-1.11.2/lib/bundler/runtime.rb:77)
/var/lib/gems/2.2.0/gems/bundler-1.11.2/lib/bundler/runtime.rb:80:in `rescue in block (2 levels) in require': There was an error while trying to load the gem 'activeuuid'. (Bundler::GemRequireError)
Given a migration such as:
class CreateSomeObject < ActiveRecord::Migration
def change
create_table :some_objects, :id => false do |t|
t.uuid :id, :primary_key => true
t.string :name
end
end
end
You get in an entry in schema.rb such as:
create_table "some_objects", :force => true do |t|
t.string "name"
end
Notice it looks EXACTLY like a normal table with an ID. I believe, because of this, your sqlite test database does not use UUIDs:
class SomeObjectTest < ActiveSupport::TestCase
test "Has a UUID primary key" do
o = SomeObject.create(:name => "FooBar")
assert_equal UUIDTools::UUID, o.id.class
end
end
gets:
1) Failure:
test_Has_a_UUID_primary_key(SomeObjectTest) [/Users/patrick/src/someobjecttest/test/unit/someobject_test.rb:6]:
<UUIDTools::UUID> expected but was
<Fixnum>.
If I edit the schema.rb file to look like:
create_table :some_objects, :id => false do |t|
t.uuid :id, :primary_key => true
t.string :name
end
The same test now outputs:
Finished tests in 0.273841s, 3.6518 tests/s, 3.6518 assertions/s.
1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
However, clearly, editing the schema.rb file by hand after every migration is not an option.
Is this a bug? Something I am missing?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.