Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

model name prefix is not always unique #231

Closed
khiav223577 opened this issue Aug 30, 2018 · 10 comments
Closed

model name prefix is not always unique #231

khiav223577 opened this issue Aug 30, 2018 · 10 comments

Comments

@khiav223577
Copy link

The document here says:

Redis::Objects automatically creates keys that are unique to each object, in the format:
model_name:id:field_name

But if two models in different namespace have same name. The generated key will be the same.
For example:

class Group < ActiveRecord::Base
  include Redis::Objects
  counter :test_counter
end

class XXX::Group < ActiveRecord::Base
  include Redis::Objects
  counter :test_counter
end
Group.first.test_counter.key
# => "group:1:test_counter"

XXX::Group.first.test_counter.key
# => "group:1:test_counter"
@nateware
Copy link
Owner

nateware commented Oct 7, 2018

Nested class names are a problem because I stole the original code from Sinatra, and unfortunately I didn't notice that it cropped the class down past the final ::. Sorry. I am open to a new option something like full_prefix: true but unfortunately we can't change the code since that would be backwards incompatible.

@nateware
Copy link
Owner

I finally have an idea. If we bumped the version to 2.0.0, we could issue a warning message in the model_prefix method if we found an :: that we are now prefixing the full method name. And/or we could provide a global setting called long_namespacing where if you said it to false it would do the old shortened version. CC @tmsrjs

@artinboghosian
Copy link
Contributor

artinboghosian commented Nov 16, 2019

@nateware I think you might want to provide this as an option at the object level as well so that if you were using redis objects for a namespaced class upgrading wouldnt break existing code. Meaning you can turn on new behavior and get benefits of namespaced keys without breaking currently functioning code in your app.

@nateware
Copy link
Owner

nateware commented Nov 16, 2019 via email

@artinboghosian
Copy link
Contributor

@nateware class level makes sense. Although it's probably an edge case this still wouldn't support existing namespaced classes with a mixture of new and old functionality. Say you add redis type after upgrading and want new definition to use namespaced keys even though existing ones wouldn't without migrating. Maybe we don't care about this but thought it might be worth mentioning. If we did care than it might make sense to add option at the instance level when defining new redis types on class.

@Dounx
Copy link

Dounx commented Nov 19, 2019

Like @khiav223577 said, developer barely cannot notice that models in different namespace could have same name. We set redis_prefix in every included class, If the new one does not know to set this, there will be problems. Still think that using model_name by default is not very reasonable.

@Dounx
Copy link

Dounx commented Dec 2, 2019

By the way, why redis_prefix should use sub and gsub?

def redis_prefix(klass = self) #:nodoc:
  @redis_prefix ||= klass.name.to_s.
    sub(%r{(.*::)}, '').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    downcase
 end

Can we just change it as follow:

def redis_prefix(klass = self) #:nodoc:
  @redis_prefix ||= klass.name.to_s.
    gsub(/::/, '_').
    downcase
end

@nateware
Copy link
Owner

Update on the design to fix this longstanding issue. The new code for redis_prefix looks like so:

def modern_redis_prefix(klass = self) #:nodoc:
  klass.name.to_s.
    gsub(/::/, '__').                     # Nested::Class => Nested__Class
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). # ClassName => Class_Name
    gsub(/([a-z\d])([A-Z])/,'\1_\2').     # className => class_Name
    downcase
end

The reason I chose __ as a substitute for :: was to ensure these don't conflict:

class Group::PlayerType  # group__player_type
class GroupPlayer::Type  # group_player__type

To cause the legacy key naming behavior, there is a new flag redis_legacy_naming:

class MyClass
  include Redis::Objects
  self.redis_legacy_naming = true

A warning will be emitted if redis-objects detects that your class name will change.

This is being developed in the long_namespace branch for those interested in following along.

@nateware
Copy link
Owner

This has been fixed in 2.0.0.alpha and pushed to rubygems

@nateware
Copy link
Owner

Also fixed in 2.0.0.beta which I just pushed to rubygems

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants