harukizaemon-drupal_fu 1.0.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/CHANGELOG.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ == 1.0.0 released 2009-01-12
2
+
3
+ * Add some very basic RDOC and packaged up as a gem.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Cogent Consulting, Pty. Ltd.
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.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = Drupal Fu
2
+
3
+ Drupal Fu is a Ruby on Rails plugin that helps with integrating Rails applications with Drupal.
4
+
5
+ == Installation
6
+
7
+ You have two choices for installation. The first uses a gem (recommended):
8
+
9
+ config.gem "harukizaemon-drupal_fu", :lib => "drupal_fu", :source => "http://gems.github.com"
10
+
11
+ Or you can use the Rails plugin
12
+
13
+ $ ruby script/plugin install git://github.com/harukizaemon/drupal_fu.git
14
+
15
+ === License
16
+
17
+ This plugin is copyright 2009 by 2009 Cogent Consulting, Pty. Ltd. and is released under the MIT license.
data/drupal_fu.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "drupal_fu"
3
+ s.version = "1.0.0"
4
+ s.date = "2009-01-12"
5
+ s.summary = "Ruby on Rails Models and Helpers for integrating with Drupal."
6
+ s.email = "simon.harris@cogentconsulting.com.au"
7
+ s.homepage = "http://github.com/harukizaemon/drupal_fu"
8
+ s.description = "Ruby on Rails Models and Helpers for integrating with Drupal."
9
+ s.has_rdoc = true
10
+ s.authors = ["Simon Harris"]
11
+ s.files = ["CHANGELOG.rdoc",
12
+ "MIT-LICENSE",
13
+ "README.rdoc",
14
+ "drupal_fu.gemspec",
15
+ "lib/drupal/authmap.rb",
16
+ "lib/drupal/base.rb",
17
+ "lib/drupal/helper.rb",
18
+ "lib/drupal/menu_link.rb",
19
+ "lib/drupal/menu_router.rb",
20
+ "lib/drupal/profile_field.rb",
21
+ "lib/drupal/serialize.rb",
22
+ "lib/drupal/session.rb",
23
+ "lib/drupal/session_store.rb",
24
+ "lib/drupal/url_alias.rb",
25
+ "lib/drupal/user.rb",
26
+ "lib/drupal/variable.rb",
27
+ "lib/drupal_fu.rb",
28
+ "lib/tasks",
29
+ "lib/tasks/drupal.rake"]
30
+ s.rdoc_options = ["--main", "README.rdoc"]
31
+ s.extra_rdoc_files = ["CHANGELOG.rdoc", "README.rdoc"]
32
+ end
@@ -0,0 +1,6 @@
1
+ module Drupal
2
+ class Authmap < Base
3
+ set_table_name "authmap"
4
+ set_primary_key "aid"
5
+ end
6
+ end
@@ -0,0 +1,31 @@
1
+ module Drupal
2
+ # Base class for all Drupal-specific model classes. If your Rails and Drupal applications share a common database then
3
+ # you can use this class as is. If your Drupal database is seperate, you can do something along the lines of the
4
+ # following in environment.rb:
5
+ #
6
+ # Drupal::Base.establish_connection "drupal_#{RAILS_ENV}"
7
+ #
8
+ # And add the corresponding entries in database.yml; one for each environment.
9
+ class Base < ActiveRecord::Base
10
+ self.abstract_class = true
11
+
12
+ protected
13
+
14
+ # Convenience method for marking model attributes as serialized. Supports a Ruby-compatible subset of the PHP
15
+ # serialisation mechanism.
16
+ def self.serializes(*attr_names)
17
+ attr_names.each do |attr_name|
18
+ class_eval <<-EOS
19
+ def #{attr_name}
20
+ @unserialized_#{attr_name} ||= Drupal::Serialize.unserialize(super)
21
+ end
22
+
23
+ def #{attr_name}=(new_value)
24
+ @unserialized_#{attr_name} = new_value
25
+ super Drupal::Serialize.serialize(new_value)
26
+ end
27
+ EOS
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,46 @@
1
+ module Drupal
2
+ # Some useful helper methods for accessing various configuration items. Simply include this module in whichever
3
+ # controller(s) need the behaviour. For example:
4
+ #
5
+ # class ApplicationController < ActionController::Base
6
+ # include Drupal::Helper
7
+ # ...
8
+ # end
9
+ module Helper
10
+ def self.included(base)
11
+ base.send(:helper_method, :primary_links, :root_path, :login_path, :site_name, :site_slogan)
12
+ end
13
+
14
+ protected
15
+
16
+ def primary_links
17
+ @primary_links ||= menu_links('primary-links')
18
+ end
19
+
20
+ def root_path
21
+ "/"
22
+ end
23
+
24
+ def login_path
25
+ @login_path ||= Drupal::UrlAlias.url_for("/user/login")
26
+ end
27
+
28
+ def site_name
29
+ @site_name ||= Drupal::Variable.value_of("site_name")
30
+ end
31
+
32
+ def site_slogan
33
+ @site_slogan ||= Drupal::Variable.value_of("site_slogan")
34
+ end
35
+
36
+ private
37
+
38
+ def menu_links(name)
39
+ Drupal::MenuLink.find(:all,
40
+ :joins => :menu_router,
41
+ :conditions => ["menu_name = ? AND hidden = 0 AND #{Drupal::MenuRouter.table_name}.access_callback <> 'user_is_anonymous'", name],
42
+ :order => "weight",
43
+ :readonly => true)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,15 @@
1
+ module Drupal
2
+ class MenuLink < Base
3
+ set_primary_key "mlid"
4
+ serializes "options"
5
+ belongs_to :menu_router, :foreign_key => "router_path", :class_name => "Drupal::MenuRouter"
6
+
7
+ def title
8
+ link_title
9
+ end
10
+
11
+ def path
12
+ @path ||= Drupal::UrlAlias.url_for(link_path)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Drupal
2
+ class MenuRouter < Base
3
+ set_table_name "menu_router"
4
+ set_primary_key "path"
5
+ self.inheritance_column = nil
6
+ serializes "access_arguments", "page_arguments", "title_arguments", "load_functions", "to_arg_functions"
7
+ has_many :menu_links, :foreign_key => "router_path", :class_name => "Drupal::MenuLink"
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ module Drupal
2
+ class ProfileField < Base
3
+ set_primary_key "fid"
4
+ self.inheritance_column = nil
5
+ has_and_belongs_to_many :users, :class_name => "Drupal::User", :join_table => "profile_values", :foreign_key => "fid", :association_foreign_key => "uid"
6
+
7
+ def value
8
+ @unserialized_value ||= case self[:type]
9
+ when "checkbox" then super != "0"
10
+ when "url" then URI.parse(super)
11
+ when "date"
12
+ hash = Serialize.unserialize(super)
13
+ Date.new(hash["year"].to_i, hash["month"].to_i, hash["day"].to_i)
14
+ when "list" then super.split(/[,\n\r]/).map(&:strip)
15
+ else super
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,189 @@
1
+ module Drupal
2
+ # Implements a Ruby-compatible subset of the PHP serialisation mechanism. This is often used for storing structured
3
+ # data in text database columns.
4
+ module Serialize
5
+ # Serialises a value. For example:
6
+ #
7
+ # Drupal::Serialize.serialize("Hello, World!") # => "s:13:\"Hello, World!\";"
8
+ def self.serialize(var, assoc = false)
9
+ s = ''
10
+ case var
11
+ when Array
12
+ s << "a:#{var.size}:{"
13
+ if assoc and var.first.is_a?(Array) and var.first.size == 2
14
+ var.each { |k,v|
15
+ s << self.serialize(k) << self.serialize(v)
16
+ }
17
+ else
18
+ var.each_with_index { |v,i|
19
+ s << "i:#{i};#{self.serialize(v)}"
20
+ }
21
+ end
22
+
23
+ s << '}'
24
+
25
+ when Hash
26
+ s << "a:#{var.size}:{"
27
+ var.each do |k,v|
28
+ s << "#{self.serialize(k)}#{self.serialize(v)}"
29
+ end
30
+ s << '}'
31
+
32
+ when Struct
33
+ # encode as Object with same name
34
+ s << "O:#{var.class.to_s.length}:\"#{var.class.to_s.downcase}\":#{var.members.length}:{"
35
+ var.members.each do |member|
36
+ s << "#{self.serialize(member)}#{self.serialize(var[member])}"
37
+ end
38
+ s << '}'
39
+
40
+ when String
41
+ s << "s:#{var.length}:\"#{var}\";"
42
+
43
+ when Fixnum # PHP doesn't have bignums
44
+ s << "i:#{var};"
45
+
46
+ when Float
47
+ s << "d:#{var};"
48
+
49
+ when NilClass
50
+ s << 'N;'
51
+
52
+ when FalseClass, TrueClass
53
+ s << "b:#{var ? 1 :0};"
54
+
55
+ else
56
+ if var.respond_to?(:to_assoc)
57
+ v = var.to_assoc
58
+ # encode as Object with same name
59
+ s << "O:#{var.class.to_s.length}:\"#{var.class.to_s.downcase}\":#{v.length}:{"
60
+ v.each do |k,v|
61
+ s << "#{self.serialize(k.to_s)}#{self.serialize(v)}"
62
+ end
63
+ s << '}'
64
+ else
65
+ raise TypeError, "Unable to serialize type #{var.class}"
66
+ end
67
+ end
68
+
69
+ s
70
+ end
71
+
72
+ # Unserialises a value. For example:
73
+ #
74
+ # Drupal::Serialize.unserialize("s:13:\"Hello, World!\";") # "Hello, World!"
75
+ def self.unserialize(string, classmap = nil, assoc = false)
76
+ string = StringIO.new(string)
77
+ def string.read_until(char)
78
+ val = ''
79
+ while (c = self.read(1)) != char
80
+ val << c
81
+ end
82
+ val
83
+ end
84
+
85
+ classmap ||= Hash.new
86
+
87
+ _unserialize(string, classmap, assoc)
88
+ end
89
+
90
+ private
91
+
92
+ def self._unserialize(string, classmap, assoc)
93
+ val = nil
94
+ # determine a type
95
+ type = string.read(2)[0,1]
96
+ case type
97
+ when 'a' # associative array, a:length:{[index][value]...}
98
+ count = string.read_until('{').to_i
99
+ val = vals = Array.new
100
+ count.times do |i|
101
+ vals << [_unserialize(string, classmap, assoc), _unserialize(string, classmap, assoc)]
102
+ end
103
+ string.read(1) # skip the ending }
104
+
105
+ unless assoc
106
+ # now, we have an associative array, let's clean it up a bit...
107
+ # arrays have all numeric indexes, in order; otherwise we assume a hash
108
+ array = true
109
+ i = 0
110
+ vals.each do |key,value|
111
+ if key != i # wrong index -> assume hash
112
+ array = false
113
+ break
114
+ end
115
+ i += 1
116
+ end
117
+
118
+ if array
119
+ vals.collect! do |key,value|
120
+ value
121
+ end
122
+ else
123
+ val = Hash.new
124
+ vals.each do |key,value|
125
+ val[key] = value
126
+ end
127
+ end
128
+ end
129
+
130
+ when 'O' # object, O:length:"class":length:{[attribute][value]...}
131
+ # class name (lowercase in PHP, grr)
132
+ len = string.read_until(':').to_i + 3 # quotes, seperator
133
+ klass = string.read(len)[1...-2].capitalize.intern # read it, kill useless quotes
134
+
135
+ # read the attributes
136
+ attrs = []
137
+ len = string.read_until('{').to_i
138
+
139
+ len.times do
140
+ attr = (_unserialize(string, classmap, assoc))
141
+ attrs << [attr.intern, (attr << '=').intern, _unserialize(string, classmap, assoc)]
142
+ end
143
+ string.read(1)
144
+
145
+ val = nil
146
+ # See if we need to map to a particular object
147
+ if classmap.has_key?(klass)
148
+ val = classmap[klass].new
149
+ elsif Struct.const_defined?(klass) # Nope; see if there's a Struct
150
+ classmap[klass] = val = Struct.const_get(klass)
151
+ val = val.new
152
+ else # Nope; see if there's a Constant
153
+ begin
154
+ classmap[klass] = val = Module.const_get(klass)
155
+
156
+ val = val.new
157
+ rescue NameError # Nope; make a new Struct
158
+ classmap[klass] = val = Struct.new(klass.to_s, *attrs.collect { |v| v[0].to_s })
159
+ end
160
+ end
161
+
162
+ attrs.each do |attr,attrassign,v|
163
+ val.__send__(attrassign, v)
164
+ end
165
+
166
+ when 's' # string, s:length:"data";
167
+ len = string.read_until(':').to_i + 3 # quotes, separator
168
+ val = string.read(len)[1...-2] # read it, kill useless quotes
169
+
170
+ when 'i' # integer, i:123
171
+ val = string.read_until(';').to_i
172
+
173
+ when 'd' # double (float), d:1.23
174
+ val = string.read_until(';').to_f
175
+
176
+ when 'N' # NULL, N;
177
+ val = nil
178
+
179
+ when 'b' # bool, b:0 or 1
180
+ val = (string.read(2)[0] == ?1 ? true : false)
181
+
182
+ else
183
+ raise TypeError, "Unable to unserialize type '#{type}'"
184
+ end
185
+
186
+ val
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,35 @@
1
+ module Drupal
2
+ class Session < Base
3
+ set_primary_key "sid"
4
+ belongs_to :user, :foreign_key => "uid", :class_name => "Drupal::User"
5
+
6
+ def self.authenticate(sid)
7
+ find(:first, :conditions => ["#{table_name}.sid = ? AND #{User.table_name}.status = 1", sid], :include => :user)
8
+ end
9
+
10
+ def session
11
+ @unserialized_session ||= decode(super || "")
12
+ end
13
+
14
+ def session=(new_value)
15
+ @unserialized_data = new_value
16
+ super encode(new_value)
17
+ end
18
+
19
+ private
20
+
21
+ def encode(data)
22
+ result = ""
23
+ data.each { |key, value| result << key << "|" << Drupal::Serialize.serialize(value) }
24
+ result
25
+ end
26
+
27
+ def decode(data)
28
+ result = {}
29
+ vars = data.split(/([a-zA-Z0-9]+)\|/)
30
+ vars.shift
31
+ vars.each_slice(2) { |pair| result[pair.first] = Drupal::Serialize.unserialize(pair.last) }
32
+ result
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,65 @@
1
+ module Drupal
2
+ class SessionStore
3
+ def self.stub(login)
4
+ self.class_eval <<-EOS
5
+ def initialize_with_stubbing(session, options = {})
6
+ user = Drupal::User.find_or_create_by_name("#{login}")
7
+ user.update_attributes!(:status => 1)
8
+ Drupal::Session.find_or_create_by_sid_and_uid(session.session_id, user.uid)
9
+ initialize_without_stubbing(session, options)
10
+ end
11
+ alias_method_chain :initialize, :stubbing
12
+ EOS
13
+
14
+ Digest::MD5.hexdigest(login)
15
+ end
16
+
17
+ def initialize(session, options = {})
18
+ @session = Drupal::Session.authenticate(session.session_id)
19
+ raise CGI::Session::NoSession, "uninitialized session" if @session.nil?
20
+ end
21
+
22
+ # Restore session data from the record.
23
+ def restore
24
+ @data = decode(@session.session)
25
+ end
26
+
27
+ # Wait until close to write the session data.
28
+ def update; end
29
+
30
+ # Update the database.
31
+ def close
32
+ now = Time.now.to_i
33
+ @session.timestamp = now
34
+ @session.session = encode(@data) if defined?(@data)
35
+ @session.save!
36
+ @session.user.access = now
37
+ @session.user.save!
38
+ @session = nil
39
+ @data = nil
40
+ end
41
+
42
+ # This is handled by Drupal.
43
+ def delete
44
+ @session = nil
45
+ @data = nil
46
+ end
47
+
48
+ private
49
+
50
+ def encode(data)
51
+ data = data.dup
52
+ data.delete(:user)
53
+ data.delete("flash") if data["flash"].blank?
54
+ data
55
+ end
56
+
57
+ def decode(data)
58
+ data = data.dup
59
+ flash = data["flash"]
60
+ data["flash"] = ActionController::Flash::FlashHash.new.replace(flash) if flash
61
+ data[:user] = @session.user
62
+ data
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,14 @@
1
+ module Drupal
2
+ class UrlAlias < Base
3
+ set_table_name "url_alias"
4
+ set_primary_key "pid"
5
+
6
+ def self.url_for(path, language = "")
7
+ if url_alias = self.find_by_src_and_language(path, language)
8
+ url_alias.dst
9
+ else
10
+ path
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ module Drupal
2
+ class User < Base
3
+ set_primary_key "uid"
4
+
5
+ has_many :sessions, :foreign_key => "sid", :class_name => "Drupal::Session"
6
+ has_and_belongs_to_many :profile_fields, :class_name => "Drupal::ProfileField", :join_table => "profile_values", :foreign_key => "uid", :association_foreign_key => "fid"
7
+ has_many :openids, :foreign_key => "uid", :class_name => "Drupal::Authmap", :conditions => { :module => "openid" }
8
+ serializes "data"
9
+
10
+ # Authenticate a user given a name and password. For example:
11
+ #
12
+ # if user = Drupal::User.authenticate("bob", "flibble")
13
+ # # At this point, we have a valid user record
14
+ # else
15
+ # # Could be an invalid user/password combo or the user might be blocked
16
+ # end
17
+ def self.authenticate(name, password)
18
+ find_by_name_and_pass_and_status(name, Digest::MD5.hexdigest(password), 1)
19
+ end
20
+
21
+ # Returns true if the user is allowed to login.
22
+ def active?
23
+ status == 1
24
+ end
25
+
26
+ # Returns true if the user has been barred from logging in.
27
+ def blocked?
28
+ !active?
29
+ end
30
+
31
+ # Returns true if the user is the system administrator account.
32
+ def administrator?
33
+ uid == 1
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ module Drupal
2
+ class Variable < Base
3
+ set_table_name "variable"
4
+ set_primary_key "name"
5
+ serializes "value"
6
+
7
+ def self.value_of(name)
8
+ if variable = self.find_by_name(name)
9
+ variable.value
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/drupal_fu.rb ADDED
@@ -0,0 +1 @@
1
+ # Do stuff
@@ -0,0 +1,37 @@
1
+ namespace :drupal do
2
+ namespace :db do
3
+ namespace :test do
4
+ desc "Empty the drupal test database"
5
+ task :purge => :environment do
6
+ abcs = ActiveRecord::Base.configurations
7
+ ActiveRecord::Base.clear_active_connections!
8
+ drop_database(abcs['drupal_test'])
9
+ create_database(abcs['drupal_test'])
10
+ end
11
+
12
+ desc "Prepare the drupal test database"
13
+ task :prepare => "drupal:db:test:purge" do
14
+ Drupal::Base.establish_connection(ActiveRecord::Base.configurations['drupal_test'])
15
+ ActiveRecord::Schema.verbose = false
16
+ Rake::Task["drupal:db:schema:load"].invoke
17
+ end
18
+ end
19
+
20
+ namespace :schema do
21
+ desc "Create a db/drupal_schema.rb file that can be portably used against any DB supported by AR"
22
+ task :dump => :environment do
23
+ require 'active_record/schema_dumper'
24
+ File.open(ENV['DRUPAL_SCHEMA'] || "db/drupal_schema.rb", "w") do |file|
25
+ ActiveRecord::SchemaDumper.dump(Drupal::Base.connection, file)
26
+ end
27
+ end
28
+
29
+ desc "Load a drupal_schema.rb file into the database"
30
+ task :load => :environment do
31
+ ActiveRecord::Base.connection = Drupal::Base.connection
32
+ load(ENV['DRUPAL_SCHEMA'] || "db/drupal_schema.rb")
33
+ ActiveRecord::Base.clear_active_connections!
34
+ end
35
+ end
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: harukizaemon-drupal_fu
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Simon Harris
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-12 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Ruby on Rails Models and Helpers for integrating with Drupal.
17
+ email: simon.harris@cogentconsulting.com.au
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - CHANGELOG.rdoc
24
+ - README.rdoc
25
+ files:
26
+ - CHANGELOG.rdoc
27
+ - MIT-LICENSE
28
+ - README.rdoc
29
+ - drupal_fu.gemspec
30
+ - lib/drupal/authmap.rb
31
+ - lib/drupal/base.rb
32
+ - lib/drupal/helper.rb
33
+ - lib/drupal/menu_link.rb
34
+ - lib/drupal/menu_router.rb
35
+ - lib/drupal/profile_field.rb
36
+ - lib/drupal/serialize.rb
37
+ - lib/drupal/session.rb
38
+ - lib/drupal/session_store.rb
39
+ - lib/drupal/url_alias.rb
40
+ - lib/drupal/user.rb
41
+ - lib/drupal/variable.rb
42
+ - lib/drupal_fu.rb
43
+ - lib/tasks
44
+ - lib/tasks/drupal.rake
45
+ has_rdoc: true
46
+ homepage: http://github.com/harukizaemon/drupal_fu
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --main
50
+ - README.rdoc
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.2.0
69
+ signing_key:
70
+ specification_version: 2
71
+ summary: Ruby on Rails Models and Helpers for integrating with Drupal.
72
+ test_files: []
73
+