Skip to content

Instantly share code, notes, and snippets.

@BenEddy
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BenEddy/5fc156875028e8fbd060 to your computer and use it in GitHub Desktop.
Save BenEddy/5fc156875028e8fbd060 to your computer and use it in GitHub Desktop.
1. write_attribute is private, but read_attribute, []= and [] are public.
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
2. update_attribute persists dirty values, not just the attribute you intend to update
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?

Rails 4 only

3. create_with exists

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: "bae@foraker.com").first_or_create

But it's nice to have the ability to add extra attributes in the event of a create.

User.where(email: "bae@foraker.com")
  .create_with(first_name: "Ben", last_name: "Eddy")
  .first_or_create
4. ids

pluck(:id) is apparently such a common operation that ids was born.

5. includes vs. eager_load vs. references

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!)

6. extending

Dynamically extend a module on a scope e.g.

User.where(email: "bae@foraker.com").extending(Pagination)

Kinda crazy, and I'm not sure it is useful. But w/e, it exists.

7. rewhere vs reorder

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: "bae@foraker.com").where(email: "kae@foraker.com").to_sql
# SELECT * FROM users WHERE email = 'bae@foraker.com' AND email = 'kae@foraker.com';

User.where(email: "bae@foraker.com").rewhere(email: "kae@foraker.com").to_sql
# SELECT * FROM users WHERE email = 'kae@foraker.com';

BUT, rewhere only overwrites conditions on the same attribute. Conditions for different attributes are still ANDed.

User.where(email: "bae@foraker.com").rewhere(first_name: "Ben").to_sql
# SELECT * FROM users WHERE email = 'bae@foraker.com' 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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment