eventbright 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.markdown +92 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/lib/eventbright.rb +5 -0
- data/lib/eventbright/api_object.rb +180 -0
- data/lib/eventbright/api_object_class_methods.rb +117 -0
- data/lib/eventbright/api_object_collection.rb +60 -0
- data/lib/eventbright/api_object_relationships.rb +72 -0
- data/lib/eventbright/api_objects/attendee.rb +51 -0
- data/lib/eventbright/api_objects/discount.rb +62 -0
- data/lib/eventbright/api_objects/event.rb +79 -0
- data/lib/eventbright/api_objects/organizer.rb +26 -0
- data/lib/eventbright/api_objects/ticket.rb +63 -0
- data/lib/eventbright/api_objects/user.rb +45 -0
- data/lib/eventbright/api_objects/venue.rb +18 -0
- data/lib/eventbright/error.rb +14 -0
- data/lib/eventbright/main.rb +57 -0
- data/spec/eventbright/api_object_class_spec.rb +113 -0
- data/spec/eventbright/api_object_collection_spec.rb +67 -0
- data/spec/eventbright/api_object_relationship_spec.rb +23 -0
- data/spec/eventbright/api_object_spec.rb +15 -0
- data/spec/eventbright/user_spec.rb +141 -0
- data/spec/eventbright_api_faker.rb +18 -0
- data/spec/eventbright_spec.rb +36 -0
- data/spec/faked_responses/auth_required.json +1 -0
- data/spec/faked_responses/event_get.json +1 -0
- data/spec/faked_responses/user_get.json +1 -0
- data/spec/faked_responses/user_list_events.json +1 -0
- data/spec/faked_responses/user_list_organizers.json +1 -0
- data/spec/faked_responses/user_list_venues.json +1 -0
- data/spec/faked_responses/user_update.json +1 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +35 -0
- metadata +132 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 David Haslem
|
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.markdown
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
eventbright
|
2
|
+
================
|
3
|
+
|
4
|
+
A simple library for integrating with EventBrite's API. Requires the "httparty" gem for connecting and doing XML parsing, and "tzinfo" gem for getting back and forth between timezone names and GMT offsets.
|
5
|
+
|
6
|
+
Usage
|
7
|
+
-----
|
8
|
+
|
9
|
+
require 'eventbright'
|
10
|
+
EventBright.setup("APP_KEY")
|
11
|
+
user = EventBright::User.new("USER_KEY") #=> <EventBright::User >
|
12
|
+
user.venues #=> [<EventBright::Venue>,...] # Venues the user has defined
|
13
|
+
|
14
|
+
Authentication
|
15
|
+
--------------
|
16
|
+
Many methods require user authentication. For these methods, you can pass a user object as an authentication token, and the user's api_key will automatically be used for the request.
|
17
|
+
|
18
|
+
Example:
|
19
|
+
|
20
|
+
EventBright::Event.new({"x" => "y"... , "user" => user})
|
21
|
+
|
22
|
+
Known Bugs
|
23
|
+
----------
|
24
|
+
|
25
|
+
1. This library's testing coverage is almost zero. I'm working on it.
|
26
|
+
2. There is no subuser support.
|
27
|
+
|
28
|
+
A Note About App Keys
|
29
|
+
---------------------
|
30
|
+
|
31
|
+
This gem has an application key for accessing EventBrite, but each app key is limited to 30,000 requests a day. To make sure your limits aren't affected by others, you should register for your own app key specific to the application you're adding the gem to.
|
32
|
+
|
33
|
+
If you just want to give the gem a whirl (you have to wait for approval to get your own) just don't call setup. The app key for the gem will be used.
|
34
|
+
|
35
|
+
Learn more about EventBrite's App Key policy here: [Terms of Service](http://www.eventbrite.com/api/terms)
|
36
|
+
|
37
|
+
Register for your own app key here: [Request a Key](http://www.eventbrite.com/api/key/)
|
38
|
+
|
39
|
+
|
40
|
+
API Gotchas:
|
41
|
+
--------------------
|
42
|
+
|
43
|
+
A list of sticking points for anyone attempting their own integration with the EventBrite API:
|
44
|
+
|
45
|
+
__/get => /update variable inconsistencies__
|
46
|
+
|
47
|
+
* event.id => event.event_id
|
48
|
+
* event.timezone (Olson format, ex: "US/Central") => event.timezone (GMT offset hours, ex: "GMT-05")
|
49
|
+
* event.privacy (String representing privacy "Private"|"Public") => event.privacy (Boolean 0 = public)
|
50
|
+
* event.url => event.personalized_url
|
51
|
+
* venue.address => venue.adress
|
52
|
+
* venue.address_2 => venue.adress_2
|
53
|
+
* venue.name => venue.venue
|
54
|
+
* event.tickets.ticket.start_date => ticket.start_sales
|
55
|
+
* event.tickets.ticket.end_date => ticket.end_sales
|
56
|
+
* event.tickets.ticket.visible (1 is visible) => ticket.hide (y is hidden, n is visible)
|
57
|
+
* event.tickets.ticket.quantity_available => ticket.quantity
|
58
|
+
|
59
|
+
__Fields you can't edit__
|
60
|
+
|
61
|
+
* event.category
|
62
|
+
* event.tags
|
63
|
+
* event.logo
|
64
|
+
* ticket.hide (on /ticket_new. You must save the ticket then call /ticket_update to hide)
|
65
|
+
|
66
|
+
__Documentation errors__
|
67
|
+
|
68
|
+
* /venue_new and /venue_update does not throw an error if "venue" is invalid/non-unique/empty.
|
69
|
+
* Dates are not technically ISO 8601 (ISO 8601 specifies a "T" - not a space - between date and time, so passing perfectly formatted ISO 8601 datetime strings such as those a standard library would provide will cause errors)
|
70
|
+
* Error description for event Privacy Error: <pre>"The privacy field must be equal to 0 (public) or 1 (private)"</pre> -> This is the opposite of the actual case. 0 is private and 1 is public, as described in other places within the API.
|
71
|
+
* /ticket_new and /ticket_update do not throw errors if quantity not set
|
72
|
+
|
73
|
+
__Other gotchas__
|
74
|
+
|
75
|
+
* Venue object included in event has extra "Lat-Long" attribute, along with "latitude" and "longitude". If you're turning a result into an object, this might cause an error if you don't suspect it.
|
76
|
+
* Timezones are weird (nothing EventBrite can do about this one): GMT offset for timezones is always computed in standard time (don't adjust for Daylight Savings, unlike UTC offset). This weirdness means that once you save the timezone the Olson description might not match what you think it should (ex. US/Eastern becomes GMT-5 which then becomes America/Bogota)
|
77
|
+
|
78
|
+
Note on Patches/Pull Requests
|
79
|
+
-----------------------------
|
80
|
+
|
81
|
+
* Fork the project.
|
82
|
+
* Make your feature addition or bug fix.
|
83
|
+
* Add tests for it. This is important so I don't break it in a
|
84
|
+
future version unintentionally.
|
85
|
+
* Commit, do not mess with rakefile, version, or history.
|
86
|
+
(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)
|
87
|
+
* Send me a pull request. Bonus points for topic branches.
|
88
|
+
|
89
|
+
Copyright
|
90
|
+
---------
|
91
|
+
|
92
|
+
Copyright (c) 2010 David Haslem. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "eventbright"
|
8
|
+
gem.summary = %Q{An unofficial gem for EventBrite Integration}
|
9
|
+
gem.description = %Q{A simple, unoffical gem that integrates with the EventBrite events service. (http://www.eventbrite.com)}
|
10
|
+
gem.email = "therabidbanana@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/therabidbanana/eventbright"
|
12
|
+
gem.authors = ["David Haslem"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
gem.add_dependency "httparty", ">= 0.5.2"
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'spec/rake/spectask'
|
23
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
24
|
+
spec.libs << 'lib' << 'spec'
|
25
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
26
|
+
end
|
27
|
+
|
28
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
29
|
+
spec.libs << 'lib' << 'spec'
|
30
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
31
|
+
spec.rcov = true
|
32
|
+
end
|
33
|
+
|
34
|
+
task :spec => :check_dependencies
|
35
|
+
|
36
|
+
task :default => :irb
|
37
|
+
|
38
|
+
require 'rake/rdoctask'
|
39
|
+
Rake::RDocTask.new do |rdoc|
|
40
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
41
|
+
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
43
|
+
rdoc.title = "eventbright #{version}"
|
44
|
+
rdoc.rdoc_files.include('README*')
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
desc "Runs irb with eventbright lib"
|
50
|
+
task :irb do
|
51
|
+
sh "irb -r 'lib/eventbright'"
|
52
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/eventbright.rb
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
libdir = File.dirname(__FILE__)
|
2
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
3
|
+
require File.join(libdir, 'eventbright', 'main.rb')
|
4
|
+
Dir.glob(File.join(libdir, 'eventbright', '*.rb')).each {|f| require f }
|
5
|
+
Dir.glob(File.join(libdir, 'eventbright', 'api_objects', '*.rb')).each {|f| require f }
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'eventbright/api_object_class_methods'
|
2
|
+
require 'eventbright/api_object_relationships'
|
3
|
+
module EventBright
|
4
|
+
class ApiObject
|
5
|
+
extend EventBright::ApiObjectClassMethods
|
6
|
+
include EventBright::ApiObjectRelationships
|
7
|
+
attr_accessor :id, :owner
|
8
|
+
attr_accessor :attributes, :relations, :collections
|
9
|
+
attr_accessor :dirty, :dirty_relations, :dirty_collections
|
10
|
+
|
11
|
+
def initialize(owner = false, hash = {})
|
12
|
+
preinit
|
13
|
+
unless hash.empty?
|
14
|
+
@id = hash.delete(:id)
|
15
|
+
@owner = owner if owner
|
16
|
+
load(hash, true)
|
17
|
+
init
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def preinit
|
22
|
+
@attributes = @relations = @collections = {}
|
23
|
+
@dirty = @dirty_relations = @dirty_collections = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def clean!
|
27
|
+
@dirty = @dirty_relations = @dirty_collections = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Callback after initialization
|
31
|
+
def init; end
|
32
|
+
|
33
|
+
def attribute_get(key); @attributes[key]; end
|
34
|
+
|
35
|
+
def attribute_set(key, val, no_dirty = false)
|
36
|
+
@dirty[key] = true if(@attributes[key] != val && !no_dirty)
|
37
|
+
@attributes[key] = val
|
38
|
+
after_attribute_set
|
39
|
+
end
|
40
|
+
|
41
|
+
def after_attribute_set
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def id=(new_id,*args)
|
46
|
+
@id = new_id.to_int
|
47
|
+
end
|
48
|
+
|
49
|
+
def load(hash = {}, no_dirty = false)
|
50
|
+
if hash.nil? || hash.size == 0
|
51
|
+
response = EventBright.call("#{self.class.singlet_name}_get", prep_api_hash('get'))
|
52
|
+
hash = response["#{self.class.singlet_name}"]
|
53
|
+
end
|
54
|
+
unless hash.nil? || hash.size == 0
|
55
|
+
init_with_hash(hash, no_dirty)
|
56
|
+
load_relations_with_hash(hash, no_dirty)
|
57
|
+
load_collections_with_hash(hash, no_dirty)
|
58
|
+
end
|
59
|
+
clean! if no_dirty
|
60
|
+
after_load(hash)
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def init_with_hash(hash, no_dirty = false)
|
65
|
+
@attributes ||= {}
|
66
|
+
hash.each do |k, v|
|
67
|
+
self.__send__("#{k}=", v, no_dirty) unless (self.class.ignores.include?(k) ||
|
68
|
+
self.class.ignores.include?(k.to_sym)) ||
|
69
|
+
self.class.relations.include?(k) ||
|
70
|
+
self.class.relations.include?(k.to_sym) ||
|
71
|
+
self.class.collections.include?(k) ||
|
72
|
+
self.class.collections.include?(k.to_sym)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
# A callback for after loads
|
78
|
+
def after_load(hash = {})
|
79
|
+
hash
|
80
|
+
end
|
81
|
+
|
82
|
+
# A callback for methods to clean up the hash a bit
|
83
|
+
# allowing subclasses to insert the user if necessary
|
84
|
+
def prep_api_hash(method = 'get', hash = {})
|
85
|
+
hash = hash.merge api_hash
|
86
|
+
hash = hash.merge get_hash if method == 'get'
|
87
|
+
hash = hash.merge new_hash if method == 'new'
|
88
|
+
hash = hash.merge update_hash if method == 'update'
|
89
|
+
hash
|
90
|
+
end
|
91
|
+
|
92
|
+
# Callbacks for individual hash changes
|
93
|
+
# These are added to the updatable_hash, if appropriate
|
94
|
+
# These are called by prep_api_hash
|
95
|
+
def api_hash; {:user => owner}; end
|
96
|
+
def update_hash; {}; end
|
97
|
+
def get_hash; {}; end
|
98
|
+
def new_hash; {}; end
|
99
|
+
|
100
|
+
def nested_hash; {:user => owner, :id => id}; end
|
101
|
+
|
102
|
+
|
103
|
+
# Forces a clean load from the remote API. Load can be passed a hash of local
|
104
|
+
# values to avoid an API call, but this circumvents it.
|
105
|
+
def load!
|
106
|
+
load({}, true)
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# Callback that happens before saving. Allows modification of options
|
111
|
+
def before_save(opts = {}); opts; end
|
112
|
+
|
113
|
+
# Save function. Can alter functionality by changing callbacks
|
114
|
+
def save(opts = {})
|
115
|
+
return false unless dirty?
|
116
|
+
opts.merge!(updatable_hash(self.class.requires))
|
117
|
+
opts = relations_save(opts)
|
118
|
+
opts = before_save(opts)
|
119
|
+
call = if loaded?
|
120
|
+
c = EventBright.call("#{self.class.singlet_name}_update", prep_api_hash('update', opts))
|
121
|
+
after_update
|
122
|
+
c
|
123
|
+
else
|
124
|
+
c = EventBright.call("#{self.class.singlet_name}_new", prep_api_hash('new', opts))
|
125
|
+
after_new
|
126
|
+
c
|
127
|
+
end
|
128
|
+
self.id = call["process"]["id"] unless loaded?
|
129
|
+
collections_save
|
130
|
+
after_save
|
131
|
+
clean!
|
132
|
+
call
|
133
|
+
end
|
134
|
+
|
135
|
+
# After save callback, only called on a new call
|
136
|
+
def after_new; end
|
137
|
+
# After save callback, only called on an update call
|
138
|
+
def after_update; end
|
139
|
+
# After save callback
|
140
|
+
def after_save; end
|
141
|
+
|
142
|
+
|
143
|
+
def updatable_hash(always_dirty = [])
|
144
|
+
updates = {}
|
145
|
+
@attributes.each do |k, v|
|
146
|
+
updates[k] = @attributes[k] if @dirty[k] || always_dirty.include?(k)
|
147
|
+
end
|
148
|
+
updates.merge! :id => @id if @id
|
149
|
+
self.class.reformats.each do |k|
|
150
|
+
updates[k] = self.__send__(k) if updates[k]
|
151
|
+
end
|
152
|
+
self.class.renames.each do |k,v|
|
153
|
+
updates[v] = updates.delete(k) if updates[k]
|
154
|
+
end
|
155
|
+
updates
|
156
|
+
end
|
157
|
+
|
158
|
+
def inspect
|
159
|
+
"#<#{self.class.to_s}:#{self.id} @attributes=#{@attributes.inspect}>"
|
160
|
+
end
|
161
|
+
|
162
|
+
def to_s
|
163
|
+
"#<#{self.class.to_s}:#{self.id} @attributes=#{@attributes.inspect}>"
|
164
|
+
end
|
165
|
+
|
166
|
+
# Defines whether the object has been loaded from a remote source. If not, then
|
167
|
+
# we assume it's new when saving.
|
168
|
+
def loaded?
|
169
|
+
(!@id.nil? || @id == "")
|
170
|
+
end
|
171
|
+
|
172
|
+
# Something is dirty if it's never been loaded or if the @dirty
|
173
|
+
# hash contains something.
|
174
|
+
def dirty?
|
175
|
+
@dirty ||= {}
|
176
|
+
@dirty.size > 0 || !loaded?
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module EventBright
|
2
|
+
module ApiObjectClassMethods
|
3
|
+
def singlet_name(name = false)
|
4
|
+
@singlet_name = name if name
|
5
|
+
@singlet_name || self.to_s.gsub('EventBright::', '').downcase
|
6
|
+
end
|
7
|
+
|
8
|
+
def plural_name(name = false)
|
9
|
+
@plural_name = name if name
|
10
|
+
@plural_name || "#{self.singlet_name}s"
|
11
|
+
end
|
12
|
+
|
13
|
+
def ignores(*args)
|
14
|
+
@ignores ||= []
|
15
|
+
@ignores.concat(args) unless args.empty?
|
16
|
+
@ignores
|
17
|
+
end
|
18
|
+
|
19
|
+
def requires(*args)
|
20
|
+
@requires ||= []
|
21
|
+
@requires.concat(args) unless args.empty?
|
22
|
+
@requires
|
23
|
+
end
|
24
|
+
|
25
|
+
# Columns to reformat when sending outgoing data
|
26
|
+
# (Reformatting is assumed to be done by calling the method with the
|
27
|
+
# same name as the attribute, so to reformat foo, use def foo... with
|
28
|
+
# an attribute_get inside)
|
29
|
+
def reformats(*args)
|
30
|
+
@reformats ||= []
|
31
|
+
@reformats.concat(args) unless args.empty?
|
32
|
+
@reformats
|
33
|
+
end
|
34
|
+
|
35
|
+
# Columns to rename when sending outgoing data
|
36
|
+
def renames(attrs = false)
|
37
|
+
@renames ||= {}
|
38
|
+
@renames.merge!(attrs) if attrs
|
39
|
+
@renames
|
40
|
+
end
|
41
|
+
|
42
|
+
def updatable(*args)
|
43
|
+
args.each{|symbol|
|
44
|
+
module_eval( "def #{symbol}(); attribute_get(:#{symbol}); end")
|
45
|
+
module_eval( "def #{symbol}=(val, no_dirty = false); attribute_set(:#{symbol}, val, no_dirty); end")
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def readable(*args)
|
50
|
+
args.each{|symbol|
|
51
|
+
|
52
|
+
module_eval( "def #{symbol}(); attribute_get(:#{symbol}); end")
|
53
|
+
module_eval( "def #{symbol}=(val, no_dirty = false); attribute_set(:#{symbol}, val, true); end")
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def updatable_date(*args)
|
58
|
+
args.each{|symbol|
|
59
|
+
|
60
|
+
module_eval( "def #{symbol}(); EventBright.formatted_time(attribute_get(:#{symbol})); end")
|
61
|
+
module_eval( "def #{symbol}=(val, no_dirty = false); attribute_set(:#{symbol}, Time.parse(val), no_dirty); end")
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def readable_date(*args)
|
66
|
+
args.each{|symbol|
|
67
|
+
|
68
|
+
module_eval( "def #{symbol}(); EventBright.formatted_time(attribute_get(:#{symbol})); end")
|
69
|
+
module_eval( "def #{symbol}=(val, no_dirty = false); attribute_set(:#{symbol}, Time.parse(val), true); end")
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
# Columns that are the same as other columns. This is mainly useful
|
74
|
+
# for incoming data with inconsistent naming. Args are passed as a hash,
|
75
|
+
# where the key is the new method name, and the value is the target method name
|
76
|
+
# you are mapping the new one onto. Note that this means there is only the original
|
77
|
+
# one stored on the object. Also note this is different from the
|
78
|
+
# renames list, which is exclusively for outgoing hashes sent to the API.
|
79
|
+
def remap(args = {})
|
80
|
+
args.each{|k,v|
|
81
|
+
module_eval( "def #{k}(); #{v}; end")
|
82
|
+
module_eval( "def #{k}=(val,no_dirty = false); self.__send__('#{v}=', val, no_dirty); end")
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
# Defines a has 1 relation
|
87
|
+
def has(args = {})
|
88
|
+
@class_relations ||= {}
|
89
|
+
args.each{|symbol, klass|
|
90
|
+
module_eval( "def #{symbol}(); relation_get(:#{symbol}); end")
|
91
|
+
module_eval( "def dirty_#{symbol}!(); relation_dirty!(:#{symbol}); end")
|
92
|
+
module_eval( "def dirty_#{symbol}?(); relation_dirty?(:#{symbol}); end")
|
93
|
+
module_eval( "def #{symbol}=(val, no_dirty = false); relation_set(:#{symbol}, val, no_dirty); end")
|
94
|
+
@class_relations[symbol] = klass
|
95
|
+
}
|
96
|
+
end
|
97
|
+
def relations
|
98
|
+
@class_relations || {}
|
99
|
+
end
|
100
|
+
|
101
|
+
# Defines a has may relation
|
102
|
+
def collection(args = {})
|
103
|
+
@class_collections ||= {}
|
104
|
+
args.each{|symbol, klass|
|
105
|
+
module_eval( "def #{symbol}(); collection_get(:#{symbol}); end")
|
106
|
+
module_eval( "def dirty_#{symbol}!(); collection_dirty!(:#{symbol}); end")
|
107
|
+
module_eval( "def dirty_#{symbol}?(); collection_dirty?(:#{symbol}); end")
|
108
|
+
module_eval( "def #{symbol}=(val, no_dirty = false); collection_set(:#{symbol}, val, no_dirty); end")
|
109
|
+
@class_collections[symbol] = klass
|
110
|
+
}
|
111
|
+
end
|
112
|
+
def collections
|
113
|
+
@class_collections || {}
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|