scam 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in scam.gemspec
4
+ gemspec
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ scam (0.1.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.2)
10
+ rspec (2.3.0)
11
+ rspec-core (~> 2.3.0)
12
+ rspec-expectations (~> 2.3.0)
13
+ rspec-mocks (~> 2.3.0)
14
+ rspec-core (2.3.1)
15
+ rspec-expectations (2.3.0)
16
+ diff-lcs (~> 1.1.2)
17
+ rspec-mocks (2.3.0)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ rspec (~> 2.3)
24
+ scam!
@@ -0,0 +1,56 @@
1
+ = Scam
2
+
3
+ Really basic model-ish thing for creating different types in your application easily.
4
+
5
+ I use this whenever I want something to do psuedo belongs to/has many relationships, but do not want to back a model with a database as the data does not change often, if ever.
6
+
7
+ == Usage
8
+
9
+ Just create a class and include scam.
10
+
11
+ class FeedTemplate
12
+ include Scam
13
+
14
+ attr_accessor :title, :icon, :instructions, :template, :format, :label
15
+
16
+ def expand(value)
17
+ url = template.gsub('{value}', URI.escape(value))
18
+ url = "http://#{url}" if url !~ /https?\:\/\//
19
+ url
20
+ end
21
+
22
+ def parse(body)
23
+ case format
24
+ when 'json'
25
+ ActiveSupport::JSON.decode(body)
26
+ when 'feed'
27
+ Feedzirra::Feed.parse(body).to_hash
28
+ end
29
+ end
30
+ end
31
+
32
+ FeedTemplate.create({
33
+ :id => 1,
34
+ :title => 'Twitter',
35
+ :label => 'Twitter Username',
36
+ :icon => 'twitter',
37
+ :instructions => 'Enter your Twitter username',
38
+ :format => 'json',
39
+ :template => 'http://twitter.com/statuses/user_timeline/{value}.json',
40
+ })
41
+
42
+ Attributes are just defined using attr_accessor. :id is added when you include Scam.
43
+
44
+ == Note on Patches/Pull Requests
45
+
46
+ * Fork the project.
47
+ * Make your feature addition or bug fix.
48
+ * Add tests for it. This is important so I don't break it in a
49
+ future version unintentionally.
50
+ * Commit, do not mess with rakefile, version, or history.
51
+ (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)
52
+ * Send me a pull request. Bonus points for topic branches.
53
+
54
+ == Copyright
55
+
56
+ Copyright (c) 2010 John Nunemaker. See LICENSE for details.
@@ -0,0 +1,6 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new
6
+ task :default => :spec
@@ -0,0 +1,28 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
2
+ require 'pp'
3
+ require 'scam'
4
+
5
+ class FeedTemplate
6
+ include Scam
7
+
8
+ attr_accessor :title
9
+ end
10
+
11
+ FeedTemplate.create(:id => 1, :title => 'Twitter')
12
+ FeedTemplate.create(:id => 2, :title => 'Dribble')
13
+
14
+ pp FeedTemplate.all
15
+
16
+ # Enumerable is on the class so you can just iterate it
17
+ FeedTemplate.each do |tpl|
18
+ pp tpl
19
+ end
20
+
21
+ # detect, select, include, etc
22
+ pp FeedTemplate.detect { |tpl| tpl.title == 'Twitter' }
23
+
24
+ # find by id
25
+ pp FeedTemplate.find(2)
26
+
27
+ # works with string id
28
+ pp FeedTemplate.find('2')
@@ -0,0 +1,17 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
2
+ require 'pp'
3
+ require 'scam'
4
+
5
+ class FeedTemplate
6
+ include Scam
7
+
8
+ sorted_by :title
9
+
10
+ attr_accessor :title
11
+ end
12
+
13
+ FeedTemplate.create(:id => 1, :title => 'Twitter')
14
+ FeedTemplate.create(:id => 2, :title => 'Dribble')
15
+
16
+ # Sorted by title instead of id so dribble will be first and twitter second
17
+ pp FeedTemplate.all
@@ -0,0 +1,52 @@
1
+ module Scam
2
+ def self.included(base)
3
+ base.class_eval do
4
+ class << self
5
+ include Enumerable
6
+ end
7
+ attr_accessor :id
8
+ end
9
+ base.extend(ClassMethods)
10
+ end
11
+
12
+ module ClassMethods
13
+ def all
14
+ instances.sort_by { |i| i.send(sorted_by) }
15
+ end
16
+
17
+ def sorted_by(attribute=nil)
18
+ @sorted_by = attribute unless attribute.nil?
19
+ @sorted_by = :id if @sorted_by.nil?
20
+ @sorted_by
21
+ end
22
+
23
+ def create(attrs={})
24
+ new(attrs).tap { |i| instances << i }
25
+ end
26
+
27
+ def each
28
+ instances.each { |i| yield(i) }
29
+ end
30
+
31
+ def find(id)
32
+ detect { |i| i.id == id.to_i }
33
+ end
34
+
35
+ alias [] find
36
+
37
+ def instances
38
+ @instances ||= []
39
+ end
40
+ private :instances
41
+ end
42
+
43
+ def initialize(attrs={})
44
+ attrs.each { |key, value| send("#{key}=", value) }
45
+ end
46
+
47
+ def eql?(other)
48
+ other.class == self.class && other.id == id
49
+ end
50
+
51
+ alias == eql?
52
+ end
@@ -0,0 +1,3 @@
1
+ module Scam
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "scam/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "scam"
7
+ s.version = Scam::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["John Nunemaker"]
10
+ s.email = ["nunemaker@gmail.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Really basic fake model for type-ish stuff}
13
+ s.description = %q{Really basic fake model for type-ish stuff}
14
+
15
+ s.add_development_dependency 'rspec', '~> 2.3'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,17 @@
1
+ $:.unshift(File.expand_path('../../lib', __FILE__))
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+
6
+ Bundler.require(:default, :development)
7
+
8
+ require 'scam'
9
+ require 'support/constants'
10
+
11
+ Rspec.configure do |config|
12
+ config.include(Support::Constants)
13
+
14
+ config.before(:each) do
15
+
16
+ end
17
+ end
@@ -0,0 +1,155 @@
1
+ require 'helper'
2
+
3
+ describe Scam do
4
+ uses_constants('FeedTemplate')
5
+
6
+ context "including Scam" do
7
+ it "adds id attr accessor" do
8
+ template = FeedTemplate.new
9
+ template.id = 5
10
+ template.id.should == 5
11
+ end
12
+ end
13
+
14
+ context "class enumerable" do
15
+ it "works" do
16
+ t1 = FeedTemplate.create(:id => 1)
17
+ t2 = FeedTemplate.create(:id => 2)
18
+ FeedTemplate.inject([]) { |acc, t| acc << t; acc }.should == [t1, t2]
19
+ FeedTemplate.detect { |t| t.id == 1 }.should == t1
20
+ end
21
+ end
22
+
23
+ describe ".sorted_by" do
24
+ it "defaults to id" do
25
+ FeedTemplate.sorted_by.should == :id
26
+ end
27
+
28
+ it "gets/sets sorted_by" do
29
+ FeedTemplate.sorted_by(:position)
30
+ FeedTemplate.sorted_by.should == :position
31
+ end
32
+ end
33
+
34
+ describe ".all" do
35
+ context "default sort by" do
36
+ before do
37
+ FeedTemplate.create(:id => 2)
38
+ FeedTemplate.create(:id => 1)
39
+ end
40
+
41
+ it "returns all instances sorted by id" do
42
+ FeedTemplate.all.map(&:id).should == [1, 2]
43
+ end
44
+ end
45
+
46
+ context "custom sort by" do
47
+ before do
48
+ FeedTemplate.sorted_by(:position)
49
+ FeedTemplate.send(:attr_accessor, :position)
50
+ FeedTemplate.create(:id => 2, :position => 1)
51
+ FeedTemplate.create(:id => 1, :position => 2)
52
+ end
53
+
54
+ it "returns all instances sorted by custom attribute" do
55
+ FeedTemplate.all.map(&:id).should == [2, 1]
56
+ end
57
+ end
58
+ end
59
+
60
+ describe ".initialize" do
61
+ before do
62
+ @template = FeedTemplate.new(:id => 5)
63
+ end
64
+
65
+ it "sets attributes" do
66
+ @template.id.should == 5
67
+ end
68
+ end
69
+
70
+ describe ".find" do
71
+ before do
72
+ @template = FeedTemplate.create(:id => 1)
73
+ end
74
+
75
+ context "with integer id" do
76
+ it "returns instance if found" do
77
+ FeedTemplate.find(1).should == @template
78
+ end
79
+ end
80
+
81
+ context "with string id" do
82
+ it "returns instance if found" do
83
+ FeedTemplate.find('1').should == @template
84
+ end
85
+ end
86
+
87
+ it "returns nil if not found" do
88
+ FeedTemplate.find(20000000000).should be_nil
89
+ end
90
+ end
91
+
92
+ describe ".[]" do
93
+ before do
94
+ @template = FeedTemplate.create(:id => 1)
95
+ end
96
+
97
+ context "with integer id" do
98
+ it "returns instance if found" do
99
+ FeedTemplate[1].should == @template
100
+ end
101
+ end
102
+
103
+ context "with string id" do
104
+ it "returns instance if found" do
105
+ FeedTemplate['1'].should == @template
106
+ end
107
+ end
108
+
109
+ it "returns nil if not found" do
110
+ FeedTemplate[1111122].should be_nil
111
+ end
112
+ end
113
+
114
+ describe ".create" do
115
+ before do
116
+ @template = FeedTemplate.create(:id => 1)
117
+ end
118
+
119
+ it "returns instance" do
120
+ @template.should be_instance_of(FeedTemplate)
121
+ end
122
+
123
+ it "adds model to list" do
124
+ FeedTemplate.should include(@template)
125
+ end
126
+ end
127
+
128
+ describe "#eql?" do
129
+ it "returns true if same class and id" do
130
+ FeedTemplate.new(:id => 1).should eql(FeedTemplate.new(:id => 1))
131
+ end
132
+
133
+ it "returns false if different class" do
134
+ FeedTemplate.new(:id => 1).should_not eql(Class.new.new)
135
+ end
136
+
137
+ it "returns false if different id" do
138
+ FeedTemplate.new(:id => 1).should_not eql(FeedTemplate.new(:id => 2))
139
+ end
140
+ end
141
+
142
+ describe "#==" do
143
+ it "returns true if same class and id" do
144
+ FeedTemplate.new(:id => 1).should == FeedTemplate.new(:id => 1)
145
+ end
146
+
147
+ it "returns false if different class" do
148
+ FeedTemplate.new(:id => 1).should_not == Class.new.new
149
+ end
150
+
151
+ it "returns false if different id" do
152
+ FeedTemplate.new(:id => 1).should_not == FeedTemplate.new(:id => 2)
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,40 @@
1
+ module Support
2
+ module Constants
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def uses_constants(*constants)
9
+ before { create_constants(*constants) }
10
+ end
11
+ end
12
+
13
+ def create_constants(*constants)
14
+ constants.each { |constant| create_constant(constant) }
15
+ end
16
+
17
+ def remove_constants(*constants)
18
+ constants.each { |constant| remove_constant(constant) }
19
+ end
20
+
21
+ def create_constant(constant)
22
+ remove_constant(constant)
23
+ Object.const_set(constant, Model(constant))
24
+ end
25
+
26
+ def remove_constant(constant)
27
+ Object.send(:remove_const, constant) if Object.const_defined?(constant)
28
+ end
29
+
30
+ def Model(name=nil)
31
+ Class.new.tap do |model|
32
+ model.class_eval """
33
+ def self.name; '#{name}' end
34
+ def self.to_s; '#{name}' end
35
+ """ if name
36
+ model.send(:include, Scam)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,45 @@
1
+ def growl(title, msg, img)
2
+ %x{growlnotify -m #{ msg.inspect} -t #{title.inspect} --image ~/.watchr/#{img}.png}
3
+ end
4
+
5
+ def form_growl_message(str)
6
+ msg = str.split("\n").last
7
+ if msg =~ /(\d)\sfailure/
8
+ img = $1.to_i > 0 ? 'fail' : 'pass'
9
+ end
10
+ growl 'Results', msg, img
11
+ end
12
+
13
+ def run(cmd)
14
+ puts cmd
15
+ output = ""
16
+ IO.popen(cmd) do |com|
17
+ com.each_char do |c|
18
+ print c
19
+ output << c
20
+ $stdout.flush
21
+ end
22
+ end
23
+ form_growl_message output
24
+ end
25
+
26
+ def run_spec(path)
27
+ path.gsub!('lib/', 'spec/')
28
+ path.gsub!('_spec', '')
29
+ file_name = File.basename(path, '.rb')
30
+ path.gsub!(file_name, file_name + "_spec")
31
+ run %Q(bundle exec rspec #{path})
32
+ end
33
+
34
+ watch('spec/helper\.rb') { system('clear'); run('rake') }
35
+ watch('lib/.*\.rb') { |m| system('clear'); run_spec(m[0]) }
36
+ watch('spec/.*_spec\.rb') { |m| system('clear'); run_spec(m[0]) }
37
+
38
+ # Ctrl-\
39
+ Signal.trap('QUIT') do
40
+ puts " --- Running all tests ---\n\n"
41
+ run('rake')
42
+ end
43
+
44
+ # Ctrl-C
45
+ Signal.trap('INT') { abort("\n") }
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: scam
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
+ platform: ruby
12
+ authors:
13
+ - John Nunemaker
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-28 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 5
30
+ segments:
31
+ - 2
32
+ - 3
33
+ version: "2.3"
34
+ type: :development
35
+ version_requirements: *id001
36
+ description: Really basic fake model for type-ish stuff
37
+ email:
38
+ - nunemaker@gmail.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - .gitignore
47
+ - Gemfile
48
+ - Gemfile.lock
49
+ - README.rdoc
50
+ - Rakefile
51
+ - examples/simple.rb
52
+ - examples/sorted.rb
53
+ - lib/scam.rb
54
+ - lib/scam/version.rb
55
+ - scam.gemspec
56
+ - spec/helper.rb
57
+ - spec/scam_spec.rb
58
+ - spec/support/constants.rb
59
+ - specs.watchr
60
+ has_rdoc: true
61
+ homepage: ""
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options: []
66
+
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.7
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Really basic fake model for type-ish stuff
94
+ test_files:
95
+ - spec/helper.rb
96
+ - spec/scam_spec.rb
97
+ - spec/support/constants.rb