infovore-ruminant 0.9.4
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/README +70 -0
- data/lib/core_ext/options_struct.rb +20 -0
- data/lib/design.rb +98 -0
- data/lib/moo.rb +58 -0
- data/lib/template.xml.builder +20 -0
- data/lib/text_line.rb +12 -0
- data/spec/design_spec.rb +65 -0
- data/spec/moo_spec.rb +85 -0
- data/spec/product_spec.rb +29 -0
- data/spec/spec_helper.rb +6 -0
- metadata +78 -0
data/README
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
Ruminant
|
2
|
+
========
|
3
|
+
|
4
|
+
Aiming to make the moo API almost as easy to use for developers as the moo.com site itself.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
|
9
|
+
If you've never installed a gem from github before - enter the following and you will eternally be graced by a thousand minds:
|
10
|
+
gem sources -a http://gems.github.com
|
11
|
+
|
12
|
+
Then you can install this like any other gem:
|
13
|
+
gem install james-ruminant
|
14
|
+
|
15
|
+
|
16
|
+
Usage
|
17
|
+
-----
|
18
|
+
|
19
|
+
All parameters are done in an ActiveRecord attributes style, i.e. they can be passed into new() as a hash, and are all attr-accessors
|
20
|
+
|
21
|
+
Making an order:
|
22
|
+
require 'rubygems'
|
23
|
+
require 'moo'
|
24
|
+
order = Moo::Order.new(:api_key => "your api key")
|
25
|
+
|
26
|
+
Adding a product:
|
27
|
+
moocard = Moo::MiniCard.new(:url => "http://farm...")
|
28
|
+
order.designs << moocard
|
29
|
+
|
30
|
+
Adding text
|
31
|
+
moocard.text = "This is line 1 \n This is line 2"
|
32
|
+
moocard.line(1) #=> This is line 1
|
33
|
+
moocard.line(1).bold = true
|
34
|
+
moocard.line(1).align = "right"
|
35
|
+
moocard.line(1).font = "modern"
|
36
|
+
moocard.line(1).colour = "#444444"
|
37
|
+
moocard.bold = true # sets bold=true on all lines
|
38
|
+
|
39
|
+
Submitting to moo:
|
40
|
+
order.to_xml # Gives you the generated xml if you want to manually submit it
|
41
|
+
order.submit
|
42
|
+
if order.error?
|
43
|
+
order.error_string
|
44
|
+
else
|
45
|
+
order.start_url
|
46
|
+
end
|
47
|
+
|
48
|
+
Current Limitations
|
49
|
+
-------------------
|
50
|
+
|
51
|
+
Currently I only support MiniCards, but have made it incredibly easy to add the other supported products.
|
52
|
+
I haven't yet, as I do not have a personal need, so don't feel I can test it. If you have such a need, do let me know, as we can add it.
|
53
|
+
|
54
|
+
Manual Cropping is not currently supported for the same reason.
|
55
|
+
|
56
|
+
Please please please do feel to give feedback and/or submit patches. I want this library to be as helpful as possible, but can only do that if I know what you want.
|
57
|
+
|
58
|
+
Contributors thus far
|
59
|
+
---------------------
|
60
|
+
Xenia Kingsley - Naming powers
|
61
|
+
Chris Mear - Fixing stuff, and provides the wine
|
62
|
+
Dan Webb - Wisdom
|
63
|
+
|
64
|
+
|
65
|
+
(__)
|
66
|
+
(oo)
|
67
|
+
/-------\/
|
68
|
+
/ | ||
|
69
|
+
* ||----||
|
70
|
+
~~ ~~
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module OptionsStruct
|
2
|
+
def self.create(*accessors)
|
3
|
+
Class.new do
|
4
|
+
attr_accessor *accessors
|
5
|
+
include Methods
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Methods
|
10
|
+
def default_options
|
11
|
+
{}
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(options={})
|
15
|
+
default_options.merge(options).each do |name, value|
|
16
|
+
self.send("#{name}=",value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/design.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'text_line'
|
2
|
+
module Moo
|
3
|
+
class Design < OptionsStruct.create(:url, :type, :crop, :lines, :font_size)
|
4
|
+
def default_options
|
5
|
+
{
|
6
|
+
:lines => [],
|
7
|
+
:crop => 'auto',
|
8
|
+
:type => 'variable'
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def text=(content)
|
13
|
+
content.split("\n").each{|line| lines << TextLine.new(:string => line, :design => self) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def line(n)
|
17
|
+
lines[n-1]
|
18
|
+
end
|
19
|
+
|
20
|
+
[:design, :string, :font_size, :bold, :italic, :align, :font, :colour].each do |text_attribute|
|
21
|
+
class_eval %{
|
22
|
+
# Sets #{text_attribute} attribute on all text lines
|
23
|
+
def #{text_attribute}=(value)
|
24
|
+
set_attribute_on_all_lines(:#{text_attribute}, value)
|
25
|
+
end
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.disable_attributes(attributes=[])
|
30
|
+
attributes.each do |attribute|
|
31
|
+
class_eval %{
|
32
|
+
def #{attribute}=(*args)
|
33
|
+
raise DisabledAttributeError
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_xml(xml=Builder::XmlMarkup.new)
|
40
|
+
xml.design {
|
41
|
+
xml.image {
|
42
|
+
xml.url self.url
|
43
|
+
xml.type self.type
|
44
|
+
xml.crop {
|
45
|
+
xml.auto true
|
46
|
+
}
|
47
|
+
}
|
48
|
+
if !product_type.eql?("sticker")
|
49
|
+
xml.text_collection {
|
50
|
+
xml.tag! product_type {
|
51
|
+
xml.minicard {
|
52
|
+
lines.each_with_index do |line, index|
|
53
|
+
xml.text_line {
|
54
|
+
xml.id index+1
|
55
|
+
xml.string line.string
|
56
|
+
xml.bold line.bold
|
57
|
+
xml.align line.align
|
58
|
+
xml.font line.font
|
59
|
+
xml.colour line.colour
|
60
|
+
}
|
61
|
+
end
|
62
|
+
}
|
63
|
+
end
|
64
|
+
}
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def set_attribute_on_all_lines(attribute, value)
|
71
|
+
@lines.each{|line| line.send("#{attribute}=",value)}
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
class MiniCard < Design
|
77
|
+
disable_attributes [:font_size, :italic]
|
78
|
+
|
79
|
+
def product_type
|
80
|
+
"minicard"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class Sticker < Design
|
85
|
+
|
86
|
+
disable_attributes [:font, :font_size, :colour, :align, :bold, :string, :italic]
|
87
|
+
|
88
|
+
def product_type
|
89
|
+
"sticker"
|
90
|
+
end
|
91
|
+
|
92
|
+
undef :text=
|
93
|
+
undef :line
|
94
|
+
end
|
95
|
+
|
96
|
+
class DisabledAttributeError < StandardError
|
97
|
+
end
|
98
|
+
end
|
data/lib/moo.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'core_ext/options_struct'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'builder'
|
4
|
+
require 'design'
|
5
|
+
|
6
|
+
require 'net/http'
|
7
|
+
require 'uri'
|
8
|
+
require 'hpricot'
|
9
|
+
|
10
|
+
module Moo
|
11
|
+
class Order < OptionsStruct.create(:api_key, :designs)
|
12
|
+
def api_version
|
13
|
+
0.7
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_options
|
17
|
+
{
|
18
|
+
:designs => [],
|
19
|
+
:api_key => 0
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def product_type
|
24
|
+
@designs.first.product_type if @designs.first
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_xml(xml=nil)
|
28
|
+
xml = Builder::XmlMarkup.new(:target => (@xml_string = "")) unless xml
|
29
|
+
eval File.open(File.expand_path(File.dirname(__FILE__) + "/template.xml.builder")).read
|
30
|
+
xml.target!
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_accessor :raw_response, :error_string, :error_code, :session_id, :start_url
|
34
|
+
def submit
|
35
|
+
res = Net::HTTP.post_form(URI.parse('http://www.moo.com/api/api.php'),
|
36
|
+
{'xml'=>self.to_xml, 'method'=>'direct'})
|
37
|
+
@raw_response = res.body
|
38
|
+
process_response
|
39
|
+
!error?
|
40
|
+
end
|
41
|
+
|
42
|
+
def process_response
|
43
|
+
@response = Hpricot(raw_response)
|
44
|
+
if error?
|
45
|
+
@error_string = @response.search('error_string').inner_html
|
46
|
+
@error_code = @response.search('error_code').inner_html
|
47
|
+
else
|
48
|
+
@session_id = @response.search('session_id').inner_html
|
49
|
+
@start_url = @response.search('start_url').inner_html
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def error?
|
54
|
+
@error ||= (@response.search('error').inner_html == "true")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.moo("xsi:noNamespaceSchemaLocation" => "http://www.moo.com/xsd/api_0.7.xsd", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance") {
|
3
|
+
xml.request {
|
4
|
+
xml.version self.api_version
|
5
|
+
xml.api_key self.api_key
|
6
|
+
xml.call "build"
|
7
|
+
}
|
8
|
+
xml.payload{
|
9
|
+
xml.products {
|
10
|
+
xml.product {
|
11
|
+
xml.product_type self.product_type
|
12
|
+
xml.designs {
|
13
|
+
self.designs.each { |design|
|
14
|
+
design.to_xml(xml)
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
data/lib/text_line.rb
ADDED
data/spec/design_spec.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[spec_helper])
|
2
|
+
|
3
|
+
describe "a minicard" do
|
4
|
+
before :each do
|
5
|
+
@design = Moo::MiniCard.new(:url => "http://farm3.static.flickr.com/2300/2179038972_23d2a1ff40_o.jpg")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should have minicard as the type" do
|
9
|
+
@design.product_type.should == "minicard"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should not support size" do
|
13
|
+
lambda{@design.font_size = 0.5}.should raise_error(Moo::DisabledAttributeError)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should not support italic" do
|
17
|
+
lambda{@design.italic = true}.should raise_error(Moo::DisabledAttributeError)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "a sticker" do
|
22
|
+
before(:each) do
|
23
|
+
@design = Moo::Sticker.new(:url => "")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should have sticker as the type" do
|
27
|
+
@design.product_type.should == "sticker"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should not support font size" do
|
31
|
+
lambda{@design.font_size = 0.5}.should raise_error(Moo::DisabledAttributeError)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should not support italic" do
|
35
|
+
lambda{@design.italic = true}.should raise_error(Moo::DisabledAttributeError)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not support string" do
|
39
|
+
lambda{@design.string = "foo"}.should raise_error(Moo::DisabledAttributeError)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should not support bold" do
|
43
|
+
lambda{@design.bold = true}.should raise_error(Moo::DisabledAttributeError)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should not support align" do
|
47
|
+
lambda{@design.align = "centre"}.should raise_error(Moo::DisabledAttributeError)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should not support font" do
|
51
|
+
lambda{@design.font = "Normal"}.should raise_error(Moo::DisabledAttributeError)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should not support colour" do
|
55
|
+
lambda{@design.colour = "#ccc"}.should raise_error(Moo::DisabledAttributeError)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should not support any text" do
|
59
|
+
lambda{@design.text = "testing!"}.should raise_error(NoMethodError)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should not support lines" do
|
63
|
+
lambda{@design.line(1)}.should raise_error(NoMethodError)
|
64
|
+
end
|
65
|
+
end
|
data/spec/moo_spec.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[spec_helper])
|
2
|
+
|
3
|
+
describe "an empty moo order" do
|
4
|
+
before :each do
|
5
|
+
@moo = Moo::Order.new :api_key => "TESTAPIKEY"
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should have the appropiate header" do
|
9
|
+
@moo.to_xml.should include('<?xml version="1.0" encoding="UTF-8"?><moo xsi:noNamespaceSchemaLocation="http://www.moo.com/xsd/api_0.7.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should user MOO API version 0.7" do
|
13
|
+
@moo.to_xml.should include("<version>0.7</version>")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should include the API key" do
|
17
|
+
@moo.to_xml.should include("<api_key>TESTAPIKEY</api_key>")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should call build" do
|
21
|
+
@moo.to_xml.should include("<call>build</call>")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not contain to_s" do
|
25
|
+
@moo.to_xml.should_not include("to_s")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "a moo order with a minicard" do
|
30
|
+
before :each do
|
31
|
+
@moo = Moo::Order.new :api_key => "TESTAPIKEY"
|
32
|
+
@minicard = Moo::MiniCard.new(:url => "http://farm3.static.flickr.com/2300/2179038972_23d2a1ff40_o.jpg")
|
33
|
+
@moo.designs << @minicard
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have product type of 'minicard'" do
|
37
|
+
@moo.product_type.should == 'minicard'
|
38
|
+
@moo.to_xml.should include('<product_type>minicard</product_type>')
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should include the xml for the minicard" do
|
42
|
+
@moo.to_xml.should include(@minicard.to_xml)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "processing an XML response for failure" do
|
47
|
+
before :each do
|
48
|
+
@moo = Moo::Order.new :api_key => "TESTAPIKEY"
|
49
|
+
@moo.stub!(:raw_response).and_return('<?xml version="1.0" encoding="UTF-8"?> <moo> <response> <call>build</call> <error>true</error> </response> <payload> <error_code>1</error_code> <error_string>Error importing XML document</error_string> </payload> </moo>')
|
50
|
+
@moo.process_response
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should set error? as true" do
|
54
|
+
@moo.error?.should be_true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should set error_string correctly" do
|
58
|
+
@moo.error_string.should == "Error importing XML document"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should set error_code correctly" do
|
62
|
+
@moo.error_code.should == "1"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
describe "processing an XML response for success" do
|
68
|
+
before :each do
|
69
|
+
@moo = Moo::Order.new :api_key => "TESTAPIKEY"
|
70
|
+
@moo.stub!(:raw_response).and_return('<?xml version="1.0" encoding="UTF-8"?> <moo> <response> <call>build</call> <api_key>3ddbe3c0-17ac-c0a802d2-47bafd19-2473</api_key> </response> <payload> <session_id>d4c7a6d179fca910d67221a57a1bf966</session_id> <start_url>http://www.moo.com/make/designback.php?bid=1&pid=115&SID=d4c7a6d179fca910d67221a57a1bf966</start_url> </payload> </moo>')
|
71
|
+
@moo.process_response
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should set error? as false" do
|
75
|
+
@moo.error?.should be_false
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should set start_url correctly" do
|
79
|
+
@moo.start_url.should == "http://www.moo.com/make/designback.php?bid=1&pid=115&SID=d4c7a6d179fca910d67221a57a1bf966"
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should set session_id correctly" do
|
83
|
+
@moo.session_id.should == "d4c7a6d179fca910d67221a57a1bf966"
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[spec_helper])
|
2
|
+
|
3
|
+
describe "The Design base class" do
|
4
|
+
before :each do
|
5
|
+
@design = Moo::Design.new(:url => "http://farm3.static.flickr.com/2300/2179038972_23d2a1ff40_o.jpg")
|
6
|
+
@design.stub!(:product_type).and_return("minicard")
|
7
|
+
|
8
|
+
@design.text = "This is Line 1\nAnd this is the second line"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should include the design's photo url" do
|
12
|
+
@design.to_xml.should include("<url>http://farm3.static.flickr.com/2300/2179038972_23d2a1ff40_o.jpg</url>")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should store the text into multiple TextLines" do
|
16
|
+
@design.line(1).class.should == Moo::TextLine
|
17
|
+
@design.line(1).string.should == "This is Line 1"
|
18
|
+
@design.line(2).class.should == Moo::TextLine
|
19
|
+
@design.line(2).string.should == "And this is the second line"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be able to set an attribute on all lines" do
|
23
|
+
@design.line(1).bold.should == false
|
24
|
+
@design.line(2).bold.should == false
|
25
|
+
@design.bold = true
|
26
|
+
@design.line(1).bold.should == true
|
27
|
+
@design.line(2).bold.should == true
|
28
|
+
end
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: infovore-ruminant
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Darling
|
8
|
+
- Tom Armitage
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain:
|
12
|
+
date: 2008-09-15 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hpricot
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: builder
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: "0"
|
32
|
+
version:
|
33
|
+
description: A ruby library to regurgitate MOO products
|
34
|
+
email: james@abscond.org tom@infovore.org
|
35
|
+
executables: []
|
36
|
+
|
37
|
+
extensions: []
|
38
|
+
|
39
|
+
extra_rdoc_files: []
|
40
|
+
|
41
|
+
files:
|
42
|
+
- lib/moo.rb
|
43
|
+
- lib/design.rb
|
44
|
+
- lib/template.xml.builder
|
45
|
+
- lib/text_line.rb
|
46
|
+
- lib/core_ext/options_struct.rb
|
47
|
+
- README
|
48
|
+
has_rdoc: false
|
49
|
+
homepage: http://github.com/infovore/ruminant/tree/master
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 0.0.0
|
60
|
+
version:
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 1.2.0
|
71
|
+
signing_key:
|
72
|
+
specification_version: 2
|
73
|
+
summary: A ruby library to regurgitate MOO products
|
74
|
+
test_files:
|
75
|
+
- spec/design_spec.rb
|
76
|
+
- spec/moo_spec.rb
|
77
|
+
- spec/product_spec.rb
|
78
|
+
- spec/spec_helper.rb
|