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

Cleanup - Specify Spree:: namespace in all Product calls #1615

Merged
merged 4 commits into from
Dec 15, 2016

Conversation

fylooi
Copy link
Contributor

@fylooi fylooi commented Nov 25, 2016

Some calls to Product are not namespaced with Spree::. This leads to a collision if the including application has an existing Product model defined.

@flyfy1
Copy link
Contributor

flyfy1 commented Nov 25, 2016

I don't quite understand.. if we have code like:

class Product
  def m
    puts "Product::m"
  end
end


module Spree
  class Product
    def m
      puts "Spree::Product::m"
    end
  end

  class Caller
    def call_product
      Product.new.m
    end
  end
end

Spree::Caller.new.call_product

shouldn't the Spree::Product to be called by the Caller by default?

@fylooi
Copy link
Contributor Author

fylooi commented Nov 25, 2016

@flyfy1
Yes, that would be the case if the constants were all in one file.
In this case, it calls my preexisting Product model. Suspect Rails autoloading might have something to do with it. Specifying the namespace results in correct behaviour and aligns with the rest of the code.

@cbrunsdon
Copy link
Contributor

I'm with @flyfy1 on this one in that I'm not sure under what circumstances the wrong product will be called, could it be something like code you've copy-pasted into a decorator that is causing the issue? I tried a local repo and couldn't recreate the undesired behavior.

@fylooi
Copy link
Contributor Author

fylooi commented Nov 25, 2016

Hmm. Moved past that code and can't dig up the point of reproduction. I'll reopen this PR if I can get a handle on it.

@fylooi fylooi closed this Nov 25, 2016
@flyfy1
Copy link
Contributor

flyfy1 commented Dec 9, 2016

@fylooi When I was reading Rails Docs upon module loading today, at section 6.2, it mentioned sth below (cannot copy with style so I just include the screenshot):

image

I think it's something related to your issue (and which also means, seems to make ur pull request valid)

@fylooi
Copy link
Contributor Author

fylooi commented Dec 9, 2016

@flyfy1
The problem is actually a combination of Rails autoloading and development code reloading. Have experienced a couple of other model name conflicts but still unable to reproduce this in a test app. Disabling Spring and setting config.eager_load = true in development appears to prevent these conflicts, with a slightly degraded dev experience.

Ensuring that all models in controllers are consistently invoked with the Spree:: namespace should solve this. The current code is a mix of namespaced and non-namespaced model calls.

If you guys are okay with this, I can do the changes and update this PR.

@fylooi fylooi reopened this Dec 9, 2016
@flyfy1
Copy link
Contributor

flyfy1 commented Dec 9, 2016

@fylooi I haven't looked through the documentation yet.. nor do I sure if u should continue with the PR. probably need comments from the core team. Meanwhile, I think it's definitely helpful to create a sample App and surface the problem..

Copy link
Member

@tvdeyen tvdeyen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with adding the model module namespace.

It has no downsides for us having them (besides bytecount ^_^).

I think it even makes the code better understandable. Not everybody is super aware of Ruby/Rails module constant lookup. And if this helps avoiding super hard to track down bugs, even better.

From me 👍

@@ -173,7 +173,7 @@ def self.property_conditions(property)

# Can't use add_search_scope for this as it needs a default argument
def self.available(available_on = nil, currency = nil)
Spree::Deprecation.warn("The second currency argument on Product.available has no effect, and is deprecated", caller) if currency
Spree::Deprecation.warn("The second currency argument on Spree::Product.available has no effect, and is deprecated", caller) if currency
joins(master: :prices).where("#{Product.quoted_table_name}.available_on <= ?", available_on || Time.current)
Copy link
Member

@tvdeyen tvdeyen Dec 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we have one Product missing its module namespace

@fylooi
Copy link
Contributor Author

fylooi commented Dec 14, 2016

Updated the PR to cover all model invocations in controllers and models.

@mamhoff
Copy link
Contributor

mamhoff commented Dec 14, 2016

I'm also fine with this. Quoting the Zen of Python:

Namespaces are one honking great idea -- let's do more of those!

;)

Copy link
Contributor

@cbrunsdon cbrunsdon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good by me, thanks for seeing this through

@jhawthorn
Copy link
Contributor

Thank you

@fylooi
Copy link
Contributor Author

fylooi commented Feb 24, 2017

Managed to reproduce one case. Documenting the steps for reference.

This is as of v1.4.

Assuming you have a Country model defined in your host application:

  1. Add a reference to Country in an around_action in ApplicationController. yield after calling a method on Country
  2. Visit CustomerDetailsController#edit
      def edit
          country_id = Country.default.id
          @order.build_bill_address(country_id: country_id) if @order.bill_address.nil?
          @order.build_ship_address(country_id: country_id) if @order.ship_address.nil?

          @order.bill_address.country_id = country_id if @order.bill_address.country.nil?
          @order.ship_address.country_id = country_id if @order.ship_address.country.nil?
        end

The Country.default.id call will call the host Country class, and will fail if the host class doesn't have default defined.

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

Successfully merging this pull request may close these issues.

6 participants