Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Switch from HABTM to has_many through #227

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 12 additions & 16 deletions lib/generators/active_record/rolify_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,42 @@ module ActiveRecord
module Generators
class RolifyGenerator < ActiveRecord::Generators::Base
source_root File.expand_path("../templates", __FILE__)

argument :user_cname, :type => :string, :default => "User", :banner => "User"

def generate_model
invoke "active_record:model", [ name ], :migration => false
end

def inject_role_class
inject_into_class(model_path, class_name, model_content)
end

def copy_rolify_migration
migration_template "migration.rb", "db/migrate/rolify_create_#{table_name}"
end

def join_table
user_cname.constantize.table_name + "_" + table_name
end


def user_reference
user_cname.demodulize.underscore
end

def role_reference
class_name.demodulize.underscore
end

def model_path
File.join("app", "models", "#{file_path}.rb")
end

def model_content
content = <<RUBY
has_and_belongs_to_many :%{user_cname}, :join_table => :%{join_table}
belongs_to :%{user_cname}
belongs_to :resource, :polymorphic => true

scopify
RUBY
content % { :user_cname => user_cname.constantize.table_name, :join_table => "#{user_cname.constantize.table_name}_#{table_name}"}
content % { :user_cname => user_cname.demodulize.underscore }
end
end
end
end
end
7 changes: 1 addition & 6 deletions lib/generators/active_record/templates/migration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,13 @@ class RolifyCreate<%= table_name.camelize %> < ActiveRecord::Migration
def change
create_table(:<%= table_name %>) do |t|
t.string :name
t.belongs_to :user
t.references :resource, :polymorphic => true

t.timestamps
end

create_table(:<%= join_table %>, :id => false) do |t|
t.references :<%= user_reference %>
t.references :<%= role_reference %>
end

add_index(:<%= table_name %>, :name)
add_index(:<%= table_name %>, [ :name, :resource_type, :resource_id ])
add_index(:<%= join_table %>, [ :<%= user_reference %>_id, :<%= role_reference %>_id ])
end
end
8 changes: 4 additions & 4 deletions lib/generators/rolify/rolify_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Rolify
module Generators
class RolifyGenerator < Rails::Generators::NamedBase
Rails::Generators::ResourceHelpers

source_root File.expand_path('../templates', __FILE__)
argument :user_cname, :type => :string, :default => "User"

Expand All @@ -16,15 +16,15 @@ def self.start(args, config)
args.insert(1, user_cname) # 0 being the view name
super
end

def inject_user_class
invoke "rolify:user", [ user_cname, class_name ], :orm => options.orm
end

def copy_initializer_file
template "initializer.rb", "config/initializers/rolify.rb"
end

def show_readme
if behavior == :invoke
readme "README"
Expand Down
4 changes: 2 additions & 2 deletions lib/generators/rolify/templates/initializer.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Rolify.configure<%= "(\"#{class_name.camelize.to_s}\")" if class_name != "Role" %> do |config|
# By default ORM adapter is ActiveRecord. uncomment to use mongoid
<%= "# " if options.orm == :active_record || !options.orm %>config.use_mongoid

# Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false
# Enable this feature _after_ running rake db:migrate as it relies on the roles table
# config.use_dynamic_shortcuts
end
end
4 changes: 2 additions & 2 deletions lib/generators/rolify/templates/role-active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ def self.table_name_prefix
<%= table_prefix(role_cname) %>_
end
<% end %>
has_and_belongs_to_many :<%= user_cname.tableize %>, :join_table => :<%= "#{table_name(user_cname, true)}_#{table_name(role_cname, true)}" %>
belongs_to <%= user_cname.singularize %>
belongs_to :resource, :polymorphic => true

scopify
end
8 changes: 4 additions & 4 deletions lib/generators/rolify/user_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,27 @@ module Generators
class UserGenerator < Rails::Generators::NamedBase
argument :role_cname, :type => :string, :default => "Role"
class_option :orm, :type => :string, :default => "active_record"

desc "Inject rolify method in the User class."

def inject_user_content
inject_into_file(model_path, :after => inject_rolify_method) do
" rolify#{role_association}\n"
end
end

def inject_rolify_method
if options.orm == :active_record
/class #{class_name.camelize}\n|class #{class_name.camelize} .*\n|class #{class_name.demodulize.camelize}\n|class #{class_name.demodulize.camelize} .*\n/
else
/include Mongoid::Document\n|include Mongoid::Document .*\n/
end
end

def model_path
File.join("app", "models", "#{file_path}.rb")
end

def role_association
if role_cname != "Role"
" :role_cname => '#{role_cname.camelize}'"
Expand Down
23 changes: 10 additions & 13 deletions lib/rolify.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,36 @@
module Rolify
extend Configure

attr_accessor :role_cname, :adapter, :role_join_table_name, :role_table_name
attr_accessor :role_cname, :adapter, :role_table_name

def rolify(options = {})
include Role
extend Dynamic if Rolify.dynamic_shortcuts

options.reverse_merge!({:role_cname => 'Role'})
options.reverse_merge!({ :role_cname => 'Role', :dependent => :destroy })
self.role_cname = options[:role_cname]
self.role_table_name = self.role_cname.tableize.gsub(/\//, "_")

default_join_table = "#{self.to_s.tableize.gsub(/\//, "_")}_#{self.role_table_name}"
options.reverse_merge!({:role_join_table_name => default_join_table})
self.role_join_table_name = options[:role_join_table_name]

rolify_options = { :class_name => options[:role_cname].camelize }
rolify_options.merge!({ :join_table => self.role_join_table_name }) if Rolify.orm == "active_record"
rolify_options = { :class_name => options[:role_cname].camelize, :dependent => options[:dependent] }
rolify_options.merge!(options.reject{ |k,v| ![ :before_add, :after_add, :before_remove, :after_remove ].include? k.to_sym })

has_and_belongs_to_many :roles, rolify_options
has_many :roles, rolify_options
has_many :groups, :through => :roles, :source => :resource, :source_type => 'Group'

self.adapter = Rolify::Adapter::Base.create("role_adapter", self.role_cname, self.name)
load_dynamic_methods if Rolify.dynamic_shortcuts
end

def resourcify(association_name = :roles, options = {})
def resourcify(role_association_name = :roles, target_association_name = :users, options = {})
include Resource

options.reverse_merge!({ :role_cname => 'Role', :dependent => :destroy })
resourcify_options = { :class_name => options[:role_cname].camelize, :as => :resource, :dependent => options[:dependent] }
options.reverse_merge!({ :role_cname => 'Role', :dependent => :destroy, :as => :resource })
resourcify_options = { :class_name => options[:role_cname].camelize, :dependent => options[:dependent], :as => options[:as] }
self.role_cname = options[:role_cname]
self.role_table_name = self.role_cname.tableize.gsub(/\//, "_")

has_many association_name, resourcify_options
has_many role_association_name, resourcify_options
has_many target_association_name, :through => role_association_name, :as => :resource

self.adapter = Rolify::Adapter::Base.create("resource_adapter", self.role_cname, self.name)
end
Expand Down
6 changes: 3 additions & 3 deletions lib/rolify/adapters/active_record/scopes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ module Scopes
def global
where(:resource_type => nil, :resource_id => nil)
end

def class_scoped(resource_type = nil)
where_conditions = "resource_type IS NOT NULL AND resource_id IS NULL"
where_conditions = [ "resource_type = ? AND resource_id IS NULL", resource_type.name ] if resource_type
where(where_conditions)
end

def instance_scoped(resource_type = nil)
where_conditions = "resource_type IS NOT NULL AND resource_id IS NOT NULL"
if resource_type
Expand All @@ -24,4 +24,4 @@ def instance_scoped(resource_type = nil)
end
end
end
end
end
10 changes: 5 additions & 5 deletions lib/rolify/configure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Rolify
module Configure
@@dynamic_shortcuts = false
@@orm = "active_record"

def configure(*role_cnames)
return if !sanity_check(role_cnames)
yield self if block_given?
Expand All @@ -27,7 +27,7 @@ def orm=(orm)
def use_mongoid
self.orm = "mongoid"
end

def use_dynamic_shortcuts
self.dynamic_shortcuts = true
end
Expand All @@ -38,9 +38,9 @@ def use_defaults
config.orm = "active_record"
end
end

private

def sanity_check(role_cnames)
role_cnames = [ "Role" ] if role_cnames.empty?
role_cnames.each do |role_cname|
Expand All @@ -52,7 +52,7 @@ def sanity_check(role_cnames)
end
true
end

def role_table_missing?(role_class)
role_class.connected? && !role_class.table_exists?
end
Expand Down
4 changes: 2 additions & 2 deletions lib/rolify/dynamic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def load_dynamic_methods
end

def define_dynamic_method(role_name, resource)
class_eval do
class_eval do
define_method("is_#{role_name}?".to_sym) do
has_role?("#{role_name}")
end if !method_defined?("is_#{role_name}?".to_sym)
Expand All @@ -18,4 +18,4 @@ def define_dynamic_method(role_name, resource)
end
end
end
end
end
6 changes: 3 additions & 3 deletions lib/rolify/finders.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ def with_any_role(*args)
users.uniq
end
end

private

def parse_args(args, users, &block)
args.each do |arg|
if arg.is_a? Hash
Expand All @@ -37,4 +37,4 @@ def parse_args(args, users, &block)
block.call(users_to_add)
end
end
end
end
4 changes: 2 additions & 2 deletions lib/rolify/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Railtie < Rails::Railtie
ActiveSupport.on_load(:active_record) do
ActiveRecord::Base.send :extend, Rolify
end

config.before_initialize do
::Mongoid::Document.module_eval do
def self.included(base)
Expand All @@ -17,4 +17,4 @@ def self.included(base)
end if defined?(Mongoid)
end
end
end
end
6 changes: 3 additions & 3 deletions lib/rolify/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ def self.included(base)
base.extend ClassMethods
end

module ClassMethods
module ClassMethods
def find_roles(role_name = nil, user = nil)
roles = user && (user != :any) ? user.roles : self.role_class
roles = roles.where(:resource_type => self.to_s)
Expand All @@ -23,9 +23,9 @@ def with_role(role_name, user = nil)
end
alias :with_roles :with_role
end

def applied_roles
self.roles + self.class.role_class.where(:resource_type => self.class.to_s, :resource_id => nil)
end
end
end
end
12 changes: 6 additions & 6 deletions lib/rolify/role.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
module Rolify
module Role
extend Utils

def self.included(base)
base.extend Finders
end

def add_role(role_name, resource = nil)
role = self.class.adapter.find_or_create_by(role_name.to_s,
(resource.is_a?(Class) ? resource.to_s : resource.class.name if resource),
role = self.class.adapter.find_or_create_by(role_name.to_s,
(resource.is_a?(Class) ? resource.to_s : resource.class.name if resource),
(resource.id if resource && !resource.is_a?(Class)))

if !roles.include?(role)
Expand Down Expand Up @@ -50,15 +50,15 @@ def has_any_role?(*args)
self.class.adapter.where(self.roles, *args).size > 0
end
end

def only_has_role?(role_name, resource = nil)
return self.has_role?(role_name,resource) && self.roles.count == 1
end

def remove_role(role_name, resource = nil)
self.class.adapter.remove(self, role_name.to_s, resource)
end

alias_method :revoke, :remove_role
deprecate :has_no_role, :remove_role

Expand Down
Loading