This commit adds support for using primary keys of type UUID in PostgreSQL: https://github.com/rails/rails/commit/bc8ebefe9825dbff2cffa29ff015a1e7a31f9812 This is *awesome*, however, I''m not sure I understand the intention with the default setting. Right now, it''s doing: def primary_key(name, type = :primary_key, options = {}) return super unless type == :uuid options[:default] ||= ''uuid_generate_v4()'' options[:primary_key] = true column name, type, options end I see two issues with this implementation: 1. The uuid_generate_v4()function depends on a module (uuid-ossp), which is not always included in PostgreSQL distributions and which itself requires an external library (which seems to often have issues compiling, at least from some initial searching). The module also must be applied to each database individually (unless the user has already added it to their system template). So, unless a user has a) installed a pg distribution which includes this module, b) installed external library, c) set up their system template to always include this module in new databases, running rake db:migrate in a fresh checkout will always fail. For those reasons, it seems like an inappropriate default setting. 2. So far as I can tell, there is no possible way to override this value, short a) specifying a different uuid function from the uuid-ossp module, or b) having installed another UUID library and specifying a function from that. You cannot specify default: 0 or default: ''NULL'', of any value other than a valid UUID, because pg does not consider them valid entries for the type. default: nil will fail, because the method above will override it. You can pass an actual uuid as a string ( default: "eddad8c1-43ad-4851-944a-a6205d266e5d"), however this seems pretty non-standard. To me, it seems that the ideal is actually to default to generating the UUID in Rails (via SecureRandom.uuid), however I''m not entirely sure how to do this while still allowing for database-level defaults. Also, I wasn''t able to find any documentation on this anywhere, so either I''m missing it, or we need to add it. I was going to file a github issue, but I wanted to check on here first to see if I was missing something or if anyone else had ideas/thoughts/insights. Thanks, Chad -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
Aaron Patterson
2013-Apr-25 22:25 UTC
Re: Implementation for PostgreSQL UUID Primary Key Default
On Wed, Apr 24, 2013 at 02:32:04PM -0700, Chad Moone wrote:> This commit adds support for using primary keys of type UUID in > PostgreSQL: https://github.com/rails/rails/commit/bc8ebefe9825dbff2cffa29ff015a1e7a31f9812 > > This is *awesome*, however, I''m not sure I understand the intention with > the default setting. Right now, it''s doing: > > def primary_key(name, type = :primary_key, options = {}) > return super unless type == :uuid > options[:default] ||= ''uuid_generate_v4()'' > options[:primary_key] = true > column name, type, options > end > > I see two issues with this implementation: > > 1. The uuid_generate_v4()function depends on a module (uuid-ossp), which > is not always included in PostgreSQL distributions and which itself > requires an external library (which seems to often have issues compiling, > at least from some initial searching). The module also must be applied to > each database individually (unless the user has already added it to their > system template). So, unless a user has a) installed a pg distribution > which includes this module, b) installed external library, c) set up their > system template to always include this module in new databases, running > rake db:migrate in a fresh checkout will always fail. For those reasons, > it seems like an inappropriate default setting.You need to add "enable_extension ''uuid-ossp''" to your migrations so that when people migrate, the extension is loaded. Same with HStore.> 2. So far as I can tell, there is no possible way to override this > value, short a) specifying a different uuid function from the uuid-ossp > module, or b) having installed another UUID library and specifying a > function from that. You cannot specify default: 0 or default: ''NULL'', > of any value other than a valid UUID, because pg does not consider them > valid entries for the type. default: nil will fail, because the method > above will override it. You can pass an actual uuid as a string ( > default: "eddad8c1-43ad-4851-944a-a6205d266e5d"), however this seems > pretty non-standard.We can fix it so that "nil" is a valid setting. Can you write a patch?> To me, it seems that the ideal is actually to default to generating the > UUID in Rails (via SecureRandom.uuid), however I''m not entirely sure how to > do this while still allowing for database-level defaults.Bingo. Using "uuid-ossp" is the cleanest solution I''ve found. If we fix the "nil" case, you could add a "before_save" hook that sets the id using `SecureRandom.uuid`, but it seems hacky, and you''d have to add the code to every model that wanted it.> Also, I wasn''t able to find any documentation on this anywhere, so either > I''m missing it, or we need to add it.It needs to be added. ;-) -- Aaron Patterson http://tenderlovemaking.com/ -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
Chad Moone
2013-Apr-26 00:22 UTC
Re: Implementation for PostgreSQL UUID Primary Key Default
Thanks for the feedback! WRT uuid-ossp, I was originally using Postgres.app (http://postgresapp.com), which it seems doesn''t ship with this module (https://github.com/mattt/PostgresApp/issues/39) by default. I was able to get it working by switching to the homebrew recipe. I think Postgres.app is fairly popular for development/testing (Heroku recommends it (https://devcenter.heroku.com/articles/heroku-postgresql#local-setup)), so this may be a common issue. That said, I think they should be able to fix it for OS X 10.8 if homebrew can make it work, and if we can at least allow nil, that will make it possible until then. And, yeah, I just set up a UUID concern with a before_create hook. In the end, though, I just switched to homebrew pg with uuid-ossp instead :P I hadn''t seen enable_extension yet, thanks for the tip. I think I pretty much have the patch to accept nil as a valid setting, but I will have to double-check the tests and try to add some documentation before submitting a pull request. --Chad On Thursday, April 25, 2013 at 6:25 PM, Aaron Patterson wrote:> On Wed, Apr 24, 2013 at 02:32:04PM -0700, Chad Moone wrote: > > This commit adds support for using primary keys of type UUID in > > PostgreSQL: https://github.com/rails/rails/commit/bc8ebefe9825dbff2cffa29ff015a1e7a31f9812 > > > > This is *awesome*, however, I''m not sure I understand the intention with > > the default setting. Right now, it''s doing: > > > > def primary_key(name, type = :primary_key, options = {}) > > return super unless type == :uuid > > options[:default] ||= ''uuid_generate_v4()'' > > options[:primary_key] = true > > column name, type, options > > end > > > > I see two issues with this implementation: > > > > 1. The uuid_generate_v4()function depends on a module (uuid-ossp), which > > is not always included in PostgreSQL distributions and which itself > > requires an external library (which seems to often have issues compiling, > > at least from some initial searching). The module also must be applied to > > each database individually (unless the user has already added it to their > > system template). So, unless a user has a) installed a pg distribution > > which includes this module, b) installed external library, c) set up their > > system template to always include this module in new databases, running > > rake db:migrate in a fresh checkout will always fail. For those reasons, > > it seems like an inappropriate default setting. > > > > > You need to add "enable_extension ''uuid-ossp''" to your migrations so > that when people migrate, the extension is loaded. Same with HStore. > > > 2. So far as I can tell, there is no possible way to override this > > value, short a) specifying a different uuid function from the uuid-ossp > > module, or b) having installed another UUID library and specifying a > > function from that. You cannot specify default: 0 or default: ''NULL'', > > of any value other than a valid UUID, because pg does not consider them > > valid entries for the type. default: nil will fail, because the method > > above will override it. You can pass an actual uuid as a string ( > > default: "eddad8c1-43ad-4851-944a-a6205d266e5d"), however this seems > > pretty non-standard. > > > > > We can fix it so that "nil" is a valid setting. Can you write a patch? > > > To me, it seems that the ideal is actually to default to generating the > > UUID in Rails (via SecureRandom.uuid), however I''m not entirely sure how to > > do this while still allowing for database-level defaults. > > > > > Bingo. Using "uuid-ossp" is the cleanest solution I''ve found. If we > fix the "nil" case, you could add a "before_save" hook that sets the id > using `SecureRandom.uuid`, but it seems hacky, and you''d have to add the > code to every model that wanted it. > > > Also, I wasn''t able to find any documentation on this anywhere, so either > > I''m missing it, or we need to add it. > > > > > It needs to be added. ;-) > > -- > Aaron Patterson > http://tenderlovemaking.com/ > > -- > You received this message because you are subscribed to a topic in the Google Groups "Ruby on Rails: Core" group. > To unsubscribe from this topic, visit https://groups.google.com/d/topic/rubyonrails-core/PaQldWtV4O8/unsubscribe?hl=en. > To unsubscribe from this group and all its topics, send an email to rubyonrails-core+unsubscribe@googlegroups.com (mailto:rubyonrails-core+unsubscribe@googlegroups.com). > To post to this group, send email to rubyonrails-core@googlegroups.com (mailto:rubyonrails-core@googlegroups.com). > Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. > For more options, visit https://groups.google.com/groups/opt_out. > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
Chad Moone
2013-May-01 21:47 UTC
Re: Implementation for PostgreSQL UUID Primary Key Default
Aaron—you''ll probably see this since I tagged you in it, but I got a patch submitted here: https://github.com/rails/rails/pull/10404 Just let me know if you see anything that I should change. --Chad On Thursday, April 25, 2013 at 8:22 PM, Chad Moone wrote:> Thanks for the feedback! > > WRT uuid-ossp, I was originally using Postgres.app (http://postgresapp.com), which it seems doesn''t ship with this module (https://github.com/mattt/PostgresApp/issues/39) by default. I was able to get it working by switching to the homebrew recipe. I think Postgres.app is fairly popular for development/testing (Heroku recommends it (https://devcenter.heroku.com/articles/heroku-postgresql#local-setup)), so this may be a common issue. That said, I think they should be able to fix it for OS X 10.8 if homebrew can make it work, and if we can at least allow nil, that will make it possible until then. > > And, yeah, I just set up a UUID concern with a before_create hook. In the end, though, I just switched to homebrew pg with uuid-ossp instead :P > > I hadn''t seen enable_extension yet, thanks for the tip. > > I think I pretty much have the patch to accept nil as a valid setting, but I will have to double-check the tests and try to add some documentation before submitting a pull request. > > --Chad > > > On Thursday, April 25, 2013 at 6:25 PM, Aaron Patterson wrote: > > > On Wed, Apr 24, 2013 at 02:32:04PM -0700, Chad Moone wrote: > > > This commit adds support for using primary keys of type UUID in > > > PostgreSQL: https://github.com/rails/rails/commit/bc8ebefe9825dbff2cffa29ff015a1e7a31f9812 > > > > > > This is *awesome*, however, I''m not sure I understand the intention with > > > the default setting. Right now, it''s doing: > > > > > > def primary_key(name, type = :primary_key, options = {}) > > > return super unless type == :uuid > > > options[:default] ||= ''uuid_generate_v4()'' > > > options[:primary_key] = true > > > column name, type, options > > > end > > > > > > I see two issues with this implementation: > > > > > > 1. The uuid_generate_v4()function depends on a module (uuid-ossp), which > > > is not always included in PostgreSQL distributions and which itself > > > requires an external library (which seems to often have issues compiling, > > > at least from some initial searching). The module also must be applied to > > > each database individually (unless the user has already added it to their > > > system template). So, unless a user has a) installed a pg distribution > > > which includes this module, b) installed external library, c) set up their > > > system template to always include this module in new databases, running > > > rake db:migrate in a fresh checkout will always fail. For those reasons, > > > it seems like an inappropriate default setting. > > > > > > > > > You need to add "enable_extension ''uuid-ossp''" to your migrations so > > that when people migrate, the extension is loaded. Same with HStore. > > > > > 2. So far as I can tell, there is no possible way to override this > > > value, short a) specifying a different uuid function from the uuid-ossp > > > module, or b) having installed another UUID library and specifying a > > > function from that. You cannot specify default: 0 or default: ''NULL'', > > > of any value other than a valid UUID, because pg does not consider them > > > valid entries for the type. default: nil will fail, because the method > > > above will override it. You can pass an actual uuid as a string ( > > > default: "eddad8c1-43ad-4851-944a-a6205d266e5d"), however this seems > > > pretty non-standard. > > > > > > > > > We can fix it so that "nil" is a valid setting. Can you write a patch? > > > > > To me, it seems that the ideal is actually to default to generating the > > > UUID in Rails (via SecureRandom.uuid), however I''m not entirely sure how to > > > do this while still allowing for database-level defaults. > > > > > > > > > Bingo. Using "uuid-ossp" is the cleanest solution I''ve found. If we > > fix the "nil" case, you could add a "before_save" hook that sets the id > > using `SecureRandom.uuid`, but it seems hacky, and you''d have to add the > > code to every model that wanted it. > > > > > Also, I wasn''t able to find any documentation on this anywhere, so either > > > I''m missing it, or we need to add it. > > > > > > > > > It needs to be added. ;-) > > > > -- > > Aaron Patterson > > http://tenderlovemaking.com/ > > > > -- > > You received this message because you are subscribed to a topic in the Google Groups "Ruby on Rails: Core" group. > > To unsubscribe from this topic, visit https://groups.google.com/d/topic/rubyonrails-core/PaQldWtV4O8/unsubscribe?hl=en. > > To unsubscribe from this group and all its topics, send an email to rubyonrails-core+unsubscribe@googlegroups.com (mailto:rubyonrails-core+unsubscribe@googlegroups.com). > > To post to this group, send email to rubyonrails-core@googlegroups.com (mailto:rubyonrails-core@googlegroups.com). > > Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. > > For more options, visit https://groups.google.com/groups/opt_out. > > > > > > > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.