jaysus 0.1.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/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+ gem 'activemodel', "~> 3.0.0"
6
+ gem 'activesupport', "~> 3.0.0"
7
+ gem 'rest-client', '~> 1.6.1'
8
+
9
+ # Add dependencies to develop your gem here.
10
+ # Include everything needed to run rake, tests, features, etc.
11
+ group :development do
12
+ gem "bundler", "~> 1.0.0"
13
+ gem 'fakeweb', '~> 1.3.0'
14
+ gem "jeweler", "~> 1.5.2"
15
+ gem "rcov", ">= 0"
16
+ gem "rspec", "~> 2.0.0"
17
+ gem 'ruby-debug'
18
+ end
19
+
data/Gemfile.lock ADDED
@@ -0,0 +1,53 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.0.3)
5
+ activesupport (= 3.0.3)
6
+ builder (~> 2.1.2)
7
+ i18n (~> 0.4)
8
+ activesupport (3.0.3)
9
+ builder (2.1.2)
10
+ columnize (0.3.2)
11
+ diff-lcs (1.1.2)
12
+ fakeweb (1.3.0)
13
+ git (1.2.5)
14
+ i18n (0.5.0)
15
+ jeweler (1.5.2)
16
+ bundler (~> 1.0.0)
17
+ git (>= 1.2.5)
18
+ rake
19
+ linecache (0.43)
20
+ mime-types (1.16)
21
+ rake (0.8.7)
22
+ rcov (0.9.9)
23
+ rest-client (1.6.1)
24
+ mime-types (>= 1.16)
25
+ rspec (2.0.0)
26
+ rspec-core (= 2.0.0)
27
+ rspec-expectations (= 2.0.0)
28
+ rspec-mocks (= 2.0.0)
29
+ rspec-core (2.0.0)
30
+ rspec-expectations (2.0.0)
31
+ diff-lcs (>= 1.1.2)
32
+ rspec-mocks (2.0.0)
33
+ rspec-core (= 2.0.0)
34
+ rspec-expectations (= 2.0.0)
35
+ ruby-debug (0.10.4)
36
+ columnize (>= 0.1)
37
+ ruby-debug-base (~> 0.10.4.0)
38
+ ruby-debug-base (0.10.4)
39
+ linecache (>= 0.3)
40
+
41
+ PLATFORMS
42
+ ruby
43
+
44
+ DEPENDENCIES
45
+ activemodel (~> 3.0.0)
46
+ activesupport (~> 3.0.0)
47
+ bundler (~> 1.0.0)
48
+ fakeweb (~> 1.3.0)
49
+ jeweler (~> 1.5.2)
50
+ rcov
51
+ rest-client (~> 1.6.1)
52
+ rspec (~> 2.0.0)
53
+ ruby-debug
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Paul Campbell
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Jaysus #
2
+
3
+ Jaysus is a local/remote persistence/sync framework for MacRuby. It's designed for keeping local copies of responses from a remote JSON api.
4
+
5
+ ## Usage ##
6
+
7
+ Jaysus::Local.store_dir = '~/.jaysus/'
8
+ Jaysus::Remote.base_url = 'https://user:pass@https://dnsimple.com'
9
+
10
+ module Domain
11
+ class Base < Jaysus::Base
12
+ primary_key :id
13
+ attribute :name
14
+ attribute :name_server_status
15
+ attribute :registrant_id
16
+ attribute :registration_status
17
+ attribute :expires_at
18
+ attribute :created_at
19
+ attribute :updated_at
20
+ attribute :user_id
21
+ end
22
+
23
+ class Local < Base
24
+ include Jaysus::Local
25
+ end
26
+
27
+ class Remote < Base
28
+ include Jaysus::Remote
29
+ end
30
+ end
31
+
32
+ domain = Site::Remote.new
33
+ domain.title = "This"
34
+ domain.user_id = 1
35
+ domain.save
36
+
37
+
38
+ == Copyright
39
+
40
+ Copyright (c) 2011 Paul Campbell. See LICENSE.txt for
41
+ further details.
42
+
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "jaysus"
16
+ gem.homepage = "http://github.com/paulca/jaysus"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{A Ruby library for managing local / remote JSON store}
19
+ gem.description = %Q{Persist remote JSON APIs locally and vice versa}
20
+ gem.email = "paul@rslw.com"
21
+ gem.authors = ["Paul Campbell"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec) do |spec|
32
+ spec.pattern = FileList['spec/**/*_spec.rb']
33
+ end
34
+
35
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "jaysus #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/jaysus.gemspec ADDED
@@ -0,0 +1,98 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{jaysus}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Paul Campbell"]
12
+ s.date = %q{2011-01-16}
13
+ s.description = %q{Persist remote JSON APIs locally and vice versa}
14
+ s.email = %q{paul@rslw.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.md",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "jaysus.gemspec",
29
+ "lib/jaysus.rb",
30
+ "lib/jaysus/base.rb",
31
+ "lib/jaysus/local.rb",
32
+ "lib/jaysus/remote.rb",
33
+ "spec/fixtures/1",
34
+ "spec/fixtures/all.json",
35
+ "spec/fixtures/find_site.json",
36
+ "spec/fixtures/new_site.json",
37
+ "spec/fixtures/update_site.json",
38
+ "spec/local_spec.rb",
39
+ "spec/remote_spec.rb",
40
+ "spec/spec_helper.rb",
41
+ "spec/support/debugger.rb",
42
+ "spec/support/fakeweb.rb",
43
+ "spec/support/jaysus.rb",
44
+ "spec/support/site.rb"
45
+ ]
46
+ s.homepage = %q{http://github.com/paulca/jaysus}
47
+ s.licenses = ["MIT"]
48
+ s.require_paths = ["lib"]
49
+ s.rubygems_version = %q{1.3.7}
50
+ s.summary = %q{A Ruby library for managing local / remote JSON store}
51
+ s.test_files = [
52
+ "spec/local_spec.rb",
53
+ "spec/remote_spec.rb",
54
+ "spec/spec_helper.rb",
55
+ "spec/support/debugger.rb",
56
+ "spec/support/fakeweb.rb",
57
+ "spec/support/jaysus.rb",
58
+ "spec/support/site.rb"
59
+ ]
60
+
61
+ if s.respond_to? :specification_version then
62
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
63
+ s.specification_version = 3
64
+
65
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
66
+ s.add_runtime_dependency(%q<activemodel>, ["~> 3.0.0"])
67
+ s.add_runtime_dependency(%q<activesupport>, ["~> 3.0.0"])
68
+ s.add_runtime_dependency(%q<rest-client>, ["~> 1.6.1"])
69
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
70
+ s.add_development_dependency(%q<fakeweb>, ["~> 1.3.0"])
71
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
72
+ s.add_development_dependency(%q<rcov>, [">= 0"])
73
+ s.add_development_dependency(%q<rspec>, ["~> 2.0.0"])
74
+ s.add_development_dependency(%q<ruby-debug>, [">= 0"])
75
+ else
76
+ s.add_dependency(%q<activemodel>, ["~> 3.0.0"])
77
+ s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
78
+ s.add_dependency(%q<rest-client>, ["~> 1.6.1"])
79
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
80
+ s.add_dependency(%q<fakeweb>, ["~> 1.3.0"])
81
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
82
+ s.add_dependency(%q<rcov>, [">= 0"])
83
+ s.add_dependency(%q<rspec>, ["~> 2.0.0"])
84
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
85
+ end
86
+ else
87
+ s.add_dependency(%q<activemodel>, ["~> 3.0.0"])
88
+ s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
89
+ s.add_dependency(%q<rest-client>, ["~> 1.6.1"])
90
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
91
+ s.add_dependency(%q<fakeweb>, ["~> 1.3.0"])
92
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
93
+ s.add_dependency(%q<rcov>, [">= 0"])
94
+ s.add_dependency(%q<rspec>, ["~> 2.0.0"])
95
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
96
+ end
97
+ end
98
+
data/lib/jaysus.rb ADDED
@@ -0,0 +1,18 @@
1
+ # rubygems
2
+ require 'rubygems'
3
+
4
+ # system dependencies
5
+ require 'fileutils'
6
+ require 'pathname'
7
+
8
+ # gem dependencies
9
+ require 'active_support/core_ext/array/wrap'
10
+ require 'active_support/core_ext/object/blank'
11
+ require 'active_support/secure_random'
12
+ require 'active_model'
13
+ require 'rest_client'
14
+
15
+ # library files
16
+ require 'jaysus/base'
17
+ require 'jaysus/local'
18
+ require 'jaysus/remote'
@@ -0,0 +1,165 @@
1
+ module Jaysus
2
+
3
+ class Base
4
+ extend ActiveModel::Naming
5
+ include ActiveModel::Serialization
6
+ include ActiveModel::Serializers::JSON
7
+
8
+ def self.attribute(name)
9
+ self.attributes << name
10
+ class_eval do
11
+ define_method(name) do # def title
12
+ instance_variable_get("@#{name}") # @title
13
+ end # end
14
+
15
+ define_method("#{name}=") do |value| # def title=(value)
16
+ instance_variable_set("@#{name}", value) # @title = value
17
+ end # end
18
+ end
19
+ end
20
+
21
+ def self.attributes
22
+ @attributes ||= []
23
+ end
24
+
25
+ def self.create(attrs = {})
26
+ new(attrs).save
27
+ end
28
+
29
+ def self.find(id, &block)
30
+ new(decode(id, &block))
31
+ end
32
+
33
+ def self.find_or_create_by_attributes(attributes, *values)
34
+ search = find_by_attributes(attributes, *values)
35
+ return search unless search.blank?
36
+ attrs = {}
37
+ attributes.zip(values).each do |pair|
38
+ attrs[pair.first] = pair.last
39
+ end
40
+ create(attrs)
41
+ end
42
+
43
+ def self.find_by_attributes(attributes, *values)
44
+ find_all_by_attributes(attributes, *values).first
45
+ end
46
+
47
+ def self.find_all_by_attributes(attributes, *values)
48
+ all.each.select do |record|
49
+ attributes.zip(values).all? do |matcher|
50
+ record.send(matcher.first) == matcher.last
51
+ end
52
+ end
53
+ end
54
+
55
+ def self.decode(id, &block)
56
+ ActiveSupport::JSON.decode(
57
+ yield
58
+ )[self.model_name.singular]
59
+ end
60
+
61
+ def self.model_base
62
+ "#{model_name}::Base".constantize
63
+ end
64
+
65
+ def self.local_base
66
+ "#{model_name}::Local".constantize
67
+ end
68
+
69
+ def self.remote_base
70
+ "#{model_name}::Remote".constantize
71
+ end
72
+
73
+ def self.model_name
74
+ ActiveModel::Name.new(super.split('::').first.constantize)
75
+ end
76
+
77
+ def self.plural_name
78
+ model_name.plural
79
+ end
80
+
81
+ def self.singular_name
82
+ model_name.singular
83
+ end
84
+
85
+ def self.primary_key(name = nil)
86
+ @primary_key = name if name.present?
87
+ @primary_key
88
+ end
89
+
90
+ def self.store_file_dir
91
+ dir = Local.store_dir.join(store_file_dir_name)
92
+ dir.mkpath unless dir.exist?
93
+ dir
94
+ end
95
+
96
+ def self.store_file_dir_name
97
+ self.model_name.plural
98
+ end
99
+
100
+ def self.method_missing(method, *args)
101
+ if method.to_s.match(/^find_by/)
102
+ attrs = method.to_s.gsub(/^find_by_/, '').split('_and_')
103
+ find_by_attributes(attrs, *args)
104
+ elsif method.to_s.match(/^find_or_create_by/)
105
+ attrs = method.to_s.gsub(/^find_or_create_by_/, '').split('_and_')
106
+ find_or_create_by_attributes(attrs, *args)
107
+ else
108
+ super
109
+ end
110
+ end
111
+
112
+ def initialize(set_attrs = {})
113
+ set_attributes(set_attrs)
114
+ end
115
+
116
+ def attributes
117
+ out = {}
118
+ self.class.model_base.attributes.each do |attribute|
119
+ out[attribute.to_s] = send(attribute)
120
+ end
121
+ out
122
+ end
123
+
124
+ def attributes=(attrs = {})
125
+ set_attributes(attrs)
126
+ end
127
+
128
+ def destroy(&block)
129
+ yield
130
+ end
131
+
132
+ def update_attributes(attrs)
133
+ set_attributes(attrs)
134
+ save
135
+ end
136
+
137
+ def set_attributes(attrs)
138
+ attrs.each_pair do |attr, value|
139
+ self.send("#{attr}=", value)
140
+ end
141
+ end
142
+
143
+ def save(&block)
144
+ yield if block_given?
145
+ end
146
+
147
+ def store_file
148
+ self.class.store_file_dir.join(store_file_name)
149
+ end
150
+
151
+ def store_file_name
152
+ pk = send(self.class.model_base.primary_key)
153
+ if pk.blank?
154
+ pk = ActiveSupport::SecureRandom.hex(32)
155
+ send("#{self.class.model_base.primary_key}=", pk)
156
+ end
157
+ "#{send(self.class.model_base.primary_key)}"
158
+ end
159
+
160
+ def persisted?
161
+ store_file.exist?
162
+ end
163
+ end
164
+
165
+ end
@@ -0,0 +1,49 @@
1
+ module Jaysus
2
+ module Local
3
+
4
+ def self.store_dir
5
+ @store_dir ||= Pathname.new('.')
6
+ end
7
+
8
+ def self.store_dir=(dir)
9
+ @store_dir = Pathname.new(dir)
10
+ end
11
+
12
+ def self.included(base)
13
+ base.extend(ClassMethods)
14
+ end
15
+
16
+ def destroy
17
+ super do
18
+ store_file.delete
19
+ self
20
+ end
21
+ end
22
+
23
+ def save
24
+ super do
25
+ store_file.open('w') do |file|
26
+ file.write(self.to_json)
27
+ end
28
+ self
29
+ end
30
+ end
31
+
32
+ module ClassMethods
33
+ def all
34
+ records = []
35
+ Dir[store_file_dir.join('*')].each do |id|
36
+ records << find(id)
37
+ end
38
+ records
39
+ end
40
+
41
+ def find(id)
42
+ super do
43
+ store_file_dir.join("#{id}").read
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,72 @@
1
+ module Jaysus
2
+ module Remote
3
+ def self.base_url
4
+ @base_url ||= ''
5
+ end
6
+
7
+ def self.base_url=(url)
8
+ @base_url = url
9
+ end
10
+
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+ end
14
+
15
+ def destroy
16
+ super do
17
+ RestClient.delete(remote_url,{
18
+ 'Accept' => 'application/json'
19
+ })
20
+ end
21
+ end
22
+
23
+ def save
24
+ super do
25
+ response = if pk = self.send(self.class.model_base.primary_key)
26
+ RestClient.put("#{self.class.model_url}/#{pk}", self.to_json, {
27
+ 'Content-Type' => 'application/json'
28
+ })
29
+ else
30
+ RestClient.post(self.class.model_url, self.to_json, {
31
+ 'Content-Type' => 'application/json'
32
+ })
33
+ end
34
+ decoded_response = ActiveSupport::JSON.decode(
35
+ response
36
+ )[self.class.singular_name]
37
+ self.set_attributes(decoded_response)
38
+ self
39
+ end
40
+ end
41
+
42
+ def remote_url
43
+ pk = self.send(self.class.model_base.primary_key)
44
+ return if pk.blank?
45
+ "#{self.class.model_url}/#{pk}"
46
+ end
47
+
48
+ module ClassMethods
49
+ def model_url
50
+ "#{Jaysus::Remote.base_url}/#{self.plural_name}"
51
+ end
52
+
53
+ def all
54
+ records = []
55
+ ActiveSupport::JSON.decode(RestClient.get(model_url,{
56
+ 'Accept' => 'application/json'
57
+ })).each do |raw_record|
58
+ records << new(raw_record[self.singular_name])
59
+ end
60
+ records
61
+ end
62
+
63
+ def find(id)
64
+ super do
65
+ RestClient.get("#{model_url}/#{id}",{
66
+ 'Accept' => 'application/json'
67
+ })
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
data/spec/fixtures/1 ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "site": {
3
+ "id": 1,
4
+ "title": "A nice fixture",
5
+ "user_id": 1
6
+ }
7
+ }
@@ -0,0 +1,9 @@
1
+ [
2
+ {
3
+ "site": {
4
+ "id": 42,
5
+ "title": "I'm from all",
6
+ "user_id": 42
7
+ }
8
+ }
9
+ ]
@@ -0,0 +1,7 @@
1
+ {
2
+ "site": {
3
+ "id": 42,
4
+ "title": "The Answer to Life, the Universe and Everything",
5
+ "user_id": 42
6
+ }
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "site": {
3
+ "id": 2,
4
+ "title": "New Site",
5
+ "user_id": 2
6
+ }
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "site": {
3
+ "id": 42,
4
+ "title": "Monster!",
5
+ "user_id": 42
6
+ }
7
+ }
@@ -0,0 +1,77 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Jaysus::Local do
4
+ let(:site) { Site::Local.new({ :title => "New Site", :user_id => 1 }) }
5
+
6
+ describe Site::Local do
7
+ subject { Site::Local }
8
+ its(:model_name) { should == 'Site' }
9
+ its(:store_file_dir_name) { should == 'sites' }
10
+ end
11
+
12
+ describe "finder methods" do
13
+ before(:each) { FileUtils.cp('spec/fixtures/1', Site::Local.store_file_dir) }
14
+
15
+ describe ".all" do
16
+ subject { Site::Local.all }
17
+ its(:length) { should == 1}
18
+ its(:first) { should be_a_kind_of(Site::Local) }
19
+ end
20
+
21
+ describe ".find" do
22
+ subject { Site::Local.find(1) }
23
+ it { should_not be_nil }
24
+ its(:title) { should == "A nice fixture" }
25
+ end
26
+
27
+ describe ".find_by_x" do
28
+ subject { Site::Local.find_by_title("A nice fixture") }
29
+ it { should_not be_nil }
30
+ its(:title) { should == "A nice fixture" }
31
+ end
32
+
33
+ describe ".find_or_create_by_x" do
34
+ subject { Site::Local.find_or_create_by_id(2) }
35
+ it { should_not be_nil }
36
+ its(:title) { should be_blank }
37
+ its(:id) { should == 2 }
38
+ end
39
+ end
40
+
41
+ describe ".new" do
42
+ subject { site }
43
+
44
+ its(:title) { should == "New Site"}
45
+ its(:user_id) { should == 1 }
46
+ end
47
+
48
+ describe "#to_json" do
49
+ let(:decoded_site) { ActiveSupport::JSON.decode(site.to_json)['site'] }
50
+
51
+ it("should have a title") { decoded_site['title'].should == "New Site" }
52
+ it("should have a user id"){ decoded_site['user_id'].should == 1 }
53
+ end
54
+
55
+ describe "#save" do
56
+ subject { site }
57
+
58
+ before do
59
+ site.save
60
+ end
61
+
62
+ it { should be_persisted }
63
+ its(:id) { should be_a_kind_of(String) }
64
+ end
65
+
66
+ describe "#update_attributes" do
67
+ subject { site.update_attributes(:title => "Newer Site")}
68
+ its(:title) { should == "Newer Site" }
69
+ end
70
+
71
+ describe "#destroy" do
72
+ before { site.save; site.destroy }
73
+ subject { site.store_file }
74
+ it { should_not exist }
75
+ end
76
+
77
+ end
@@ -0,0 +1,90 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Jaysus::Remote do
4
+ let(:site) { Site::Remote.new({ :title => "New Site" }) }
5
+
6
+ describe ".all" do
7
+ before do
8
+ RestClient.should_receive(:get).with(
9
+ 'http://testapi/sites',
10
+ {
11
+ 'Accept' => 'application/json'
12
+ }
13
+ ).and_return(File.read('spec/fixtures/all.json'))
14
+ end
15
+ subject { Site::Remote.all.first }
16
+ it { should_not be_nil }
17
+ its(:title) { should == "I'm from all" }
18
+ end
19
+
20
+ describe ".find" do
21
+ before do
22
+ RestClient.should_receive(:get).with(
23
+ 'http://testapi/sites/42',
24
+ {
25
+ 'Accept' => 'application/json'
26
+ }
27
+ ).and_return(File.read('spec/fixtures/find_site.json'))
28
+ end
29
+ subject { Site::Remote.find(42) }
30
+ it { should_not be_nil }
31
+ its(:title) { should == 'The Answer to Life, the Universe and Everything'}
32
+ its(:user_id) { should == 42 }
33
+ end
34
+
35
+ describe "#save" do
36
+ before do
37
+ RestClient.should_receive(:post).with(
38
+ 'http://testapi/sites',
39
+ site.to_json,
40
+ {
41
+ 'Content-Type' => 'application/json'
42
+ }
43
+ ).and_return(File.read('spec/fixtures/new_site.json'))
44
+ site.save
45
+ end
46
+
47
+ subject { site }
48
+ its(:id) { should == 2 }
49
+ its(:title) { should == "New Site" }
50
+ end
51
+
52
+ describe "#update_attributes" do
53
+ before do
54
+ RestClient.should_receive(:get).with(
55
+ 'http://testapi/sites/42',
56
+ {
57
+ 'Accept' => 'application/json'
58
+ }
59
+ ).and_return(File.read('spec/fixtures/find_site.json'))
60
+
61
+ RestClient.should_receive(:put).with(
62
+ 'http://testapi/sites/42',
63
+ "{\"site\":{\"title\":\"Monster!\",\"id\":42,\"user_id\":42}}",
64
+ {
65
+ 'Content-Type' => 'application/json'
66
+ }
67
+ ).and_return(File.read('spec/fixtures/update_site.json'))
68
+ end
69
+
70
+ let(:site) { Site::Remote.find(42) }
71
+ subject { site.update_attributes(:title => 'Monster!') }
72
+
73
+ its(:title){ should == 'Monster!'}
74
+ end
75
+
76
+ describe "#destroy" do
77
+ before do
78
+ RestClient.should_receive(:delete).with(
79
+ 'http://testapi/sites/42',
80
+ {
81
+ 'Accept' => 'application/json'
82
+ }
83
+ )
84
+ end
85
+ let(:site) { Site::Remote.find(42) }
86
+ it "should be gone" do
87
+ site.destroy
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,16 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'jaysus'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+ config.after(:all) do
12
+ Dir[File.expand_path(File.dirname(__FILE__) + '/store/*')].each do |file|
13
+ FileUtils.rm_rf(file)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ begin
2
+ require 'ruby-debug'
3
+ Debugger.settings[:autoeval] = true
4
+ rescue LoadError
5
+ puts "could not load ruby-debug"
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'fakeweb'
2
+ FakeWeb.allow_net_connect = false
3
+
4
+ FakeWeb.register_uri(:get, 'http://testapi/sites/42', {
5
+ :body => File.read('spec/fixtures/find_site.json')
6
+ })
@@ -0,0 +1,3 @@
1
+ Jaysus::Local.store_dir = File.expand_path(File.dirname(__FILE__) + '/../store/')
2
+
3
+ Jaysus::Remote.base_url = 'http://testapi'
@@ -0,0 +1,16 @@
1
+ module Site
2
+ class Base < Jaysus::Base
3
+ primary_key :id
4
+ attribute :id
5
+ attribute :title
6
+ attribute :user_id
7
+ end
8
+
9
+ class Local < Base
10
+ include Jaysus::Local
11
+ end
12
+
13
+ class Remote < Base
14
+ include Jaysus::Remote
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,237 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jaysus
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Paul Campbell
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-16 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :runtime
23
+ prerelease: false
24
+ name: activemodel
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ hash: 7
31
+ segments:
32
+ - 3
33
+ - 0
34
+ - 0
35
+ version: 3.0.0
36
+ requirement: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ type: :runtime
39
+ prerelease: false
40
+ name: activesupport
41
+ version_requirements: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ hash: 7
47
+ segments:
48
+ - 3
49
+ - 0
50
+ - 0
51
+ version: 3.0.0
52
+ requirement: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ type: :runtime
55
+ prerelease: false
56
+ name: rest-client
57
+ version_requirements: &id003 !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ hash: 13
63
+ segments:
64
+ - 1
65
+ - 6
66
+ - 1
67
+ version: 1.6.1
68
+ requirement: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ type: :development
71
+ prerelease: false
72
+ name: bundler
73
+ version_requirements: &id004 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ hash: 23
79
+ segments:
80
+ - 1
81
+ - 0
82
+ - 0
83
+ version: 1.0.0
84
+ requirement: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ type: :development
87
+ prerelease: false
88
+ name: fakeweb
89
+ version_requirements: &id005 !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ~>
93
+ - !ruby/object:Gem::Version
94
+ hash: 27
95
+ segments:
96
+ - 1
97
+ - 3
98
+ - 0
99
+ version: 1.3.0
100
+ requirement: *id005
101
+ - !ruby/object:Gem::Dependency
102
+ type: :development
103
+ prerelease: false
104
+ name: jeweler
105
+ version_requirements: &id006 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ hash: 7
111
+ segments:
112
+ - 1
113
+ - 5
114
+ - 2
115
+ version: 1.5.2
116
+ requirement: *id006
117
+ - !ruby/object:Gem::Dependency
118
+ type: :development
119
+ prerelease: false
120
+ name: rcov
121
+ version_requirements: &id007 !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: 3
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ requirement: *id007
131
+ - !ruby/object:Gem::Dependency
132
+ type: :development
133
+ prerelease: false
134
+ name: rspec
135
+ version_requirements: &id008 !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ~>
139
+ - !ruby/object:Gem::Version
140
+ hash: 15
141
+ segments:
142
+ - 2
143
+ - 0
144
+ - 0
145
+ version: 2.0.0
146
+ requirement: *id008
147
+ - !ruby/object:Gem::Dependency
148
+ type: :development
149
+ prerelease: false
150
+ name: ruby-debug
151
+ version_requirements: &id009 !ruby/object:Gem::Requirement
152
+ none: false
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ hash: 3
157
+ segments:
158
+ - 0
159
+ version: "0"
160
+ requirement: *id009
161
+ description: Persist remote JSON APIs locally and vice versa
162
+ email: paul@rslw.com
163
+ executables: []
164
+
165
+ extensions: []
166
+
167
+ extra_rdoc_files:
168
+ - LICENSE.txt
169
+ - README.md
170
+ files:
171
+ - .document
172
+ - .rspec
173
+ - Gemfile
174
+ - Gemfile.lock
175
+ - LICENSE.txt
176
+ - README.md
177
+ - Rakefile
178
+ - VERSION
179
+ - jaysus.gemspec
180
+ - lib/jaysus.rb
181
+ - lib/jaysus/base.rb
182
+ - lib/jaysus/local.rb
183
+ - lib/jaysus/remote.rb
184
+ - spec/fixtures/1
185
+ - spec/fixtures/all.json
186
+ - spec/fixtures/find_site.json
187
+ - spec/fixtures/new_site.json
188
+ - spec/fixtures/update_site.json
189
+ - spec/local_spec.rb
190
+ - spec/remote_spec.rb
191
+ - spec/spec_helper.rb
192
+ - spec/support/debugger.rb
193
+ - spec/support/fakeweb.rb
194
+ - spec/support/jaysus.rb
195
+ - spec/support/site.rb
196
+ has_rdoc: true
197
+ homepage: http://github.com/paulca/jaysus
198
+ licenses:
199
+ - MIT
200
+ post_install_message:
201
+ rdoc_options: []
202
+
203
+ require_paths:
204
+ - lib
205
+ required_ruby_version: !ruby/object:Gem::Requirement
206
+ none: false
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ hash: 3
211
+ segments:
212
+ - 0
213
+ version: "0"
214
+ required_rubygems_version: !ruby/object:Gem::Requirement
215
+ none: false
216
+ requirements:
217
+ - - ">="
218
+ - !ruby/object:Gem::Version
219
+ hash: 3
220
+ segments:
221
+ - 0
222
+ version: "0"
223
+ requirements: []
224
+
225
+ rubyforge_project:
226
+ rubygems_version: 1.3.7
227
+ signing_key:
228
+ specification_version: 3
229
+ summary: A Ruby library for managing local / remote JSON store
230
+ test_files:
231
+ - spec/local_spec.rb
232
+ - spec/remote_spec.rb
233
+ - spec/spec_helper.rb
234
+ - spec/support/debugger.rb
235
+ - spec/support/fakeweb.rb
236
+ - spec/support/jaysus.rb
237
+ - spec/support/site.rb