user = User.new
user.first_name = "Ben"
user[:first_name] = "Ben"
user.read_attribute(:first_name)
# => "Ben"
user[:first_name]
# => "Ben"
user.write_attribute(:first_name, "Ben")
# NoMethodError: private method `write_attribute' called
user = User.create
# #<User id: 1, first_name: nil, last_name: nil>
user.first_name = "Ben"
user.update_attribute(:last_name, "Eddy")
user.reload
# #<User id: 1, first_name: "Ben", last_name: "Eddy">
# Whaaaaa?
Pass attributes into a scope which are only used when you create a record from the scope. You might be familiar with this:
User.where(email: "[email protected]").first_or_create
But it's nice to have the ability to add extra attributes in the event of a create.
User.where(email: "[email protected]")
.create_with(first_name: "Ben", last_name: "Eddy")
.first_or_create
pluck(:id)
is apparently such a common operation that ids
was born.
includes
has been around for a while. It either performs a LEFT JOIN or prefetches data with a separate query. You never really know which, though.
User.all.includes(:comments).where("comments.active = ?", true)
# ERRORS - missing from clause for table `comments`
i.e. the LEFT JOIN wasn't performed, so the comments table isn't reference-able in conditions. references
allows you to stipulate exactly which tables you need to reference.
User.all.includes(:comments).where("comments.active = ?", true).references(:comments)
# No problems
eager_load
forces a LEFT JOIN (yay, finally!)
Dynamically extend a module on a scope e.g.
User.where(email: "[email protected]").extending(Pagination)
Kinda crazy, and I'm not sure it is useful. But w/e, it exists.
reorder
blows away previous ordering clauses.
User.order(:created_at).reorder(:updated_at).to_sql
# SELECT * FROM users ORDER BY updated_at;
rewhere
blows away previous conditions. For example, the :email
condition is replaced.
User.where(email: "[email protected]").where(email: "[email protected]").to_sql
# SELECT * FROM users WHERE email = '[email protected]' AND email = '[email protected]';
User.where(email: "[email protected]").rewhere(email: "[email protected]").to_sql
# SELECT * FROM users WHERE email = '[email protected]';
BUT, rewhere
only overwrites conditions on the same attribute. Conditions for different attributes are still AND
ed.
User.where(email: "[email protected]").rewhere(first_name: "Ben").to_sql
# SELECT * FROM users WHERE email = '[email protected]' AND first_name = 'Ben';
#####8. not
not
isn't really suprising, I'm just happy it exists.
User.where.not(id: 1)
# SELECT * FROM users WHERE id != 1;