-
Notifications
You must be signed in to change notification settings - Fork 2
Concerns
cavalle edited this page Dec 23, 2012
·
13 revisions
http://weblog.jamisbuck.org/2007/1/17/concerns-in-activerecord
module Folder
def self.included(base)
base.has_many :files, :as => :owner, :dependent => :destroy
end
# This returns the path where files are to be uploaded
# for this specific "folder".
def attachment_path
"/path/to/files/for/#{id}"
end
endclass Message < ActiveRecord::Base
include Folder
#...
end
class Comment < ActiveRecord::Base
include Folder
#...
end- https://speakerdeck.com/seenmyfate/4-steps-to-faster-rails-tests
- http://confreaks.com/videos/641-gogaruco2011-fast-rails-tests
module DiscountCalculator
def total_discount
basket_items.collect(&:discount).inject(:+)
end
endclass Basket < ActiveRecord::Base
has_many :basket_items
include DiscountCalculator
endhttp://www.rvdh.de/2011/12/01/splitting-your-rails-classes-into-modules-how-does-it-work/
# app/models/user/authentication.rb
class User
module Authentication
extend ActiveSupport::Concern
included do
has_secure_password
end
def create_password_reset_token
token = SecureRandom.base64.tr('+/=lIO0', 'zomglol')
self.update_attribute(:password_reset_token, token)
end
end
end# app/models/user.rb
class User < ActiveRecord::Base
include Authentication
include Validations
# ...
endhttp://37signals.com/svn/posts/3372-put-chubby-models-on-a-diet-with-concerns
module Taggable
extend ActiveSupport::Concern
included do
has_many :taggings, as: :taggable, dependent: :destroy
has_many :tags, through: :taggings
end
def tag_names
tags.map(&:name)
end
end# current_account.posts.visible_to(current_user)
module Visible
extend ActiveSupport::Concern
module ClassMethods
def visible_to(person)
where \
"(#{table_name}.bucket_id IN (?) AND
#{table_name}.bucket_type = 'Project') OR
(#{table_name}.bucket_id IN (?) AND
#{table_name}.bucket_type = 'Calendar')",
person.projects.pluck('projects.id'),
calendar_scope.pluck('calendars.id')
end
end
endmodule Dropboxed
extend ActiveSupport::Concern
included do
before_create :generate_dropbox_key
end
def rekey_dropbox
generate_dropbox_key
save!
end
private
def generate_dropbox_key
self.dropbox_key = SignalId::Token.unique(24) do |key|
self.class.find_by_dropbox_key(key)
end
end
end- http://railscasts.com/episodes/398-service-objects
- https://github.com/railscasts/398-service-objects
class User < ActiveRecord::Base
attr_accessible :email, :username, :password, :password_confirmation
validates_presence_of :username, :email
validates_uniqueness_of :username
validates_confirmation_of :password
include Authentication
include Searchable
include CsvConversion
include Inviter
include PasswordResettable
end# app/models/concerns/user/authentication.rb
class User
module Authentication
extend ActiveSupport::Concern
included do
has_secure_password
end
module ClassMethods
def authenticate(username, password)
user = find_by_username(username)
user if user && user.authenticate(password)
end
def from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth[:provider]
user.uid = auth[:uid]
user.username = auth[:info][:nickname]
user.save!
end
end
end
end
end# app/models/user.rb
class User < ActiveRecord::Base
include Tickets
include ApiKeys
has_many :events
end# app/models/user/tickets.rb
module User::Tickets
extend ActiveSupport::Concern
included do
has_many :tickets
end
def most_recent_ticket
# huh, obviously code here
end
private
def recent_tickets
end
end# app/models/user/api_keys.rb
module User::ApiKeys
extend ActiveSupport::Concern
included do
after_create :create_api_keys
end
private
def create_api_keys
end
def random_key
end
end# create an extensions directory in models
# app/models/extensions/popular.rb
module Extensions
module Popular
extend ActiveSupport::Concern
# you can include other things here
included do
include Extensions::OtherCoolStuff
# or if you're using Mongoid you can also add fields
field :points, :type => Integer, :default => 0
end
# include class methods here
# like User.most_popular
module ClassMethods
def most_popular(limit=10)
order_by(:points.desc).limit(limit).all
end
end
# include Instance methods
# like @user.popularity
module InstanceMethods
def popularity
1+(self.points/100)
end
end
end
endclass User
include Extensions::Popular
endclass Tags
include Extensions::Popular
end