1

I have a model Artboard and a model Group that has a many to many relationship through a table called ArtboardsGroups that has attributes for an x and y value pertaining to the relationship

class Artboard < ApplicationRecord
  has_many :artboards_groups, dependent: :destroy
  has_many :groups, -> { select("groups.id as id, groups.name as name, artboards_groups.x as x, artboards_groups.y as y, artboards_groups.index as index, artboards_groups.r as r") }, through: :artboards_groups
end

class ArtboardsGroup < ApplicationRecord
  belongs_to :artboard
  belongs_to :group
end

class Group < ApplicationRecord
  has_many :artboards_groups, dependent: :destroy
  has_many :artboards, through: :artboards_group
end

The model works perfectly fine when I try to access it by itself but when I try to select groups through an artboard and access the 'y' attribute I get a error that it is a private method

NoMethodError: private method `y' called for #<Group id: 5, name: nil>

According to this thread (From over 10 years ago) it is because there is a private method in ActiveRecord::Base called 'y' /lib/ruby/2.5.0/psych/y.rb which is from a gem called psych that is a yaml parser

I don't want to change the attribute name for 'y' considering it is referencing a coordinate system and (x,y) is the standard for coordinates. Is there any other way to deal with this?

David
  • 377
  • 5
  • 14
  • 1
    what happens if you call `send(:y)` instead or `.y`? – arieljuod Nov 07 '19 at 20:57
  • 1
    You can configure your Group model to delegate the `y` method to it's associated ArtboardsGroup too https://apidock.com/rails/Module/delegate – arieljuod Nov 07 '19 at 21:00
  • 2
    From what I can see its not actually from ActiveRecord. Try `Group.new.method(:y).source_location`. I'm getting `["/Users/max/.rbenv/versions/2.6.3/lib/ruby/2.6.0/psych/y.rb", 5]` – max Nov 07 '19 at 21:01
  • @arieljuod I get a NoMethodError: undefined method `end_line=' for nil:NilClass – David Nov 07 '19 at 21:02
  • @max you're right I made an edit to the op – David Nov 07 '19 at 21:10

1 Answers1

5
class Group < ApplicationRecord
  undef :y
  has_many :artboards_groups, dependent: :destroy
  has_many :artboards, through: :artboards_group
end
irb(main):001:0> g = Group.new(y: 1, x: 2)
=> #<Group id: nil, x: 2.0, y: 1.0, created_at: nil, updated_at: nil>
irb(main):002:0> g.y
=> 1.0

The :y method is most likely from the yaml parser psych which monkeypatches it into the Kernel class.

max
  • 96,212
  • 14
  • 104
  • 165
  • 1
    I haven't done any more extensive testing with this but I doubt ActiveRecord uses `y` internally somewhere. – max Nov 07 '19 at 21:16