
Five Common Rails Mistakes - vamsee
http://www.mikeperham.com/2012/05/05/five-common-rails-mistakes
======
cageface
_Without schema constraints, your data will slowly corrode due to bugs in your
codebase until you can’t depend on any fields being populated._

Don't tell that to the NoSQL people.

 _use :limit = > N to size your string columns appropriately. Strings default
to 255 characters and phone probably doesn’t need to be that big, does it?_

Is this a Rails limitation? A lot of DBs, like Postgres, treat all strings as
varchar anyway.

~~~
kondro
How big do you think an index on a 255 character string is (at least in
MySQL)? And if you're not putting limits on your strings, do you think it's
likely you're putting limits on your indexes?

~~~
cageface
I avoid MySQL as much as possible, so I couldn't say in that case. However,
according to the Postgres docs:

[http://www.postgresql.org/docs/9.1/static/datatype-
character...](http://www.postgresql.org/docs/9.1/static/datatype-
character.html)

The fixed-size field is actually _slower_ in their implementation.

~~~
masklinn
Warning, fixed-size and limited-size is not the same thing. VARCHAR(12) is a
VARCHAR which can not go beyond 12 characters, CHAR(12) is a fixed-size string
which will _be padded_ to 12 characters.

I'm pretty sure Rails uses VARCHAR (or its equivalent in other DBs)
exclusively. But unless a size is specified it will use VARCHAR(255).
VARCHAR(16) will enforce a maximum size (through truncation) and may
(depending on the database[0]) lead to optimizations by storing the string
differently and/or ending with lower row (and table) sizes.

As for TFA, his example using phone numbers is not very good because while
there are standard sizes for phone numbers (E.164 allows for 15 digits
including a country code of 1-3 digits, giving national number maximums of 12
to 14 digits depending on the country) people usually fuck them up hard (by
using the sizes — and formattings — of their home countries), and when adding
local formatting conventions it's an even bigger messes (depending on the
country, you can have up to half a dozen format characters interspersed
between digit groups)

[0] it does not in Postgres: as your link notes, Postgres will dynamically
decide how to store a string — in-row or out-of-row for instance — on the spot
based on its size. On the other hand maximum string size has an effect on
Postgres indexes: b-tree (the default) will blow up on strings beyond 4k
chars, and this is _not_ statically checked by postgres, it will blow up while
trying to insert a string of more than 4k chars.

Of course if you're trying to index a string column with such sizes using
anything but full-text indexes you're probably doing something wrong anyway,
but if you're using VARCHAR (which maxes out at 1GB due to implementation
details) you _may_ find yourself in that situation even though you're only
storing 4-letter codes.

In that case, you're better off using VARCHAR(4).

~~~
pilif
> VARCHAR(16) will enforce a maximum size (through truncation)

Thankfully, real databases won't do that. They will blow up and leave the
application to do the truncation.

If there is one feature I want a database to have, it's that I'm guaranteed to
read the data back that I stored there.

That also means that if I store "foobar" in a varchar(3) field that I don't
want to read back "foo" with no way to ever find out that I didn't actually
ever store foo there to begin with.

Storing a 6 character string into a field dimensioned for three characters is
an error and not something that would warrant silent data corruption.

~~~
Corrado
If you read the PostgreSQL docs you'll see that it only truncates spaces and
throws an error if any non-space data is present. Apparently, this behavior is
required by the SQL specifications.

So, in your example of storing "foobar" in a varchar(3) field, PostgreSQL will
throw an error and not store the data. You could however store "foo " in that
same field without any problems and you would get back "foo" in return.

~~~
caiusdurling
MySQL will silently truncate it without throwing an error however. And even
when you know about it, you'll still get bitten occasionally and SERIOUSLY
kick yourself when you realise the error.

Postgres is better for the little things, but when it goes wrong it tends to
be harder to find the reason why. At least in my experience. That said, I'll
still reach for Postgres over MySQL these days.

~~~
mzarate06
_MySQL will silently truncate it without throwing an error however._

It will indeed, for folks that prefer that or haven't looked into enabling
alternate behavior. Set STRICT_TRANS_TABLES (for InnoDB) or STRICT_ALL_TABLES
(for any storage engine) in MySQL's config and it'll throw the following error
instead of silently truncating data:

 _[Err] 1406 - Data too long for column '[some column]' at row [XYZ]_

Does that help?

------
chris_wot
I'm interested in point 4: use SQL. Is there a way of doing a find that only
returns the primary key value and then do a delete only based on this value
_without_ using SQL and only via Active Record?

~~~
xentronium
Do you mean something like this?

    
    
        ids = Post.where(:published => true).pluck(:id) 
        Post.where(:id => ids).delete_all
    

or this

    
    
        Post.where(:published => true).delete_all
    
    ?

~~~
janus
You might want to use 'destroy' instead of 'delete', as 'delete' skips all
ActiveRecord callbacks (i. e., if you had a dependent: :destroy callback for
post comments, using 'delete' would leave them intact)

~~~
xentronium
`destroy` instantiates active record models which kind of defeats the purpose
of fast deletion :)

~~~
janus
You are right, well in that case, you would have to delete associated records
manually if you didn't add any foreign keys at the db level

~~~
chris_wot
I'd suggest deleting or dealing with those records anyway, regardless of
whether you added FKs! But... if you don't add FKs, you've got bigger issues
to deal with :(

------
DavidAbrams
Is Rails as prevalent as it once was, or has something emerged to overtake it
for whatever it is that Rails excels at?

------
cbsmith
Forgot 6: Using Rails.

