Skip to content
Browse files

First version

  • Loading branch information...
1 parent b648592 commit 73ade9e3f0d049bbfef52a389ae98a22ac574f07 @iain committed
Showing with 202 additions and 38 deletions.
  1. +0 −20 LICENSE
  2. +76 −12 README.rdoc
  3. +3 −3 Rakefile
  4. +63 −0 lib/basic_named_scopes.rb
  5. +53 −2 spec/basic_named_scopes_spec.rb
  6. +7 −1 spec/spec_helper.rb
View
20 LICENSE
@@ -1,20 +0,0 @@
-Copyright (c) 2009 Iain Hecker
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
88 README.rdoc
@@ -1,17 +1,81 @@
-= basic_named_scopes
+= BasicNamedScopes
-Description goes here.
+Basic named scopes for ActiveRecord. Propagates the parameters of the
+find-method as named scopes, for easy reusability and prettier code.
-== Note on Patches/Pull Requests
-
-* Fork the project.
-* Make your feature addition or bug fix.
-* Add tests for it. This is important so I don't break it in a
- future version unintentionally.
-* Commit, do not mess with rakefile, version, or history.
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
-* Send me a pull request. Bonus points for topic branches.
+Instead of writing:
+
+ Post.all(:conditions => { :published => true }, :select => :title, :includes => :author)
+
+You can now write:
+
+ Post.conditions(:published => true).select(:title).include(:author)
+
+Reuse them by making class methods:
+
+ class Post < ActiveRecord::Base
+
+ def self.published
+ conditions(:published => true)
+ end
+
+ def self.visible
+ conditions(:visible => true)
+ end
+
+ def self.index
+ published.visible
+ end
+
+ end
+
+Also, the +all+-method is a named scope now, so you can chain after callling
+all, for greater flexibility.
+
+ Post.all.published
+
+Arrays can be used as multple parameters too, sparing you some brackets.
+
+ Post.include(:author, :comments).conditions("name LIKE ?", query)
+
+The +read_only+ and +lock+ scopes default to true, but can be adjusted.
+
+ Post.readonly # => same as Post.all(:readonly => true)
+ Post.readonly(false) # => same as Post.all(:readonly => false)
+
+== Why?
+
+NamedScopes are really handy and they should play a more central theme in ActiveRecord.
+While I heard that ActiveRecord 3 will support similar syntax, there is no reason to wait
+any longer.
+
+I find defining named scopes very ugly, especially when dealing with parameters.
+Just compare the amount of curly braces!
+
+ # Using normal named scope:
+ named_scope :name_like, lambda { |query| { :conditions => ["name LIKE ?", query] } }
+
+ # Using BasicNamedScopes
+ def self.name_like(query)
+ conditions("name LIKE ?", query)
+ end
+
+Also, regular named scopes don't support using other named scopes at all!
+
+I found myself implementing (mostly conditions, but others too) so often, that
+a little gem like this would be the obvious choice. Use it if a gem like
+searchlogic is overkill for your needs.
+
+== Installing
+
+The gem is called "basic_named_scopes". You know how to install it.
+
+ gem install basic_named_scopes
+
+Use it in Rails:
+
+ config.gem "basic_named_scopes"
== Copyright
-Copyright (c) 2009 Iain Hecker. See LICENSE for details.
+Copyright (c) 2009 Iain Hecker. Released under the MIT License.
View
6 Rakefile
@@ -5,13 +5,13 @@ begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = "basic_named_scopes"
- gem.summary = %Q{TODO: one-line summary of your gem}
- gem.description = %Q{TODO: longer description of your gem}
+ gem.summary = %Q{Basic named scopes for ActiveRecord makes all find-parameters a named scope}
+ gem.description = %Q{Make your queries prettier and more reusable by having a named scope for every find-parameter. As easy as Post.include(:author, :comments)}
gem.email = "iain@iain.nl"
gem.homepage = "http://github.com/iain/basic_named_scopes"
gem.authors = ["Iain Hecker"]
gem.add_development_dependency "rspec", ">= 1.2.9"
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
+ gem.add_development_dependency "temping", ">= 1.1.0"
end
Jeweler::GemcutterTasks.new
rescue LoadError
View
63 lib/basic_named_scopes.rb
@@ -0,0 +1,63 @@
+# Basic named scopes for ActiveRecord. Propagates the parameters of the
+# find-method as named scopes, for easy reusability and prettier code.
+#
+# Instead of writing:
+#
+# Post.all(:conditions => { :published => true }, :select => :title, :includes => :author)
+#
+# You can now write:
+#
+# Post.conditions(:published => true).select(:title).include(:author)
+#
+# Reuse them by making class methods:
+#
+# class Post < ActiveRecord::Base
+#
+# def self.published
+# conditions(:published => true)
+# end
+#
+# def self.visible
+# conditions(:visible => true)
+# end
+#
+# def self.index
+# published.visible
+# end
+#
+# end
+#
+# Also, the +all+-method is a named scope now, so you can chain after callling
+# all, for greater flexibility.
+#
+# Post.all.published
+#
+# Arrays can be used as multple parameters too, sparing you some brackets.
+#
+# Post.include(:author, :comments).conditions("name LIKE ?", query)
+#
+# The +read_only+ and +lock+ scopes default to true, but can be adjusted.
+#
+# Post.readonly # => same as Post.all(:readonly => true)
+# Post.readonly(false) # => same as Post.all(:readonly => false)
+#
+module BasicNamedScopes
+
+ FIND_PARAMETERS = [:conditions, :order, :group, :having, :limit, :offset, :joins, :include, :select, :from]
+ FIND_BOOLEAN_SWITCHES = [:readonly, :lock]
+
+ def self.extended(record)
+ FIND_PARAMETERS.each do |parameter|
+ record.named_scope(parameter, lambda { |*args| { parameter => args.size == 1 ? args.first : args } })
+ end
+ FIND_BOOLEAN_SWITCHES.each do |parameter|
+ record.named_scope(parameter, lambda { |*args| { parameter => args.size == 0 ? true : args[0] } })
+ end
+ record.named_scope(:all, lambda { |*args| args[0] || {} })
+ end
+
+end
+
+if defined? ActiveRecord
+ ActiveRecord::Base.extend(BasicNamedScopes)
+end
View
55 spec/basic_named_scopes_spec.rb
@@ -1,7 +1,58 @@
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
describe "BasicNamedScopes" do
- it "fails" do
- fail "hey buddy, you should probably rename this file and start specing for real"
+
+ before :all do
+ create_model :posts do
+ with_columns do |table|
+ table.boolean :published
+ table.boolean :visible
+ end
+ extend BasicNamedScopes
+ end
+ end
+
+ before :each do
+ Post.delete_all
+ @published = Post.create!(:published => true)
+ @unpublished = Post.create!(:published => false)
+ end
+
+ it "should make .all a named scope" do
+ # Without parameters
+ Post.all.class.should be_scope
+ # With parameters
+ Post.all(:conditions => {:published => true}).class.should be_scope
+ end
+
+ it "should make find parameters a named scope" do
+ subject = Post.conditions(:published => true)
+ subject.class.should be_scope
+ subject.should == [ @published ]
+ end
+
+ it "should expand into array when using multiple parameters" do
+ subject = Post.conditions("published = ?", true)
+ subject.class.should be_scope
+ subject.should == [ @published ]
+ end
+
+ [:conditions, :order, :group, :having, :limit, :offset, :joins, :include, :select, :from].each do |option|
+ it "should known #{option} ActiveRecord::Base.find" do
+ Post.send(option).class.should be_scope
+ end
+ end
+
+ it "should default to true for readonly" do
+ subject = Post.readonly
+ subject.class.should be_scope
+ lambda { subject.first.save }.should raise_error(ActiveRecord::ReadOnlyRecord)
+ end
+
+ it "should accept a value for readonly" do
+ subject = Post.readonly(false)
+ subject.class.should be_scope
+ lambda { subject.first.save }.should_not raise_error(ActiveRecord::ReadOnlyRecord)
end
+
end
View
8 spec/spec_helper.rb
@@ -3,7 +3,13 @@
require 'basic_named_scopes'
require 'spec'
require 'spec/autorun'
+require 'active_record'
+require 'temping'
Spec::Runner.configure do |config|
-
+ config.include(Temping)
+end
+
+def be_scope
+ eql(ActiveRecord::NamedScope::Scope)
end

0 comments on commit 73ade9e

Please sign in to comment.
Something went wrong with that request. Please try again.