betty_resource 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ .DS_Store
2
+ .bundle
3
+ .rvmrc
4
+ *.gem
5
+ coverage/*
6
+ pkg/*
7
+ Gemfile.lock
8
+ .credentials
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,16 @@
1
+ = BettyResource CHANGELOG
2
+
3
+ === Version 0.0.5 / 2012-03-01
4
+
5
+ * Created by Chiel
6
+
7
+ === Version 0.0.6 / 2013-01-22
8
+
9
+ === Version 0.0.7 / 2013-01-22
10
+
11
+ * 5 improvements:
12
+
13
+ * Add changelog generation script
14
+ * Adjust author information
15
+ * Remove some sensitive details
16
+ * We have a hard dependency on multi_json
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :gem_default do
6
+ gem "betty_resource", :path => "."
7
+ gem "colorize"
8
+ gem "pry"
9
+ end
10
+
11
+ group :gem_test do
12
+ gem "minitest"
13
+ gem "mocha", :require => "mocha/setup"
14
+ gem "simplecov", ">= 0.4.0"
15
+ end
data/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # BettyResource
2
+
3
+ Map Betty5 application resources to Ruby objects through the JSON API!
4
+
5
+ ## Introduction
6
+
7
+ This gem is created to map resources directly to the Betty5 API with ease. Just include the gem in your Gemfile, configure the Betty5 API credentials and your good to go!
8
+
9
+ ## Installation
10
+
11
+ ### Add `BettyResource` to your Gemfile
12
+
13
+ gem "betty_resource"
14
+
15
+ ### Install the gem dependencies
16
+
17
+ $ bundle
18
+
19
+ ### Configure the Betty5 API credentials
20
+
21
+ At first, you will need to create a user within the Betty5 application provided with an `api_password`. Ask one of the BettyBlocks developers for more information.
22
+
23
+ Afterwards, add the following in a Ruby file which gets required at startup of the application (e.g. within an `initializer`).
24
+
25
+ BettyResource.configure do |config|
26
+ config.host = "https://<identifier>.bettyblocks.com"
27
+ config.user = <user email>
28
+ config.password = <user api password>
29
+ end
30
+
31
+ ## Usage
32
+
33
+ Using `BettyResource` is pretty straightforward. Let's say you want to load, edit and save a record of the `Relation` model with ID 1:
34
+
35
+ $ relation = BettyResource::Relation.get 1
36
+ $ relation.first_name = "Paul"
37
+ $ relation.save #=> true
38
+
39
+ ## Using the console
40
+
41
+ The BettyResource repo is provided with `script/console` which you can use for development / testing purposes.
42
+
43
+ Run the following command in your console:
44
+
45
+ $ script/console
46
+ Loading BettyResource development environment
47
+ Configured connection
48
+ [1] pry(main)> r = BettyResource::Relation.get 1
49
+ => #<Relation id: 1, last_name: "Willemse", first_name: "Daniel">
50
+ [2] pry(main)> r.dirty?
51
+ => false
52
+ [3] pry(main)> r.first_name = "Paul"
53
+ => "Paul"
54
+ [4] pry(main)> r.dirty?
55
+ => true
56
+ [5] pry(main)> r.changes
57
+ => {"first_name"=>["Daniel", "Paul"]}
58
+ [6] pry(main)> r.first_name_changed?
59
+ => true
60
+ [7] pry(main)> r.first_name_change
61
+ => ["Daniel", "Paul"]
62
+ [8] pry(main)> r.first_name_was
63
+ => "Daniel"
64
+ [9] pry(main)> r.save
65
+ => true
66
+ [10] pry(main)> r.dirty?
67
+ => false
68
+ [11] pry(main)> BettyResource::Relation.get(r.id).first_name
69
+ => "Paul"
70
+
71
+ ## Testing
72
+
73
+ Run the following command for testing:
74
+
75
+ $ rake
76
+
77
+ You can also run a single test:
78
+
79
+ $ ruby test/unit/model/test_record.rb
80
+
81
+ ## TODO
82
+
83
+ * Typecasting of attributes
84
+
85
+ ## Contact us
86
+
87
+ For support, remarks and requests, please mail us at [support@bettyblocks.com](mailto:support@bettyblocks.com).
88
+
89
+ ## License
90
+
91
+ Copyright (c) 2013 BettyBlocks B.V.
92
+
93
+ [http://bettyblocks.com](http://bettyblocks.com) - [info@bettyblocks.com](mailto:info@bettyblocks.com)
data/Rakefile ADDED
@@ -0,0 +1,77 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ desc "Changelog"
11
+ task :changelog do
12
+ tag = ENV["FROM"] || `git describe --abbrev=0 --tags`.strip
13
+ range = [tag, "HEAD"].compact.join ".."
14
+ cmd = "git log --no-merges #{range} '--format=tformat:%B|||%aN|||%aE|||'"
15
+ now = Time.new.strftime "%Y-%m-%d"
16
+
17
+ changes = `#{cmd}`.split(/\|\|\|/).each_slice(3).map do |msg, author, email|
18
+ msg.split(/\n/).reject { |s| s.empty? }
19
+ end
20
+
21
+ changes = changes.flatten
22
+
23
+ next if changes.empty?
24
+
25
+ $changes = Hash.new { |h,k| h[k] = [] }
26
+
27
+ codes = {
28
+ "!" => :major,
29
+ "+" => :minor,
30
+ "*" => :minor,
31
+ "-" => :bug,
32
+ "?" => :unknown,
33
+ }
34
+
35
+ codes_re = Regexp.escape codes.keys.join
36
+
37
+ changes.each do |change|
38
+ if change =~ /^\s*([#{codes_re}])\s*(.*)/ then
39
+ code, line = codes[$1], $2
40
+ else
41
+ code, line = codes["?"], change.chomp
42
+ end
43
+
44
+ $changes[code] << line
45
+ end
46
+
47
+ puts "=== #{ENV['VERSION'] || 'NEXT'} / #{now}"
48
+ puts
49
+ changelog_section :major
50
+ changelog_section :minor
51
+ changelog_section :bug
52
+ changelog_section :unknown
53
+ puts
54
+ end
55
+
56
+ def changelog_section code
57
+ name = {
58
+ :major => "major enhancement",
59
+ :minor => "minor enhancement",
60
+ :bug => "bug fix",
61
+ :unknown => "unknown",
62
+ }[code]
63
+
64
+ changes = $changes[code]
65
+ count = changes.size
66
+ name += "s" if count > 1
67
+ name.sub!(/fixs/, 'fixes')
68
+
69
+ return if count < 1
70
+
71
+ puts "* #{count} #{name}:"
72
+ puts
73
+ changes.sort.each do |line|
74
+ puts " * #{line}"
75
+ end
76
+ puts
77
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'betty_resource/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "betty_resource"
8
+ gem.version = BettyResource::VERSION
9
+ gem.authors = ["Chiel Wester", "Stephan Kaag", "Daniel Willemse", "Paul Engel"]
10
+ gem.email = ["chiel.wester@holder.nl", "stephan.kaag@bettyblocks.com", "daniel.willemse@holder.nl", "paul.engel@bettyblocks.com"]
11
+ gem.description = %q{Map Betty5 application resources to Ruby objects through the JSON API}
12
+ gem.summary = %q{Map Betty5 application resources to Ruby objects}
13
+ gem.homepage = "https://github.com/bettyblocks/betty_resource"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ gem.platform = Gem::Platform::RUBY
20
+
21
+ gem.add_dependency "httparty"
22
+ gem.add_dependency "activesupport"
23
+ gem.add_dependency "crack"
24
+ gem.add_dependency "dirty_hashy", "0.1.3"
25
+ gem.add_dependency "multi_json"
26
+ gem.add_development_dependency "minitest"
27
+ end
@@ -0,0 +1,10 @@
1
+ module BettyResource
2
+ class Api
3
+ include HTTParty
4
+
5
+ base_uri "#{BettyResource.config.host}/api"
6
+ format :json
7
+ basic_auth BettyResource.config.user, BettyResource.config.password
8
+
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ require "singleton"
2
+
3
+ module BettyResource
4
+ class Configuration
5
+ def initialize(args = {})
6
+ args.each do |key, value|
7
+ self.send("#{key}=", value) if [:host, :user, :password].include?(key.to_sym)
8
+ end
9
+ end
10
+
11
+ class InvalidError < StandardError; end
12
+
13
+ attr_accessor :host, :user, :password
14
+
15
+ def validate!
16
+ raise InvalidError if [:host, :user, :password].any?{|option| send(option).to_s.strip.empty?}
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ module BettyResource
2
+ class MetaData
3
+
4
+ def models
5
+ @models ||= BettyResource::Model.parse(Api.get("/models").parsed_response)
6
+ end
7
+
8
+ def model(name)
9
+ models[name.to_s]
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module BettyResource
2
+ class Model
3
+ class Property
4
+ attr_accessor :id, :name, :kind, :options
5
+
6
+ def self.parse(input)
7
+ input.collect do |row|
8
+ Property.new(row["id"], row["name"], row["kind"], row["options"])
9
+ end
10
+ end
11
+
12
+ def initialize(id, name, kind, options)
13
+ @id, @name, @kind, @options = id, name, kind, options
14
+ end
15
+
16
+ # TODO: Clean this up as this is a dirty quick fix for loading belongs_to properties at the moment
17
+ def model
18
+ BettyResource.meta_data.models.values.detect{|x| x.id == options["model"]} if kind == "belongs_to"
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,101 @@
1
+ module BettyResource
2
+ class Model
3
+ class Record
4
+
5
+ include DirtyAttributes::InstanceMethods
6
+ include MethodMap
7
+ attr_reader :id, :model
8
+
9
+ alias :_class :class
10
+ def class
11
+ model
12
+ end
13
+
14
+ def initialize(model, attributes = {})
15
+ @model = model
16
+ @id = attributes.delete(:id) || attributes.delete("id")
17
+ @errors = {}
18
+ super()
19
+ self.attributes = Hash[model.attributes.collect{|x| [x, nil]}].merge attributes
20
+ end
21
+
22
+ def new_record?
23
+ @id.nil?
24
+ end
25
+
26
+ # TODO: Test this
27
+ def attributes=(other)
28
+ other.each do |key, value|
29
+ send "#{key}=", value
30
+ end
31
+ end
32
+
33
+ def errors
34
+ @errors.dup
35
+ end
36
+
37
+ def save
38
+ @errors.clear
39
+
40
+ result = begin
41
+ if new_record?
42
+ Api.post("/models/#{model.id}/records/new", to_params)
43
+ else
44
+ Api.put("/models/#{model.id}/records/#{id}", to_params)
45
+ end
46
+ end
47
+
48
+ (result.code.to_s[0..1] == "20").tap do |success|
49
+ if success
50
+ model.send :load, result.parsed_response, self
51
+ else
52
+ @errors = result.parsed_response ? result.parsed_response["errors"] : {"" => ["Er is iets mis gegaan met het verwerken van het formulier. Probeer u het later nog eens. Onze excuses voor het ongemak"]}
53
+ end
54
+ end
55
+ end
56
+
57
+ def inspect
58
+ inspection = "id: #{id.inspect}, #{attributes.collect{|key, value| "#{key}: #{value.inspect}"}.join(", ")}"
59
+ "#<#{model.name} #{inspection}>"
60
+ end
61
+ alias :to_s :inspect
62
+
63
+ # TODO: Test this update
64
+ def as_json(options = {})
65
+ attributes_as_json(options).merge! "id" => id
66
+ end
67
+
68
+ private
69
+
70
+ # TODO: Clean this mess up as this is a dirty quick fix for loading belongs_to properties at the moment
71
+ def method_missing(method, *args)
72
+ if method.to_s.match(/^(\w+).id=$/)
73
+ if model.attributes.include?($1)
74
+ instance = attributes[$1] ||= begin
75
+ if property = model.properties.detect{|x| x.name == $1}
76
+ property.model.new
77
+ end
78
+ end
79
+ if instance
80
+ return instance.instance_variable_set :@id, args.first
81
+ end
82
+ end
83
+ end
84
+ super
85
+ end
86
+
87
+ def to_params
88
+ {:body => {:record => attributes_as_json}}
89
+ end
90
+
91
+ # TODO: Test this update
92
+ def attributes_as_json(options = {})
93
+ attributes.inject({}) do |h, (k, v)|
94
+ h.merge! k => (v.respond_to?(:as_json) ? v.as_json(options) : v) if v
95
+ h
96
+ end
97
+ end
98
+
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,68 @@
1
+ module BettyResource
2
+ class Model
3
+ autoload :Record, "betty_resource/model/record"
4
+ autoload :Property, "betty_resource/model/property"
5
+
6
+ attr_accessor :id, :name, :properties
7
+
8
+ def self.parse(input)
9
+ input.inject({}) do |hash, row|
10
+ hash.merge(row["name"] => Model.new(row["id"], row["name"], Property.parse(row["properties"])))
11
+ end
12
+ end
13
+
14
+ def initialize(id, name, properties = [])
15
+ @id, @name, @properties = id, name, properties
16
+ end
17
+
18
+ def attributes
19
+ properties.collect(&:name)
20
+ end
21
+
22
+ # TODO: Refactor this method in order to handle formatted view JSON correctly
23
+ def all(options = {})
24
+ begin
25
+ response = Api.get("/models/#{id}/records", :body => options).parsed_response
26
+ ((view_id = options.delete(:view_id) || options.delete("view_id")).nil? ? response : response["records"]).collect do |data|
27
+ load data
28
+ end
29
+ rescue MultiJson::DecodeError
30
+ end
31
+ end
32
+
33
+ def get(record_id)
34
+ begin
35
+ load Api.get("/models/#{id}/records/#{record_id}").parsed_response
36
+ rescue MultiJson::DecodeError
37
+ end
38
+ end
39
+
40
+ def new(attributes = {})
41
+ BettyResource::Model::Record.new(self, attributes)
42
+ end
43
+
44
+ def create(attributes = {})
45
+ new(attributes).tap do |record|
46
+ record.save
47
+ end
48
+ end
49
+
50
+ def to_s
51
+ name
52
+ end
53
+
54
+ private
55
+
56
+ def load(data, record = nil)
57
+ if data
58
+ id = data.delete "id"
59
+ (record || BettyResource::Model::Record.new(self)).tap do |record|
60
+ record.instance_variable_set :@id, id
61
+ record.attributes = data
62
+ record.clean_up!
63
+ end
64
+ end
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,7 @@
1
+ module BettyResource
2
+ MAJOR = 0
3
+ MINOR = 0
4
+ TINY = 7
5
+
6
+ VERSION = [MAJOR, MINOR, TINY].join(".")
7
+ end
@@ -0,0 +1,39 @@
1
+ require "active_support/core_ext/hash/indifferent_access" # See https://gist.github.com/1075643
2
+
3
+ require "httparty"
4
+ require "crack/json"
5
+ require "dirty_hashy"
6
+
7
+ module BettyResource
8
+ autoload :Api, "betty_resource/api"
9
+ autoload :Configuration, "betty_resource/configuration"
10
+ autoload :MetaData, "betty_resource/meta_data"
11
+ autoload :Model, "betty_resource/model"
12
+
13
+ def self.const_missing(name)
14
+ meta_data.model(name).tap do |model|
15
+ const_set(name, model)
16
+ end || super
17
+ end
18
+
19
+ def self.meta_data
20
+ @meta_data ||= MetaData.new
21
+ end
22
+
23
+ def self.config(validate = true)
24
+ (@configuration ||= Configuration.new).tap do |config|
25
+ config.validate! if validate
26
+ end
27
+ end
28
+
29
+ def self.configure(configuration = nil)
30
+ if configuration
31
+ @configuration = Configuration.new(configuration).tap do |config|
32
+ config.validate!
33
+ end
34
+ else
35
+ yield config(false)
36
+ end
37
+ end
38
+
39
+ end
data/script/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ require "rubygems"
3
+ require "bundler/setup"
4
+
5
+ Bundler.require :gem_default
6
+
7
+ BettyResource.configure(MultiJson.decode(File.read(File.expand_path('../../.credentials', __FILE__))))
8
+
9
+ puts "Loading BettyResource development environment (#{BettyResource::VERSION})"
10
+ puts "Configured connection with #{BettyResource.config.host}".yellow
11
+ Pry.start
@@ -0,0 +1,18 @@
1
+ ENV["RACK_ENV"] = "test"
2
+ ENV["TESTOPTS"] = "-v"
3
+
4
+ require "rubygems"
5
+ require "bundler/setup"
6
+
7
+ require "minitest/unit"
8
+ require "minitest/autorun"
9
+
10
+ require "simplecov"
11
+
12
+ SimpleCov.start do
13
+ coverage_dir "coverage"
14
+ add_filter "/test/"
15
+ end
16
+
17
+ Bundler.require :gem_default, :gem_test
18
+ BettyResource.configure(MultiJson.decode(File.read(File.expand_path('../../.credentials', __FILE__))))
@@ -0,0 +1,116 @@
1
+ require_relative "../../test_helper"
2
+
3
+ module Unit
4
+ module Record
5
+ class TestRecord < MiniTest::Unit::TestCase
6
+
7
+ describe BettyResource::Model::Record do
8
+ it "should return its model" do
9
+ assert_equal BettyResource::Relation, BettyResource::Relation.new.model
10
+ assert_equal BettyResource::Relation, BettyResource::Relation.new.class
11
+ end
12
+
13
+ it "should return its attributes" do
14
+ relation = BettyResource::Relation.new
15
+ assert_equal %w(first_name id last_name), relation.attributes.keys.sort
16
+ end
17
+
18
+ it "should create a method for writing each attribute" do
19
+ relation = BettyResource::Relation.new
20
+ assert relation.first_name = "my_first_name"
21
+ assert relation.last_name = "my_last_name"
22
+ end
23
+
24
+ it "should create a method for reading each attribute" do
25
+ relation = BettyResource::Relation.new
26
+ relation.first_name = "my_first_name"
27
+ assert_equal "my_first_name", relation.first_name
28
+ end
29
+
30
+ it "should store its values in the @attributes instance variable" do
31
+ relation = BettyResource::Relation.new
32
+ relation.first_name = "my_first_name"
33
+ assert_equal "my_first_name", relation.attributes[:first_name]
34
+ end
35
+
36
+ it "should allow mass-assignment when initializing" do
37
+ relation = BettyResource::Relation.new(:first_name => "my_first_name", :last_name => "my_last_name")
38
+ assert_equal "my_first_name", relation.first_name
39
+ assert_equal "my_last_name", relation.last_name
40
+ end
41
+
42
+ it "should allow mass-assignment when already initialized" do
43
+ relation = BettyResource::Relation.new
44
+ relation.attributes = {:first_name => "my_first_name", :last_name => "my_last_name"}
45
+ assert_equal "my_first_name", relation.first_name
46
+ assert_equal "my_last_name", relation.last_name
47
+ end
48
+
49
+ it "should not allow setting of id" do
50
+ relation = BettyResource::Relation.get(1)
51
+ assert_equal 1, relation.id
52
+ assert relation.id = 2
53
+ assert_equal 1, relation.id
54
+ end
55
+
56
+ it "should be able to represent itself as JSON" do
57
+ relation = BettyResource::Relation.new(:first_name => "Paul", :last_name => "Engel")
58
+ assert_equal({"id" => nil, "first_name" => "Paul", "last_name" => "Engel"}, relation.as_json)
59
+
60
+ relation = BettyResource::Relation.get(1)
61
+ assert_equal({"id" => 1, "first_name" => "Daniel", "last_name" => "Willemse"}, relation.as_json)
62
+ end
63
+
64
+ it "should save itself" do
65
+ relation = BettyResource::Relation.new(:first_name => "Stephan", :last_name => "Kaag")
66
+ assert relation.save
67
+ assert relation.id > 0
68
+
69
+ relation = BettyResource::Relation.get(relation.id)
70
+ assert_equal "Stephan", relation.first_name
71
+ assert_equal "Kaag", relation.last_name
72
+ end
73
+
74
+ it "should not save itself when invalid (first_name is required)" do
75
+ relation = BettyResource::Relation.new
76
+ assert !relation.save
77
+ assert_equal({"first_name"=>["is_required"]}, relation.errors)
78
+
79
+ relation.first_name = "Stephan"
80
+ assert relation.save
81
+ end
82
+
83
+ it "should have read-only errors messages" do
84
+ relation = BettyResource::Relation.create
85
+ assert_equal({"first_name"=>["is_required"]}, relation.errors)
86
+
87
+ relation.errors.clear
88
+ assert_equal({"first_name"=>["is_required"]}, relation.errors)
89
+ end
90
+
91
+ it "should not resave itself when invalid" do
92
+ relation = BettyResource::Relation.new :first_name => "Piet"
93
+ assert relation.save
94
+
95
+ relation.first_name = ""
96
+ assert !relation.save
97
+ assert relation.id > 0
98
+
99
+ assert_equal "Piet", BettyResource::Relation.get(relation.id).first_name
100
+ end
101
+
102
+ it "should update itself" do
103
+ relation = BettyResource::Relation.new(:first_name => "Stefan", :last_name => "Kaag")
104
+ relation.save
105
+
106
+ relation.first_name = "Stephan"
107
+ relation.save
108
+
109
+ relation = BettyResource::Relation.get(relation.id)
110
+ assert_equal "Stephan", relation.first_name
111
+ end
112
+ end
113
+
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,41 @@
1
+ require_relative "../test_helper"
2
+
3
+ module Unit
4
+ class TestBase < MiniTest::Unit::TestCase
5
+
6
+ describe BettyResource do
7
+ it "should validate its config" do
8
+ assert config = BettyResource.config
9
+
10
+ config.expects(:host).returns(nil)
11
+ assert_raises(BettyResource::Configuration::InvalidError) do
12
+ BettyResource.config
13
+ end
14
+
15
+ config.expects(:host).returns("")
16
+ assert_raises(BettyResource::Configuration::InvalidError) do
17
+ BettyResource.config
18
+ end
19
+
20
+ config.expects(:host).returns(" ")
21
+ assert_raises(BettyResource::Configuration::InvalidError) do
22
+ BettyResource.config
23
+ end
24
+
25
+ config.expects(:host).returns("localhost")
26
+ assert BettyResource.config
27
+ end
28
+
29
+ it "should return a model instance" do
30
+ assert BettyResource::Relation.is_a?(BettyResource::Model)
31
+ end
32
+
33
+ it "should raise NameError when an unknown model is requested" do
34
+ assert_raises(NameError) do
35
+ assert BettyResource::DoesNotExist
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,26 @@
1
+ require_relative "../test_helper"
2
+
3
+ module Unit
4
+ class TestBase < MiniTest::Unit::TestCase
5
+
6
+ describe BettyResource::Configuration do
7
+ it "should be able to validate itself" do
8
+ config = BettyResource::Configuration.new
9
+ assert_raises(BettyResource::Configuration::InvalidError) do
10
+ config.validate!
11
+ end
12
+
13
+ config.host = "localhost"
14
+ assert_raises(BettyResource::Configuration::InvalidError) do
15
+ config.validate!
16
+ end
17
+
18
+ config.host = "localhost"
19
+ config.user = "foo"
20
+ config.password = "bar"
21
+ assert_nil config.validate!
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,54 @@
1
+ require_relative "../test_helper"
2
+
3
+ module Unit
4
+ class TestModel < MiniTest::Unit::TestCase
5
+
6
+ describe BettyResource::Model do
7
+ it "should know its properties" do
8
+ assert BettyResource::Relation.properties.is_a?(Array)
9
+ assert BettyResource::Relation.properties.any?
10
+ assert BettyResource::Relation.properties[0].is_a?(BettyResource::Model::Property)
11
+ end
12
+
13
+ it "should know its attributes" do
14
+ assert_equal %w(first_name id last_name), BettyResource::Relation.attributes.sort
15
+ end
16
+
17
+ it "should return a new record instance" do
18
+ assert BettyResource::Relation.new.is_a?(BettyResource::Model::Record)
19
+ end
20
+
21
+ it "should not load unexisting records" do
22
+ assert_nil BettyResource::Relation.get(-1)
23
+ end
24
+
25
+ it "should fetch a record" do
26
+ relation = BettyResource::Relation.get(1)
27
+ assert_equal 1, relation.id
28
+ assert_equal "Daniel", relation.first_name
29
+ assert_equal "Willemse", relation.last_name
30
+ end
31
+
32
+ it "should fetch multiple records" do
33
+ relations = BettyResource::Relation.all
34
+ assert_equal 100, relations.size
35
+ assert relations.first.is_a?(BettyResource::Model::Record)
36
+
37
+ relations = BettyResource::Relation.all :limit => 10
38
+ assert_equal 10, relations.size
39
+ assert relations.first.is_a?(BettyResource::Model::Record)
40
+ end
41
+
42
+ it "should directly create a record" do
43
+ relation = BettyResource::Relation.create(:first_name => "Stephan", :last_name => "Kaag")
44
+ assert relation
45
+ assert relation.id > 0
46
+
47
+ relation = BettyResource::Relation.get(relation.id)
48
+ assert_equal "Stephan", relation.first_name
49
+ assert_equal "Kaag", relation.last_name
50
+ end
51
+ end
52
+
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: betty_resource
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chiel Wester
9
+ - Stephan Kaag
10
+ - Daniel Willemse
11
+ - Paul Engel
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+ date: 2013-01-22 00:00:00.000000000 Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: httparty
19
+ requirement: !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ! '>='
23
+ - !ruby/object:Gem::Version
24
+ version: '0'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: activesupport
35
+ requirement: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ - !ruby/object:Gem::Dependency
50
+ name: crack
51
+ requirement: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ - !ruby/object:Gem::Dependency
66
+ name: dirty_hashy
67
+ requirement: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - '='
71
+ - !ruby/object:Gem::Version
72
+ version: 0.1.3
73
+ type: :runtime
74
+ prerelease: false
75
+ version_requirements: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - '='
79
+ - !ruby/object:Gem::Version
80
+ version: 0.1.3
81
+ - !ruby/object:Gem::Dependency
82
+ name: multi_json
83
+ requirement: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ description: Map Betty5 application resources to Ruby objects through the JSON API
114
+ email:
115
+ - chiel.wester@holder.nl
116
+ - stephan.kaag@bettyblocks.com
117
+ - daniel.willemse@holder.nl
118
+ - paul.engel@bettyblocks.com
119
+ executables: []
120
+ extensions: []
121
+ extra_rdoc_files: []
122
+ files:
123
+ - .gitignore
124
+ - CHANGELOG.rdoc
125
+ - Gemfile
126
+ - README.md
127
+ - Rakefile
128
+ - betty_resource.gemspec
129
+ - lib/betty_resource.rb
130
+ - lib/betty_resource/api.rb
131
+ - lib/betty_resource/configuration.rb
132
+ - lib/betty_resource/meta_data.rb
133
+ - lib/betty_resource/model.rb
134
+ - lib/betty_resource/model/property.rb
135
+ - lib/betty_resource/model/record.rb
136
+ - lib/betty_resource/version.rb
137
+ - script/console
138
+ - test/test_helper.rb
139
+ - test/unit/model/test_record.rb
140
+ - test/unit/test_base.rb
141
+ - test/unit/test_configuration.rb
142
+ - test/unit/test_model.rb
143
+ homepage: https://github.com/bettyblocks/betty_resource
144
+ licenses: []
145
+ post_install_message:
146
+ rdoc_options: []
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ! '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ! '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 1.8.24
164
+ signing_key:
165
+ specification_version: 3
166
+ summary: Map Betty5 application resources to Ruby objects
167
+ test_files:
168
+ - test/test_helper.rb
169
+ - test/unit/model/test_record.rb
170
+ - test/unit/test_base.rb
171
+ - test/unit/test_configuration.rb
172
+ - test/unit/test_model.rb
173
+ has_rdoc: