Have AR::Base#[] act consistently for non-existent attributes

Currently we have an inconcistency between calling `[]` for columns that
exist but were not included in the query, and accessing columns which do
not exist.

    class Author < ActiveRecord::Base
      connection.create_table(:authors, force: true) do |t|
        t.string :name
      end
    end

    author = Author.select('id').first

    # Before:
    author[:name] # => Raises ActiveModel::MissingAttributeError
    author[:non_existent] # => nil

    # After:
    author[:name] # => Raises ActiveModel::MissingAttributeError
    author[:non_existent] # => Raises ActiveModel::MissingAttributeError

Personally, I think it'd make more sense for `[]` to return nil in all
cases, but the documentation states that "It raises
`ActiveModel::MissingAttributeError` if the identified attribute is
missing." so we cannot do that at this time.
It is impossible for the pk not to be in this has. If id was not in there,
we *must* have a non standard pk. We don't need to pass the block because
that line will never be reached with a PK
On Jun 9, 2014 3:12 AM, "Matthew Draper" <notifications@github.com> wrote:

> In activerecord/lib/active_record/attribute_methods/read.rb:
>
> >
> >            value = @raw_attributes.fetch(name) {
> > -            return block_given? ? yield(name) : nil
> > +            # We have a non-standard pk and `id` was not present in a custom
> > +            # select clause
> > +            if name == 'id'
>
> "We have a non-standard pk" seems to have gone missing in this
> conditional? In fact, even with that condition, shouldn't the below call to
> read_attribute pass on our block?
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/rails/rails/pull/15581/files#r13533575>.
>