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.
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +24 -0
- data/README.rdoc +56 -0
- data/Rakefile +6 -0
- data/examples/simple.rb +28 -0
- data/examples/sorted.rb +17 -0
- data/lib/scam.rb +52 -0
- data/lib/scam/version.rb +3 -0
- data/scam.gemspec +21 -0
- data/spec/helper.rb +17 -0
- data/spec/scam_spec.rb +155 -0
- data/spec/support/constants.rb +40 -0
- data/specs.watchr +45 -0
- metadata +97 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -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!
|
data/README.rdoc
ADDED
@@ -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.
|
data/Rakefile
ADDED
data/examples/simple.rb
ADDED
@@ -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')
|
data/examples/sorted.rb
ADDED
@@ -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
|
data/lib/scam.rb
ADDED
@@ -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
|
data/lib/scam/version.rb
ADDED
data/scam.gemspec
ADDED
@@ -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
|
data/spec/helper.rb
ADDED
@@ -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
|
data/spec/scam_spec.rb
ADDED
@@ -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
|
data/specs.watchr
ADDED
@@ -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
|