I wouldn't go for this route when trying to convince one.
IMO database migration and the ORM are different concerns and we should
actually use the single responsibility principle with regards to them.
For example, I prefer to maintain my database migrations in a different
project using standalone-migrations:
https://github.com/thuss/standalone-migrations
There are advantages and disadvantages using this approach, but I still
think it is a better option than integrating the migrations directly in
the application.
Disadvantages:
1- rails g model user email password_hash role:references
This wouldn't be much useful if migrations are not integrated. This
could be worked around in the standalone-migrations if they included
some generators to easy migrations generation.
The generated model class itself is so short that it is pretty fast to
create it by hand. With ActiveRecord it is "class MyModel <
ActiveRecord::Base; end". Just replace with Sequel::Model for Sequel.
2 - application-specific classes can't be used inside migrations (is
this really a disadvantage?)
Some people like the idea of updating some data in the database during a
migration by using the ORM itself inside the migrations.
While this can be handy sometimes, it can create some issues too.
For instance, your migration is now relying on your application code by
the time you created the migration.
After a while that code may no longer exist or do a different thing, so
this is pretty dangerous.
I've already experienced some issues in open-source projects where I
couldn't run a migration because the code inside earlier migrations
would no longer run.
The solution provided by Rails is to use "rake db:setup" for fresh
databases, but what if you need to run several migrations because you
already have a database, but the code has changed in such a way that
some of the earlier migration code won't run anymore?
That is one of two of the strongest reason I want to keep my migrations
in a separate project. Doing that you'll be assuring that no
application-specific domain code will be part of the migrations.
3 - You can't know what was the specific database version in use within
some commit.
Working around this limitation is pretty simple if you're using Git.
Just use your migrations project as a submodule and every time your
classes rely on a different database state, update the commit the
submodule points to.
Advantages:
I've talked already about most of them. Here are some more:
1 - You don't risk being unable to migrate or rollback your database due
to some issue in your code
I want to be sure that I'll be able to quickly run my migrations or
rollback the database even if my application won't boot for some reason,
like a bad initializer that relies on some network connection that is
not available or anything else. I want to just keep it simple.
2 - You can have different applications in possibly different languages
interacting with your database while having a single separate place to
store the migrations.
Back to the subject:
I've tried to convince you not to argue about defining the properties
inside the models to avoid duplication of code in migrations because
they should be really isolated from each other from my point of view.
Now, I'd like to share that I like the ability to quickly see what are
the column names for some domain by looking at its source-code. Your
solution provides that, but it is not the only way to achieve this goal.
Some people might want to document such columns by using the
attr_protected and attr_accessible methods. I don't agree that
protection against mass-assignment is a responsibility of the models,
hence I don't agree with the default
config.active_record.whitelist_attributes = true in application.rb. They
should be handled by the controller in a MVC or Model2 architecture.
But there is a simple solution that solves this issue for me (this
example assumes Sequel, since that is my ORM of choice):
rails r "puts User.columns.join ', '"
Then it is just a matter of replacing the comment in my classes when the
table changes (I always omit 'id'):
class User < Sequel::Model
# columns: email, password_hash, role_id
...
end
So, I'd like to ask you how do you think your proposal could help me if
I were using ActiveRecord instead of Sequel, since I'd use the same
ideas with AR as well.
Cheers,
Rodrigo.
Em 09-05-2012 07:29, mcasimir escreveu:
No other answer? I do not have you convinced yet then .. I hope that
does not bother you if I try again.
About 'this is not active record': with ruby ActiveRecord you have
improved the pattern yet mixing it with STI and supporting
associations with macros.
About 'this is duplicated code': what about STI? where in the
migrations code or in schema.rb or even in the database itself persist
the information that an attribute belongs to a children class and not
on the whole hierarchy classes? And where in the migration code is
eg
class Content < AR::Base
class Article < Content
class Video < Content
create_table content
add_column :title ..
add_column :url ..
add_column :text ..
Here Video instances will respond to :text, and Article will
respond_to :url without batting an eye. moreover even in the schema.rb
the 'contents' table schema is all you can find.. perhaps this is a
consequence of ActiveRecord not yet supporting STI very well.
This can't be the same of:
class Content < AR::Base
field :title
class Article < Content
field :text
class Video < Content
field :url
there is a very important information here: text is something that
belongs to Article, and url is something that belongs to Video. This
way you could also enforce that Video should not respond to 'text' and
Article should not respond to 'url'. This is nothing you can express
with migrations! Migrations are only a history to keep track of
changes you made to database. They are not good to express the
*logical *structure of the application domain.
All that i ask to you is what you think about that? But answer without
focusing on my purposed solution, but in a more abstract way. I think
the topic of discussion here is not whether to make a change or not
to ActiveRecord .. I probably said bad in this regard.. but I'd like
to know what you think of this lack.. first of all.. do you think this
is so? have you ever thought of it?
For me this was the first thing I noticed when i approached ruby on
rails from java world. This leak significantly restricts the ability
to refactor, mantain, document and reuse code, in other word a
weakness in dealing with changes over time. Why do not just try to
make things better? You have just done it in past, em i wrong?
Maurizio --
--
You received this message because you are subscribed to the Google Groups "Ruby on
Rails: Core" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/rubyonrails-core?hl=en.