engrel 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +20 -0
- data/README.rdoc +62 -0
- data/lib/engrel.rb +43 -0
- data/lib/engrel/mixin.rb +34 -0
- data/lib/engrel/prepositional_phrase.rb +83 -0
- data/lib/engrel/sentence.rb +132 -0
- data/lib/generators/engrel_generator.rb +19 -0
- data/lib/generators/templates/create_engrel_tables.rb +47 -0
- data/test/helper.rb +17 -0
- data/test/test_engrel.rb +7 -0
- metadata +204 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Matt Lightner
|
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,62 @@
|
|
1
|
+
= **ENG**lish **REL**ational Framework
|
2
|
+
|
3
|
+
*A simple and elegant way to specify relations without explicitly making a table for each one.*
|
4
|
+
|
5
|
+
*Modify or delete this text in the editor above.*
|
6
|
+
|
7
|
+
WMD's context-sensitive commands pack a lot of power into a simple user interface. Here are some advanced features to try:
|
8
|
+
|
9
|
+
== Why use English/Sentences instead of Join Tables?
|
10
|
+
|
11
|
+
In a way, we are using join tables--but just one instead of dozens of hundreds. Normal join tables serve one single purpose--to connect A to B under circumstance C. Like to link all of the users who were tagged in a specific photo ID. But if you step back, all that join tables really do is link one object to another with a little bit of context. Engrel puts the context into the join table and voila, one join table can link any two objects **and** provide (often even more) useful context than a full join table. No really.
|
12
|
+
|
13
|
+
== Prepositional Phrases
|
14
|
+
|
15
|
+
Sounds like something only a linguistics professor would care about, but in reality, you use them all the time and they're very helpful in describing relations. For instance, taking an example from Facebook:
|
16
|
+
|
17
|
+
I was tagged in photo ID 23982930 (technically there's already a preposition there, but watch now)
|
18
|
+
I was tagged in photo ID 23982930 by user ID 850932
|
19
|
+
|
20
|
+
More info, right? And more data is always better, we think.
|
21
|
+
|
22
|
+
|
23
|
+
== Console Usage
|
24
|
+
|
25
|
+
irb(main):022:0> s = Engrel::Sentence.claim(User["00002394802384"], :likes, Page["overwerk"])
|
26
|
+
=> #<Engrel::Sentence id: 1, subject_id: 00002394802384, subject_type: "User", direct_object_id: 133241766707287, direct_object_type: "Page", verb: "likes", data: nil, created_at: "2010-11-18 18:41:27", updated_at: "2010-11-18 18:41:27">
|
27
|
+
|
28
|
+
irb(main):024:0> s = Engrel::Sentence.claim(User["00002394802384"], :likes, Page["overwerk"])
|
29
|
+
=> #<Engrel::Sentence id: 1, subject_id: 00002394802384, subject_type: "User", direct_object_id: 133241766707287, direct_object_type: "Page", verb: "likes", data: nil, created_at: "2010-11-18 18:41:27", updated_at: "2010-11-18 18:41:27">
|
30
|
+
|
31
|
+
irb(main):025:0> s.prep(:via, User["00002394804563"])
|
32
|
+
=> #<Engrel::PrepositionalPhrase id: 2, parent_id: 1, parent_type: "Engrel::Sentence", preposition: "via", modifier: nil, indirect_object_id: 00002394804563, indirect_object_type: "User", created_at: "2010-11-18 20:15:39", updated_at: "2010-11-18 20:15:39", started_at: nil, ended_at: nil>
|
33
|
+
|
34
|
+
irb(main):026:0> pp s
|
35
|
+
=> #<Engrel::Sentence id: 1, subject_id: 00002394802384, subject_type: "User", direct_object_id: 133241766707287, direct_object_type: "Page", verb: "likes", data: nil, created_at: "2010-11-18 18:41:27", updated_at: "2010-11-18 18:41:27">
|
36
|
+
|
37
|
+
irb(main):027:0> pp s.prepositional_phrases
|
38
|
+
=> [#<Engrel::PrepositionalPhrase id: 2, parent_id: 1, parent_type: "Engrel::Sentence", preposition: "via", modifier: nil, indirect_object_id: 00002394804563, indirect_object_type: "User", created_at: "2010-11-18 20:15:39", updated_at: "2010-11-18 20:15:39", started_at: nil, ended_at: nil>]
|
39
|
+
|
40
|
+
irb(main):028:0> pp s.to_sentence
|
41
|
+
=> "User[Matt Lightner#00002394802384] likes Page[OVERWERK#133241766707287] via User[Some Friend#00002394804563 indirect_object])
|
42
|
+
|
43
|
+
|
44
|
+
== Use with FBGraph
|
45
|
+
|
46
|
+
|
47
|
+
This was originally designed to solve a problem I ran into while trying to persist Facebook Graph data, and works well with the fbgraph (not fb_graph) library. I recommend you check that out too!
|
48
|
+
|
49
|
+
== Contributing to engrel
|
50
|
+
|
51
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
52
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
53
|
+
* Fork the project
|
54
|
+
* Start a feature/bugfix branch
|
55
|
+
* Commit and push until you are happy with your contribution
|
56
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
57
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
58
|
+
|
59
|
+
== Copyright
|
60
|
+
|
61
|
+
Copyright (c) 2010 Matt Lightner. See LICENSE.txt for
|
62
|
+
further details.
|
data/lib/engrel.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'enumerated_attribute'
|
3
|
+
require 'engrel/sentence'
|
4
|
+
require 'engrel/prepositional_phrase'
|
5
|
+
require 'engrel/mixin'
|
6
|
+
|
7
|
+
# Helper methods that make creating new sentences a joy!
|
8
|
+
module Engrel
|
9
|
+
module Helpers
|
10
|
+
|
11
|
+
# Creates a new relation from scratch--that is, without an implicit subject. Takes arguments in the order they would be written in
|
12
|
+
# an anglish sentence.
|
13
|
+
#
|
14
|
+
# @param [Object] an object, usually an actor.
|
15
|
+
# @param [Symbol] a verb from the vast pre-approved list that decsribes this relation.
|
16
|
+
# @param [Object] the direct object in this
|
17
|
+
# @returns [Sentence] The new Sentence object created to represent this relation.
|
18
|
+
def sentence(*args, &block)
|
19
|
+
Engrel::Sentence.claim(*args, &block)
|
20
|
+
end
|
21
|
+
alias :fact :sentence
|
22
|
+
alias :claim :sentence
|
23
|
+
|
24
|
+
module AciveRecordInstanceMethods
|
25
|
+
# Helper method that gets included into AR::Base that allows any model object to specify a relationship between it and any other
|
26
|
+
# object (the direct object (they're both polymorphic, of course).
|
27
|
+
#
|
28
|
+
# @param [Symbol] The downcased, underscored word representing the transitive verb i.e. (:is_friends_with)
|
29
|
+
# @param [Object] The direct object that is the second receiver for the trasitive verb above.
|
30
|
+
# @returns [Sentence] The new Sentence object created to represent this relation.
|
31
|
+
def fact(verb, direct_object, &block)
|
32
|
+
Engrel::Sentence.claim(self, verb, direct_object, &block)
|
33
|
+
end
|
34
|
+
alias :claim :fact
|
35
|
+
alias :sentence :claim
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
ActiveRecord::Base.send(:include, ::Engrel::Helpers::AciveRecordInstanceMethods) if (defined?(ActiveRecord::Base) rescue false)
|
43
|
+
include ::Engrel::Helpers
|
data/lib/engrel/mixin.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module Engrel
|
4
|
+
module Mixin
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
# Who knows--maybe I'll think of something to put here someday.
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
|
13
|
+
# This is very specific to Facebook--it stores a reference to the object through whose access token the intermediate object was initially fetched.
|
14
|
+
def set_fetcher!(newfetcher = nil)
|
15
|
+
write_attribute(:fetcher_id, newfetcher[:id])
|
16
|
+
write_attribute(:fetcher_type, newfetcher.class.to_s)
|
17
|
+
save(:validate => false)
|
18
|
+
reload
|
19
|
+
fetcher
|
20
|
+
end
|
21
|
+
|
22
|
+
# Make sure we can make an object before we go trying to save the "association".
|
23
|
+
def instantiate_object!(key)
|
24
|
+
key = key.to_sym
|
25
|
+
id_key, type_key = "#{key}_id".to_sym, "#{key}_type".to_sym
|
26
|
+
return true if !self[key].blank? && !(self[key][:id].blank? rescue true)
|
27
|
+
class_name = self[type_key] || (self.send(key).class.to_s rescue "Page")
|
28
|
+
raise "Could not determine class name for #{key} (#{self.to_s})" if class_name.blank?
|
29
|
+
newid = self[id_key] || (self[key][:id] rescue nil)
|
30
|
+
class_name.constantize.spec(newid) rescue raise("Unable to instantiate #{class_name} object with ID #{newid || '[unavailable]'}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'engrel/mixin'
|
2
|
+
|
3
|
+
class Engrel::PrepositionalPhrase < ActiveRecord::Base
|
4
|
+
include Engrel::Mixin
|
5
|
+
|
6
|
+
# This whole top declaration will need changing if you're not using AR.
|
7
|
+
set_table_name "engrel_prepositional_phrases"
|
8
|
+
|
9
|
+
# A prepositional phrase, which answers the questions: how?, which one?, when? with whom? by whom? etc.
|
10
|
+
# http://www.chompchomp.com/terms/prepositionalphrase.htm
|
11
|
+
belongs_to :indirect_object, :polymorphic => true
|
12
|
+
|
13
|
+
# The sentence that owns us.
|
14
|
+
belongs_to :sentence, :class_name => "::Engrel::Sentence"
|
15
|
+
|
16
|
+
enum_attr :preposition, %w( ^about at_time on_date since beginning beginning_at before and as_well_as in_addition_to along_with together_with in_conjunction_with at_time on_date before prior_to after following since beginning beginning_at dring while at_the_sae_time_as about on in_reference_to concerning regarding in inside within inside_of included_in as_part_of via through by_way_of from by at located_at
|
17
|
+
with_location at_venue at_place and as_well_as in_addition_to along_with together_with in_conjunction_with ) do
|
18
|
+
at_time? %w( at_time on_date )
|
19
|
+
before? %w( before prior_to )
|
20
|
+
after? %w( after following )
|
21
|
+
since? %w( since beginning beginning_at )
|
22
|
+
during? %w( dring while at_the_sae_time_as )
|
23
|
+
about? %w( about on in_reference_to concerning regarding )
|
24
|
+
in? %w( in inside within inside_of included_in as_part_of )
|
25
|
+
via? %w( via through by_way_of from by )
|
26
|
+
at? %w( at located_at with_location at_venue at_place )
|
27
|
+
and? %w( and as_well_as in_addition_to along_with together_with in_conjunction_with )
|
28
|
+
|
29
|
+
references_time? { at_time? || before? || after? || during? || since? }
|
30
|
+
references_object? { in? || via? || about? }
|
31
|
+
references_location? { at? || via? } # Yes via is both?
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :ind :indirect_object
|
35
|
+
|
36
|
+
before_save do
|
37
|
+
instantiate_object!(:indirect_object) unless !indirect_object.blank?
|
38
|
+
end
|
39
|
+
|
40
|
+
def has_indirect_object?
|
41
|
+
(self.indirect_object.present? && self.indirect_object[:id].present?) rescue false
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
#### Time Helpers! ####
|
47
|
+
|
48
|
+
def started_at
|
49
|
+
(references_time? && has_indirect_object?) && (ind.started_time rescue nil || ind.started_at rescue nil || ind.created_time rescue nil)
|
50
|
+
end
|
51
|
+
|
52
|
+
def started?; started_at.present?; end
|
53
|
+
alias :starts_at :started_at
|
54
|
+
alias :starts? :started?
|
55
|
+
|
56
|
+
def ended_at
|
57
|
+
(references_time? && has_indirect_object?) && (ind.ended_time rescue nil || ind.ended_at rescue nil || ind.created_time rescue nil)
|
58
|
+
end
|
59
|
+
|
60
|
+
def ended?; ended_at.present?; end
|
61
|
+
alias :ends_at :ended_at
|
62
|
+
alias :ends? :ended?
|
63
|
+
|
64
|
+
def now
|
65
|
+
@now ||= Time.now
|
66
|
+
end
|
67
|
+
|
68
|
+
def active?
|
69
|
+
(started? && !ended?) rescue nil
|
70
|
+
end
|
71
|
+
alias :ongoing? :active?
|
72
|
+
|
73
|
+
# Returning anything here is misleading. Maybe nil?
|
74
|
+
def ended?
|
75
|
+
(started_at < now && ended_at > now) rescue nil
|
76
|
+
end
|
77
|
+
alias :over? :ended?
|
78
|
+
|
79
|
+
def started?
|
80
|
+
(started_at < now) rescue nil
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'engrel/mixin'
|
2
|
+
require 'engrel/prepositional_phrase'
|
3
|
+
|
4
|
+
class Engrel::Sentence < ActiveRecord::Base
|
5
|
+
# This is the main backbone of Engrel. A sentence is just a has and belongs to many relation with a verb attached that tells you the nature of the relationship.
|
6
|
+
# Prepositional phrases are optional and can make relationships ternary and more specific. A sentence can have as many prepositional phrases as is appropriate.
|
7
|
+
|
8
|
+
include Engrel::Mixin
|
9
|
+
|
10
|
+
# NOTE: TO non-AR users--this whole top declaration will need changing if you're not using AR.
|
11
|
+
|
12
|
+
# Set the table name so as not to clash with other tables.
|
13
|
+
set_table_name "engrel_sentences"
|
14
|
+
|
15
|
+
# Usually a user, since they're the "actors" in most systems. The "Who" of the sentence.
|
16
|
+
belongs_to :subject, :polymorphic => true
|
17
|
+
|
18
|
+
# The thing we're being related with. The "What" of the sentence, and the recipieit of theeffect of the transitive verb.
|
19
|
+
# http://www.chompchomp.com/terms/directobject.htm
|
20
|
+
belongs_to :direct_object, :polymorphic => true
|
21
|
+
|
22
|
+
# Prepositions are stored as children. Each has a preposition and an object (i.e. "beside the chair")
|
23
|
+
has_many :prepositional_phrases, :uniq => true
|
24
|
+
|
25
|
+
# There's obviously the possibility that dynamic accessors could be defined to access these "indirect object" so you could say like sentence.well post if the ternary
|
26
|
+
# relation was "Bob posted about Mary on his wall", where the post is the indirect object, mary is the direct object, and Bob is the subject.
|
27
|
+
has_many :indirect_objects, :through => :prepositional_phrases
|
28
|
+
|
29
|
+
# The verb. Specifically a transitive verb (it needs two objects).
|
30
|
+
# commented_on: Something comments on a direct_object.
|
31
|
+
# likes: Something likes a direct_object object.
|
32
|
+
# manages: Something manages a page.
|
33
|
+
# is_friends_with: A user knows another user.
|
34
|
+
# dates: A user dates another user (acts like: knows)
|
35
|
+
# is_related_to: A user is related to another user.
|
36
|
+
# attended: A user attended an event.
|
37
|
+
# worked_for/works_for: User employed by organization.
|
38
|
+
# attended/attends: User attends a school.
|
39
|
+
# checked_in: A user checks in to a page (through a subject)
|
40
|
+
# posted: Something posts an object (photo/video/album/link)
|
41
|
+
# messaged: Someone messages someone else.
|
42
|
+
# wall_messaged: Something posts on something's wall (about a subject/tagged_in user)
|
43
|
+
# subscribes_to: Something subscribes to a feed.
|
44
|
+
# write_note: Something wrote a note (about a subject)
|
45
|
+
# is: A status message.
|
46
|
+
# hosts: Something hosts an event..
|
47
|
+
# is_invited_to: A user is invited to an event/group.
|
48
|
+
enum_attr :verb, %w(^is_friends_with commented_on likes belongs_to manages dates is_related_to attended
|
49
|
+
is_friends_with dates is_related_to worked_for was_employed_by works_for was_laid_off_from founded works_part_time_for attended is_an_avid_alumni teaches_at subscribes_to wall_messaged
|
50
|
+
commented_on checked_in tagged_in posted messaged is wrote_note is_invited_to belongs_to worked_for works_for attends attended is_invited_to religiously_attends tagged_in visited
|
51
|
+
appears_to_be_having_fun_in is_posing_generically_in attends attended is_invited_to does_not_want_to_attend disliked_the_crowd_at ) do
|
52
|
+
|
53
|
+
# When the link acts like "knows" relation
|
54
|
+
# Facebook-specific verbs
|
55
|
+
knows? %w( is_friends_with dates is_related_to )
|
56
|
+
job? %w( worked_for was_employed_by works_for was_laid_off_from founded works_part_time_for)
|
57
|
+
education? %w( attended is_an_avid_alumni teaches_at)
|
58
|
+
subscription? %w( subscribes_to wall_messaged commented_on checked_in tagged_in posted messaged is wrote_note is_invited_to )
|
59
|
+
membership? %w( belongs_to worked_for works_for attends attended is_invited_to religiously_attends )
|
60
|
+
tag? %w( tagged_in visited appears_to_be_having_fun_in is_posing_generically_in )
|
61
|
+
event? %w( attends attended is_invited_to does_not_want_to_attend disliked_the_crowd_at )
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# How we make a new sentence while ensuring an existing one doesn't exist.
|
66
|
+
def self.claim(subject, verb, direct_object)
|
67
|
+
params = {:subject_type => subject.class.to_s, :subject_id => subject[:id], :direct_object_type => direct_object.class.to_s, :direct_object_id => direct_object[:id], :verb => verb.to_s}.stringify_keys
|
68
|
+
s = self.where(params).first
|
69
|
+
s = create(params) if s.blank?
|
70
|
+
s.reload
|
71
|
+
block_given? ? yield(s) : s
|
72
|
+
end
|
73
|
+
|
74
|
+
# This describes the relationship of the subject to the fact.
|
75
|
+
# You can determine your own meaning for these, but try to document your use as you see fit.
|
76
|
+
before_save do
|
77
|
+
instantiate_object!(:subject)
|
78
|
+
instantiate_object!(:direct_object)
|
79
|
+
end
|
80
|
+
|
81
|
+
def object_list
|
82
|
+
[ subject, direct_object ].concat(indirect_objects).compact
|
83
|
+
end
|
84
|
+
|
85
|
+
def has_subject?
|
86
|
+
(self.subject.present? && self.subject[:id].present?) rescue false
|
87
|
+
end
|
88
|
+
|
89
|
+
def has_direct_object?
|
90
|
+
(self.direct_object.present? && self.direct_object[:id].present?) rescue false
|
91
|
+
end
|
92
|
+
|
93
|
+
def verb_enums
|
94
|
+
self.enums(:verb)
|
95
|
+
end
|
96
|
+
|
97
|
+
def verb_label(element = nil)
|
98
|
+
element ||= self.verb
|
99
|
+
verb_enums.label(element.to_sym)
|
100
|
+
end
|
101
|
+
|
102
|
+
def only(*args)
|
103
|
+
self.prepositional_phrases.clear
|
104
|
+
prep(*args)
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
def prep(prep, indirect_object)
|
109
|
+
if self.prepositional_phrases.include?(preposition: prep, indirect_object_id: indirect_object.id, indirect_object_type: indirect_object.class.to_s)
|
110
|
+
warn "PREP ALREADY EXISTS!"
|
111
|
+
else
|
112
|
+
self.prepositional_phrases.create(preposition: prep, indirect_object: indirect_object)
|
113
|
+
end
|
114
|
+
self
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_sentence_colored
|
118
|
+
sen = "#{subject_type.humanize}[#{subject.name rescue subject_id}\##{subject_id}]".green +
|
119
|
+
" #{verb_label.downcase} " + "#{direct_object_type.humanize}[#{direct_object.name rescue direct_object_id}\##{direct_object_id}]".cyan
|
120
|
+
sen += " " unless prepositional_phrases.blank? rescue true
|
121
|
+
preps = prepositional_phrases.collect { |p| "#{p.preposition.to_s.humanize.downcase} " + "#{p.indirect_object_type.humanize}[#{p.object.name rescue p.indirect_object_id}\##{p.indirect_object_id}]".yellow }.join(" ") rescue nil
|
122
|
+
sen << preps unless preps.blank?
|
123
|
+
sen += '.'
|
124
|
+
sen
|
125
|
+
end
|
126
|
+
|
127
|
+
# TODO: Properly strip ANSI color chars
|
128
|
+
def to_sentence
|
129
|
+
to_sentence_colored
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rails/generators/migration'
|
2
|
+
|
3
|
+
# Very simple--we're doing a straight copy of the migration.
|
4
|
+
class EngrelGenerator < Rails::Generators::Base
|
5
|
+
include Rails::Generators::Migration
|
6
|
+
|
7
|
+
def self.source_root
|
8
|
+
@_acts_as_engrelable_source_root ||= File.expand_path("../templates", __FILE__)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.next_migration_number(path)
|
12
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_model_file
|
16
|
+
template "engrel.rb", "app/models/engrel.rb"
|
17
|
+
migration_template "create_engrel_tables.rb", "db/migrate/create_engrel_tables.rb"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class CreateEngrelTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :engrel_sentences, :force => true do |t|
|
4
|
+
t.column :subject_id, "BIGINT"
|
5
|
+
t.column :subject_type, :string
|
6
|
+
|
7
|
+
t.column :direct_object_id, "BIGINT"
|
8
|
+
t.column :direct_object_type, :string
|
9
|
+
|
10
|
+
t.enum :verb
|
11
|
+
t.string :direct_object_data
|
12
|
+
|
13
|
+
t.datetime :created_at
|
14
|
+
t.datetime :updated_at
|
15
|
+
end
|
16
|
+
|
17
|
+
add_index :engrel_sentences, :direct_object_id, :name => "direct_object_index"
|
18
|
+
add_index :engrel_sentences, :subject_id, :name => "subject_index"
|
19
|
+
add_index :engrel_sentences, :verb, :name => "verb_index"
|
20
|
+
change_column :engrel_sentences, :id, 'BIGINT NOT NULL AUTO_INCREMENT' # For big IDs like Facebook
|
21
|
+
|
22
|
+
create_table :engrel_prepositional_phrases, :force => true do |t|
|
23
|
+
t.references :sentence
|
24
|
+
|
25
|
+
t.enum :preposition
|
26
|
+
t.enum :modifier
|
27
|
+
|
28
|
+
t.column :indirect_object_id, "BIGINT"
|
29
|
+
t.column :indirect_object_type, :string
|
30
|
+
|
31
|
+
t.string :indirect_object_data
|
32
|
+
|
33
|
+
t.datetime :created_at
|
34
|
+
t.datetime :updated_at
|
35
|
+
end
|
36
|
+
|
37
|
+
add_index :engrel_prepositional_phrases, :indirect_object_id, :name => "indirect_object_index"
|
38
|
+
add_index :engrel_prepositional_phrases, :preposition, :name => "preposition_index"
|
39
|
+
change_column :engrel_prepositional_phrases, :id, 'BIGINT NOT NULL AUTO_INCREMENT'
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.down
|
43
|
+
drop_table :engrel_sentences
|
44
|
+
drop_table :engrel_prepositional_phrases
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
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 'test/unit'
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
require 'engrel'
|
15
|
+
|
16
|
+
class Test::Unit::TestCase
|
17
|
+
end
|
data/test/test_engrel.rb
ADDED
metadata
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: engrel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 10
|
8
|
+
- 0
|
9
|
+
version: 0.10.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Matt Lightner
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-11-24 00:00:00 -06:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: activerecord
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 3
|
29
|
+
- 0
|
30
|
+
- 0
|
31
|
+
version: 3.0.0
|
32
|
+
type: :runtime
|
33
|
+
prerelease: false
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: activesupport
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 3
|
44
|
+
- 0
|
45
|
+
- 0
|
46
|
+
version: 3.0.0
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: text-highlight
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :runtime
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: enumerated_attribute
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
type: :runtime
|
74
|
+
prerelease: false
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: yard
|
78
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ~>
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
- 6
|
86
|
+
- 0
|
87
|
+
version: 0.6.0
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *id005
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: bundler
|
93
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
segments:
|
99
|
+
- 1
|
100
|
+
- 0
|
101
|
+
- 0
|
102
|
+
version: 1.0.0
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: *id006
|
106
|
+
- !ruby/object:Gem::Dependency
|
107
|
+
name: jeweler
|
108
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ~>
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
segments:
|
114
|
+
- 1
|
115
|
+
- 5
|
116
|
+
- 1
|
117
|
+
version: 1.5.1
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: *id007
|
121
|
+
- !ruby/object:Gem::Dependency
|
122
|
+
name: rcov
|
123
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
version: "0"
|
131
|
+
type: :development
|
132
|
+
prerelease: false
|
133
|
+
version_requirements: *id008
|
134
|
+
- !ruby/object:Gem::Dependency
|
135
|
+
name: active_support
|
136
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ">"
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
segments:
|
142
|
+
- 3
|
143
|
+
- 0
|
144
|
+
- 0
|
145
|
+
version: 3.0.0
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: *id009
|
149
|
+
description: Allows for natural grammar to specify object relationships based on parts of speech.
|
150
|
+
email: mlightner@gmail.com
|
151
|
+
executables: []
|
152
|
+
|
153
|
+
extensions: []
|
154
|
+
|
155
|
+
extra_rdoc_files:
|
156
|
+
- LICENSE.txt
|
157
|
+
- README.rdoc
|
158
|
+
files:
|
159
|
+
- README.rdoc
|
160
|
+
- lib/engrel.rb
|
161
|
+
- lib/engrel/mixin.rb
|
162
|
+
- lib/engrel/prepositional_phrase.rb
|
163
|
+
- lib/engrel/sentence.rb
|
164
|
+
- lib/generators/engrel_generator.rb
|
165
|
+
- lib/generators/templates/create_engrel_tables.rb
|
166
|
+
- LICENSE.txt
|
167
|
+
- test/helper.rb
|
168
|
+
- test/test_engrel.rb
|
169
|
+
has_rdoc: true
|
170
|
+
homepage: http://engrel.com
|
171
|
+
licenses:
|
172
|
+
- MIT
|
173
|
+
post_install_message:
|
174
|
+
rdoc_options: []
|
175
|
+
|
176
|
+
require_paths:
|
177
|
+
- lib
|
178
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
179
|
+
none: false
|
180
|
+
requirements:
|
181
|
+
- - ">="
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
hash: 3076847749877114109
|
184
|
+
segments:
|
185
|
+
- 0
|
186
|
+
version: "0"
|
187
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
|
+
none: false
|
189
|
+
requirements:
|
190
|
+
- - ">="
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
segments:
|
193
|
+
- 0
|
194
|
+
version: "0"
|
195
|
+
requirements: []
|
196
|
+
|
197
|
+
rubyforge_project:
|
198
|
+
rubygems_version: 1.3.7
|
199
|
+
signing_key:
|
200
|
+
specification_version: 3
|
201
|
+
summary: A highly flexible entity relationship management system that requires only two tables and lots of clever.
|
202
|
+
test_files:
|
203
|
+
- test/helper.rb
|
204
|
+
- test/test_engrel.rb
|