[Change Request - warning, controversial] Rename "belongs_to" to what it actually is

50 views
Skip to first unread message

Richard McSharry

unread,
Sep 24, 2016, 10:38:36 AM9/24/16
to Ruby on Rails: Core
Any framework that has convention over configuration has the the problem that newcomers have to learn the conventions.

I think that one of the biggest stumbling blocks to new users of Rails is the way associations are described. Just look at the number of questions on this on SO. M-1 and 1-M and even M-1-M are really quite simple concepts, but the Rails naming of these relationships just serves to confuse.

Here is a good definition that kind of gets at the root cause:

> belongs_to and has_many do not describe either the ownership or the scope or the life cycles for the objects they relate. They may give that impression because 'belongs' implies ownership and responsibility, but they merely describe the references (the keys) between the objects.


> Associations are a set of macro-like class methods for tying objects together through foreign keys

In that case isn't it easier if we called a spade a spade, and not a shovel? ;)

Surely all the confusion would be cleared up by renaming `belongs_to`? This would lower the barrier to learning Rails, resulting in less mistakes, less time wasted asking and answering on SO, less discussions, less blogs -> overall a HUGE time saver for the community **over the long term** (against which you have to weigh the short-term pain of adopting the change of course).

**Example 1 - one-to-one**
```ruby
class Employee
  has_one :salary
end
class Salary
  has_key_for :employee 
end
```

**Example 2 - one-to-many**
```ruby
class Manager
  has_many :employees
end
class Employee < ActiveRecord::Base
  has_key_for :manager
end
```

**Example 3- M-1-M**
```ruby
class Project
  has_many :assignments
  has_many :employees, through: :assignments  
end

class Employee
  has_many :assignments
  has_many :projects, through: :assignments
end

class Assignment
  has_key_for :employee
  has_key_for :project
end
```

**Example 4 - Polymorphic**
```ruby
class Address
  has_key_for :addressable, :polymorphic => true
end

class Person
  has_one :address, as: :addressable
end
```

I think this just leaves "has_and_belongs_to_many" which personally I have always hated. :)  Why not just use "has_many"? Since when you have an explicit join table for M-M, you use "through"...so if there is no "through" specified, we know it is a HABTM.


Chad Woolley

unread,
Sep 24, 2016, 10:42:51 AM9/24/16
to Ruby on Rails: Core
I agree.  I've been doing Rails for 10 years (and databases for going on 25)), and "belongs_to" has always been a cognitive blocker for me.

I wouldn't do away with "belongs_to", but making "has_key_for" aliases sounds like a great idea, for people who want to write their code that way.

But, most likely this should be in a gem, probably not a lot of chance of it making it into official Rails (I may be wrong, but I doubt it).

-- 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 https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.

Muhammad Nuzaihan Bin Kamal Luddin

unread,
Sep 24, 2016, 11:59:27 AM9/24/16
to rubyonra...@googlegroups.com
Sequel gem (which i had used for supporting legacy databases) is clearer to me. But i still can work on both ActiveRecord and Sequel-type associations.

https://github.com/jeremyevans/sequel#associations

--
Taqi Systems
269-J Jalan Panji
Kampung Chempaka, Kota Bharu, Kelantan 16100

Phone: +6097738657
Mobile: +60199788657

Xavier Noria

unread,
Sep 24, 2016, 5:57:42 PM9/24/16
to rubyonrails-core
On Sat, Sep 24, 2016 at 12:01 PM, Richard McSharry <rmcs...@gmail.com> wrote:

**Example 1 - one-to-one**
```ruby
class Employee
  has_one :salary
end
class Salary
  has_key_for :employee 
end
```

Generally speaking, the Active Record API expresses stuff at the entity level, at the model level.

For example, in idiomatic Active Record, if you have a user instance and want to fetch their posts you do NOT write this thing (that I sometimes see in the wild):

    Post.where(user_id: user.id)

That is thinking in SQL. It is a direct translation of a SELECT. In Active Record the whole API is oriented to entites, you write instead

    user.posts

which is pleasant, isn't. It flows.

Make no mistake, AR is not supposed to be magical or a black box. Active Record is a SQL generator, you gotta now what you are doing. As a programmer you know the SELECTs you need, but at the same time the API is such that you can express them that way: user.posts. Reads awesome, done.

`belongs_to` is the name of the macro because in many cases things belong to their parents at the model level. In the canonical AR example, comments belong to posts, like in real life, you know. Posts belong to authors or users. Invoice lines belong, are part of, their invoices, a task belongs to a to-do list, a wing belongs to an airplane, and so on.

On the other hand, has_key_for expresses at a different level, closer to SQL, in general that's not the approach of AR. Of course, if the defaults do not match the schema, then you configure options that start to get closer to SQL, because you need to. But that's the exceptional stuff, the one you support allowing the design to depart. You design the API to read naturally thinking about models, and at the same time leave room for the non-conventional needs going down in the vocabulary to SQL as needed.

Reply all
Reply to author
Forward
0 new messages