Skip to content

Instantly share code, notes, and snippets.

@bf4
Last active April 10, 2017 05:44
Show Gist options
  • Save bf4/5594532 to your computer and use it in GitHub Desktop.
Save bf4/5594532 to your computer and use it in GitHub Desktop.
# use inverse_of to 'just work'
class User < ActiveRecord::Base
has_many :contributions, inverse_of: :user
has_many :posts, through: :contributions
end
class Post < ActiveRecord::Base
has_many :contributions, inverse_of: :post
has_many :contributors, through: :contributions,
source: :user
end
class Contribution < ActiveRecord::Base
belongs_to :user
belongs_to :post
validates :user, presence: true
validates :post, presence: true
end
# prefer not to use callbacks
# if you do, have them only deal with the current class
# and not talk to other classes or relations
# or hit services or anything outside of itself
# and you can even get callback-like
# behavior as below which will always be called
# even when callbacks are not
# a pre-condition (before filter)
# with a post-condition (after filter)
# that rollsback the transaction
def create_or_update
say_my_name_before_filter &&
super && say_goodbye_after_filter or raise ActiveRecord::Rollback
end
# like an around filter
# with a condition on the post part
def create_or_update
puts 'we got' unless dont_do_it?
super
puts 'all the way around' if we_want_to?
end
# always use after_initialize { }
# or after_initialize :something
# since def initialize(*) isn't always called
# don't use default_scope
# it doesn't work
# don't validate e.g. association_id
# validate ruby objects!!
# UNIQUENESS
class Record < ActiveRecord::Base
# validates :email, uniqueness: true
# def save(*)
# super
# rescue ActiveRecord::RecordNotUnique => e
# errors.add(:email, :taken)
# false
# end
validates :title,
uniqueness: { scope: :subtitle }
def save(*)
super
rescue ActiveRecord::RecordNotUnique => e
attr_name, *scope = e.message.
match(/Key \(([^\)]+)\)/)[1].split(/,\s*/)
message = errors.generate_message(attr_name, :taken)
if scope.any?
message << " (scope: #{scope.to_sentence})"
end
errors.add attr_name, message
false
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment