Browse Source

permissions finished

pull/1/head
Nicolae Claudius 13 years ago
parent
commit
6144d62a52
  1. 8
      Gemfile.lock
  2. 41
      config/initializers/cancan.rb
  3. 3
      config/initializers/squeel.rb
  4. 13
      spec/models/domain_spec.rb
  5. 44
      spec/models/record_spec.rb

8
Gemfile.lock

@ -100,7 +100,7 @@ GEM
guard-spork (0.3.2)
guard (>= 0.8.4)
spork (>= 0.8.4)
highline (1.6.9)
highline (1.6.11)
hike (1.2.1)
i18n (0.6.0)
jquery-rails (1.0.19)
@ -199,12 +199,12 @@ GEM
multi_json (~> 1.0.3)
simplecov-html (~> 0.5.3)
simplecov-html (0.5.3)
spork (0.9.0.rc9)
spork (0.9.0)
sprockets (2.0.3)
hike (~> 1.2)
rack (~> 1.0)
tilt (!= 1.3.0, ~> 1.1)
squeel (0.9.3)
tilt (~> 1.1, != 1.3.0)
squeel (0.9.5)
activerecord (~> 3.0)
activesupport (~> 3.0)
polyamorous (~> 0.5.0)

41
config/initializers/cancan.rb

@ -1,4 +1,19 @@
# https://gist.github.com/1523940
class String
include Squeel::Nodes::PredicateOperators
end
module Squeel
module Visitors
class PredicateVisitor < Visitor
def visit_String(o, parent)
Arel::Nodes::SqlLiteral.new(o)
end
end
end
end
module CanCan
module ModelAdapters
@ -35,24 +50,14 @@ module CanCan
else raise NotImplemented, "The #{method} Squeel condition is not supported."
end
end
def tableized_conditions(conditions, model_class = @model_class)
return conditions unless conditions.kind_of? Hash
conditions.inject({}) do |result_hash, (name, value)|
name_sym = case name
when Symbol then name
when Squeel::Nodes::Join then name._name
when Squeel::Nodes::Predicate then name.expr
else raise name
end
if value.kind_of? Hash
reflection = model_class.reflect_on_association(name_sym)
association_class = reflection.class_name.constantize
name_sym = reflection.table_name.to_sym
value = tableized_conditions(value, association_class)
end
result_hash[name_sym] = value
result_hash
# mostly let Squeel do the job in building the query
def conditions
if @rules.size == 1 && @rules.first.base_behavior
# Return the conditions directly if there's just one definition
@rules.first.conditions.dup
else
@rules.reverse.inject(false_sql) {|acc, rule| acc | rule.conditions.dup}
end
end

3
config/initializers/squeel.rb

@ -1,12 +1,11 @@
Squeel.configure do |config|
# To load hash extensions (to allow for AND (&), OR (|), and NOT (-) against
# hashes of conditions)
config.load_core_extensions :hash
# To load symbol extensions (for a subset of the old MetaWhere functionality,
# via ARel predicate methods on Symbols: :name.matches, etc)
# config.load_core_extensions :symbol
# To load both hash and symbol extensions
# Load both hash and symbol extensions
config.load_core_extensions :hash, :symbol
end

13
spec/models/domain_spec.rb

@ -69,10 +69,15 @@ describe Domain do
it "queries domains corectly in index" do
permission3
query = Domain.accessible_by(user.ability(:reload => true))
wheres = query.where_values
joins = query.joins_values.map{|j| [j._name, j._type]}
wheres.should == ["(`domains`.`name_reversed` = '#{domain3.name_reversed}.%') OR ((`permissions`.`user_id` = #{user.id}) OR (`domains`.`user_id` = #{user.id}))"]
joins.should == [[:permissions, Arel::Nodes::OuterJoin]]
expected = <<-SQL
SELECT `domains`.* FROM `domains`
LEFT OUTER JOIN `permissions` ON `permissions`.`domain_id` = `domains`.`id`
WHERE ((((1=0 OR
`domains`.`user_id` = #{user.id}) OR
`permissions`.`user_id` = #{user.id}) OR
`domains`.`name_reversed` LIKE '#{permission3.domain.name_reversed}.%'))
SQL
query.to_sql.should == expected.gsub("\n", '').gsub(/\s+/, ' ').strip
end
it "has reversed name" do

44
spec/models/record_spec.rb

@ -17,31 +17,35 @@ describe Record do
a_record.should be_valid
end
def record_joins_expectations(joins)
# joins == [{:domain => Squeel(:permissions, outer)}]
joins.size.should == 1
joins.first.should be_an_instance_of(Hash)
domain_joins = joins.first[:domain]
domain_joins.size.should == 1
domain_joins.first[:domain]._name.should == :permissions
domain_joins.first[:domain]._type.should == Arel::Nodes::OuterJoin
end
it "queries records corectly in index" do
wheres = Record.accessible_by(user.ability).where_values
joins = Record.accessible_by(user.ability).joins_values
wheres.should == ["(`permissions`.`user_id` = #{user.id}) OR (`domains`.`user_id` = #{user.id})"]
record_joins_expectations(joins)
permission3
query = Record.accessible_by(user.ability)
expected = <<-SQL
SELECT `records`.* FROM `records`
INNER JOIN `domains` ON `domains`.`id` = `records`.`domain_id`
LEFT OUTER JOIN `permissions` ON `permissions`.`domain_id` = `domains`.`id`
WHERE ((((1=0 OR
`domains`.`user_id` = #{user.id}) OR
`permissions`.`user_id` = #{user.id}) OR
`domains`.`name_reversed` LIKE '#{permission3.domain.name_reversed}.%'))
SQL
query.to_sql.should == expected.gsub("\n", '').gsub(/\s+/, ' ').strip
end
it "queries A records corectly in index" do
it "queries A records corectly in index", :focus => true do
permission3
query = A.accessible_by(user.ability(:reload => true))
wheres = query.where_values
joins = query.joins_values
wheres.size.should == 2
wheres.second.should == "(`domains`.`name_reversed` = '#{domain3.name_reversed}.%') OR ((`permissions`.`user_id` = #{user.id}) OR ((`records`.`user_id` = #{user.id}) OR (`domains`.`user_id` = #{user.id})))"
record_joins_expectations(joins)
expected = <<-SQL
SELECT `records`.* FROM `records`
INNER JOIN `domains` ON `domains`.`id` = `records`.`domain_id`
LEFT OUTER JOIN `permissions` ON `permissions`.`domain_id` = `domains`.`id`
WHERE `records`.`type` IN ('A') AND (((((1=0 OR
`domains`.`user_id` = #{user.id}) OR
`records`.`user_id` = #{user.id}) OR
`permissions`.`user_id` = #{user.id}) OR
`domains`.`name_reversed` LIKE '#{permission3.domain.name_reversed}.%'))
SQL
query.to_sql.should == expected.gsub("\n", '').gsub(/\s+/, ' ').strip
end
end

Loading…
Cancel
Save