Help converting line in Concern

Hi,

I’ve identified a selection of code that i’d like to apply to two other models in my app.

I’ve also discovered that a Concern looks to be the right way of achieving this and all is working nicely, apart from the fact i’m unsure how to convert the line below into a line that is valid inside a concern. (eg, does not reference my Coaster model itself and will refer to the model that the concern is a part of).

scope :originals, -> { ridden.where('original_version_id = coasters.id') }

I did try the below:

scope :originals, -> { ridden.where('original_version_id = ' + self.to_s.downcase.pluralize + '.id') }

but I get the following error:

Coaster.originals Coaster Load (13.0ms) SELECT “coasters”.* FROM “coasters” WHERE “coasters”.“type” IS NULL AND (original_version_id = #coaster::activerecord_relation:0x000000010b067ed8s.id) (Object doesn’t support #inspect)

Help would be appreciated!

Thanks!

1 Like

You are calling to_s in a relation, which is causing the problem. Try this:

included do
  scope :originals, -> { ridden.where('original_version_id = ' + self.table_name + '.id')
end

@brenogazzola Thankyou!

May I ask why the .to_s was causing an issue. I tried that as I thought it would concatenate all 3 strings together?

1 Like

In this case self is an instance of ActiveRecord::Relation not the class which is using the concern (which is what I think you were expecting).

When you call to_s on it instead of getting Coaster, you get the default implementation for a generic ruby object, which is class name + memory address. In this case Coaster::ActiveRecord::Relation:0x000000010b067ed8 I think.

1 Like

Yeh, I was expecting self to equal “Coaster”.

Why does it return an ActiveRecord::Relation? Apologies for the questions. I just like to fill the gaps in my knowledge to improve my understanding.

Scopes can be chained. For example:

class Product
  scope :available, -> { where(available: true) }
  scope :sold_by, -> (company){ where(company: company )}
end

Can be used like this:

Product.available.sold_by(@company)

If the self inside each scope was the class, then calling where on it would overwrite the previous scope. That’s why self is always a relation with all the previous scopes and where clauses applied.

1 Like