social_stream 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +16 -0
- data/Gemfile.lock +117 -0
- data/LICENSE +20 -0
- data/README.rdoc +63 -0
- data/Rakefile +43 -0
- data/app/controllers/home_controller.rb +3 -0
- data/app/helpers/activities_helper.rb +10 -0
- data/app/models/activity.rb +75 -0
- data/app/models/activity_object.rb +18 -0
- data/app/models/activity_object_activity.rb +4 -0
- data/app/models/activity_verb.rb +14 -0
- data/app/models/actor.rb +31 -0
- data/app/models/permission.rb +4 -0
- data/app/models/relation.rb +73 -0
- data/app/models/relation_permission.rb +4 -0
- data/app/models/tie.rb +207 -0
- data/app/models/user.rb +82 -0
- data/app/views/activities/_activity.html.erb +5 -0
- data/app/views/activities/_activity_options.html.erb +8 -0
- data/app/views/activities/_jquery.html.erb +52 -0
- data/app/views/activities/_new.html.erb +13 -0
- data/app/views/activities/_root_activity.html.erb +44 -0
- data/app/views/activities/_subactivity.html.erb +23 -0
- data/app/views/activities/_subactivity_options.html.erb +7 -0
- data/app/views/devise/registrations/new.html.erb +21 -0
- data/app/views/home/_activities.html.erb +19 -0
- data/app/views/home/_location.html.erb +3 -0
- data/app/views/home/index.html.erb +4 -0
- data/app/views/ties/_pending.html.erb +33 -0
- data/config/locales/en.yml +29 -0
- data/lib/generators/social_stream/USAGE +9 -0
- data/lib/generators/social_stream/install_generator.rb +30 -0
- data/lib/generators/social_stream/templates/initializer.rb +14 -0
- data/lib/generators/social_stream/templates/migration.rb +131 -0
- data/lib/generators/social_stream/templates/seeds.yml +29 -0
- data/lib/social_stream.rb +49 -0
- data/lib/social_stream/models/activity_object.rb +59 -0
- data/lib/social_stream/models/actor.rb +30 -0
- data/lib/social_stream/models/supertype.rb +41 -0
- data/lib/social_stream/rails.rb +13 -0
- data/lib/social_stream/rails/common.rb +34 -0
- data/lib/social_stream/rails/engine.rb +7 -0
- data/lib/social_stream/rails/railtie.rb +7 -0
- data/lib/social_stream/rails/routes.rb +17 -0
- data/lib/social_stream/seed.rb +47 -0
- data/lib/social_stream/version.rb +3 -0
- metadata +144 -0
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "rails", "3.0.0"
|
4
|
+
gem "capybara", ">= 0.3.9"
|
5
|
+
gem "sqlite3-ruby", :require => "sqlite3"
|
6
|
+
|
7
|
+
if RUBY_VERSION < '1.9'
|
8
|
+
gem "ruby-debug", ">= 0.10.3"
|
9
|
+
end
|
10
|
+
|
11
|
+
gem 'atd-ancestry', :require => 'ancestry'
|
12
|
+
gem 'cancan'
|
13
|
+
|
14
|
+
gem "rspec-rails", ">= 2.0.0.beta"
|
15
|
+
gem "factory_girl"
|
16
|
+
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
abstract (1.0.0)
|
5
|
+
actionmailer (3.0.0)
|
6
|
+
actionpack (= 3.0.0)
|
7
|
+
mail (~> 2.2.5)
|
8
|
+
actionpack (3.0.0)
|
9
|
+
activemodel (= 3.0.0)
|
10
|
+
activesupport (= 3.0.0)
|
11
|
+
builder (~> 2.1.2)
|
12
|
+
erubis (~> 2.6.6)
|
13
|
+
i18n (~> 0.4.1)
|
14
|
+
rack (~> 1.2.1)
|
15
|
+
rack-mount (~> 0.6.12)
|
16
|
+
rack-test (~> 0.5.4)
|
17
|
+
tzinfo (~> 0.3.23)
|
18
|
+
activemodel (3.0.0)
|
19
|
+
activesupport (= 3.0.0)
|
20
|
+
builder (~> 2.1.2)
|
21
|
+
i18n (~> 0.4.1)
|
22
|
+
activerecord (3.0.0)
|
23
|
+
activemodel (= 3.0.0)
|
24
|
+
activesupport (= 3.0.0)
|
25
|
+
arel (~> 1.0.0)
|
26
|
+
tzinfo (~> 0.3.23)
|
27
|
+
activeresource (3.0.0)
|
28
|
+
activemodel (= 3.0.0)
|
29
|
+
activesupport (= 3.0.0)
|
30
|
+
activesupport (3.0.0)
|
31
|
+
arel (1.0.1)
|
32
|
+
activesupport (~> 3.0.0)
|
33
|
+
atd-ancestry (1.3.0)
|
34
|
+
builder (2.1.2)
|
35
|
+
cancan (1.3.4)
|
36
|
+
capybara (0.3.9)
|
37
|
+
culerity (>= 0.2.4)
|
38
|
+
mime-types (>= 1.16)
|
39
|
+
nokogiri (>= 1.3.3)
|
40
|
+
rack (>= 1.0.0)
|
41
|
+
rack-test (>= 0.5.4)
|
42
|
+
selenium-webdriver (>= 0.0.3)
|
43
|
+
columnize (0.3.1)
|
44
|
+
culerity (0.2.12)
|
45
|
+
diff-lcs (1.1.2)
|
46
|
+
erubis (2.6.6)
|
47
|
+
abstract (>= 1.0.0)
|
48
|
+
factory_girl (1.3.2)
|
49
|
+
ffi (0.6.3)
|
50
|
+
rake (>= 0.8.7)
|
51
|
+
i18n (0.4.1)
|
52
|
+
json_pure (1.4.6)
|
53
|
+
linecache (0.43)
|
54
|
+
mail (2.2.5)
|
55
|
+
activesupport (>= 2.3.6)
|
56
|
+
mime-types
|
57
|
+
treetop (>= 1.4.5)
|
58
|
+
mime-types (1.16)
|
59
|
+
nokogiri (1.4.3.1)
|
60
|
+
polyglot (0.3.1)
|
61
|
+
rack (1.2.1)
|
62
|
+
rack-mount (0.6.13)
|
63
|
+
rack (>= 1.0.0)
|
64
|
+
rack-test (0.5.4)
|
65
|
+
rack (>= 1.0)
|
66
|
+
rails (3.0.0)
|
67
|
+
actionmailer (= 3.0.0)
|
68
|
+
actionpack (= 3.0.0)
|
69
|
+
activerecord (= 3.0.0)
|
70
|
+
activeresource (= 3.0.0)
|
71
|
+
activesupport (= 3.0.0)
|
72
|
+
bundler (~> 1.0.0)
|
73
|
+
railties (= 3.0.0)
|
74
|
+
railties (3.0.0)
|
75
|
+
actionpack (= 3.0.0)
|
76
|
+
activesupport (= 3.0.0)
|
77
|
+
rake (>= 0.8.4)
|
78
|
+
thor (~> 0.14.0)
|
79
|
+
rake (0.8.7)
|
80
|
+
rspec (2.0.0.beta.20)
|
81
|
+
rspec-core (= 2.0.0.beta.20)
|
82
|
+
rspec-expectations (= 2.0.0.beta.20)
|
83
|
+
rspec-mocks (= 2.0.0.beta.20)
|
84
|
+
rspec-core (2.0.0.beta.20)
|
85
|
+
rspec-expectations (2.0.0.beta.20)
|
86
|
+
diff-lcs (>= 1.1.2)
|
87
|
+
rspec-mocks (2.0.0.beta.20)
|
88
|
+
rspec-rails (2.0.0.beta.20)
|
89
|
+
rspec (= 2.0.0.beta.20)
|
90
|
+
ruby-debug (0.10.3)
|
91
|
+
columnize (>= 0.1)
|
92
|
+
ruby-debug-base (~> 0.10.3.0)
|
93
|
+
ruby-debug-base (0.10.3)
|
94
|
+
linecache (>= 0.3)
|
95
|
+
rubyzip (0.9.4)
|
96
|
+
selenium-webdriver (0.0.28)
|
97
|
+
ffi (>= 0.6.1)
|
98
|
+
json_pure
|
99
|
+
rubyzip
|
100
|
+
sqlite3-ruby (1.3.1)
|
101
|
+
thor (0.14.0)
|
102
|
+
treetop (1.4.8)
|
103
|
+
polyglot (>= 0.3.1)
|
104
|
+
tzinfo (0.3.23)
|
105
|
+
|
106
|
+
PLATFORMS
|
107
|
+
ruby
|
108
|
+
|
109
|
+
DEPENDENCIES
|
110
|
+
atd-ancestry
|
111
|
+
cancan
|
112
|
+
capybara (>= 0.3.9)
|
113
|
+
factory_girl
|
114
|
+
rails (= 3.0.0)
|
115
|
+
rspec-rails (>= 2.0.0.beta)
|
116
|
+
ruby-debug (>= 0.10.3)
|
117
|
+
sqlite3-ruby
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Universidad Politécnica de Madrid
|
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,63 @@
|
|
1
|
+
= Social Stream
|
2
|
+
Social Stream is a plugin for Ruby on Rails. It provides your application with social networking
|
3
|
+
features and activity streams.
|
4
|
+
|
5
|
+
== Social networking
|
6
|
+
Social networks are a new paradigm on web application design. Social networking platforms stand
|
7
|
+
among the most popular websites, while many content oriented applications are supporting social
|
8
|
+
networking features in order to improve engagement, enhance user awareness and stimulate communities
|
9
|
+
around the website.
|
10
|
+
|
11
|
+
{Social Stream}[http://github.com/ging/social_stream] is based in
|
12
|
+
{Social Network Analysis}[http://en.wikipedia.org/wiki/Social_network] concepts and methods,
|
13
|
+
including social entities (actors), ties and relations.
|
14
|
+
It also provides a new tie-based access control model.
|
15
|
+
|
16
|
+
== Activity Streams
|
17
|
+
{Activity Streams}[http://activitystrea.ms/] is a format for syndicating social activities around the web. It has already been adopted by some of the major social networking platforms.
|
18
|
+
|
19
|
+
{Social Stream}[http://github.com/ging/social_stream] provides a database schema based on the
|
20
|
+
{Activity Streams specification}[http://activitystrea.ms/head/activity-schema.html], leading your
|
21
|
+
application towards a well-known compatible data model design.
|
22
|
+
|
23
|
+
= Installation
|
24
|
+
|
25
|
+
Add to your Gemfile:
|
26
|
+
|
27
|
+
gem 'social_stream'
|
28
|
+
|
29
|
+
and run:
|
30
|
+
|
31
|
+
bundle update
|
32
|
+
|
33
|
+
Then, execute:
|
34
|
+
|
35
|
+
rails generate social_stream:install
|
36
|
+
|
37
|
+
This will generate the following:
|
38
|
+
* A migration providing the database schema
|
39
|
+
* An initializer configuration file for Social Stream.
|
40
|
+
* A database seeds file for defining Social Stream relations. You must add:
|
41
|
+
SocialStream.seed!
|
42
|
+
to your db/seeds.rb
|
43
|
+
* A devise:install generation for authentication support
|
44
|
+
|
45
|
+
== Actors and Activity Objects
|
46
|
+
|
47
|
+
{Social Stream}[http://github.com/ging/social_stream] relies in Devise[http://github.com/plataformatec/devise].
|
48
|
+
|
49
|
+
You must include an <tt>actor_id</tt> column in the user's migration. Then add user to
|
50
|
+
<tt>config/initializers/social_stream.rb</tt>
|
51
|
+
|
52
|
+
You must do the same with Activity Objects, like posts, comments or photos. Don't forget to add
|
53
|
+
a <tt>activity_object_id</tt> column in the migration and add them to the initializer.
|
54
|
+
|
55
|
+
= Documentation
|
56
|
+
|
57
|
+
{Social Stream documentation}[http://rdoc.info/github/ging/social_stream/frames] is available at
|
58
|
+
{rdoc.info}[http://rdoc.info/]
|
59
|
+
|
60
|
+
= Discussion
|
61
|
+
|
62
|
+
It is at an early stage of development.
|
63
|
+
Feel free to add an issue or send a message at github[http://github.com/ging/social_stream].
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
require 'rspec/core'
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
|
9
|
+
require File.join(File.dirname(__FILE__), 'lib', 'social_stream', 'version')
|
10
|
+
|
11
|
+
|
12
|
+
Rspec::Core::RakeTask.new(:spec) do |t|
|
13
|
+
t.rspec_opts = ["--color"]
|
14
|
+
end
|
15
|
+
|
16
|
+
task :default => :spec
|
17
|
+
|
18
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
19
|
+
rdoc.rdoc_dir = 'rdoc'
|
20
|
+
rdoc.title = 'SocialStream'
|
21
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
22
|
+
rdoc.rdoc_files.include('README.rdoc')
|
23
|
+
rdoc.rdoc_files.include('lib/**/*.rb', 'app/**/*.rb')
|
24
|
+
end
|
25
|
+
|
26
|
+
spec = Gem::Specification.new do |s|
|
27
|
+
s.name = "social_stream"
|
28
|
+
s.version = SocialStream::VERSION.dup
|
29
|
+
s.summary = "Social networking features and activity streams."
|
30
|
+
s.description = "Ruby on Rails plug-in supporting social networking features and activity streams."
|
31
|
+
s.authors = ['Antonio Tapiador', 'Diego Carrera']
|
32
|
+
s.files = FileList["[A-Z]*", "{app,config,lib}/**/*"]
|
33
|
+
s.add_dependency('atd-ancestry', '~> 1.3.0')
|
34
|
+
s.add_dependency('devise', '~> 1.1.3')
|
35
|
+
end
|
36
|
+
|
37
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Install the gem #{spec.name}-#{spec.version}.gem"
|
41
|
+
task :install => :gem do
|
42
|
+
system("sudo gem install pkg/#{spec.name}-#{spec.version}.gem --no-ri --no-rdoc")
|
43
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module ActivitiesHelper
|
2
|
+
|
3
|
+
def like_activity(activity)
|
4
|
+
if (activity.liked_by?(current_user))
|
5
|
+
link_to t('activity.unlike'), activity_like_path(activity), :method => :delete, :remote => true
|
6
|
+
else
|
7
|
+
link_to t('activity.like'), activity_like_path(activity), :method => :post, :remote => true
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Activities follow the {Activity Streams}[http://activitystrea.ms/] standard.
|
2
|
+
#
|
3
|
+
# == Activities and Ties
|
4
|
+
# Every activity is attached to a Tie, which defines the sender, the receiver and
|
5
|
+
# the relation in which the activity is transferred
|
6
|
+
#
|
7
|
+
# == Wall
|
8
|
+
# The Activity.wall(ties) scope provides all the activities attached to a set of ties
|
9
|
+
#
|
10
|
+
class Activity < ActiveRecord::Base
|
11
|
+
has_ancestry
|
12
|
+
|
13
|
+
belongs_to :activity_verb
|
14
|
+
|
15
|
+
belongs_to :tie,
|
16
|
+
:include => [ :sender ]
|
17
|
+
|
18
|
+
has_one :sender,
|
19
|
+
:through => :tie
|
20
|
+
has_one :receiver,
|
21
|
+
:through => :tie
|
22
|
+
has_one :relation,
|
23
|
+
:through => :tie
|
24
|
+
|
25
|
+
delegate :sender_subject,
|
26
|
+
:receiver_subject,
|
27
|
+
:to => :tie
|
28
|
+
|
29
|
+
has_many :activity_object_activities,
|
30
|
+
:dependent => :destroy
|
31
|
+
has_many :activity_objects,
|
32
|
+
:through => :activity_object_activities
|
33
|
+
|
34
|
+
scope :wall, lambda { |ties|
|
35
|
+
select("DISTINCT activities.*").
|
36
|
+
roots.
|
37
|
+
where(:tie_id => ties).
|
38
|
+
order("created_at desc")
|
39
|
+
}
|
40
|
+
|
41
|
+
# The name of the verb of this activity
|
42
|
+
def verb
|
43
|
+
activity_verb.name
|
44
|
+
end
|
45
|
+
|
46
|
+
# Set the name of the verb of this activity
|
47
|
+
def verb=(name)
|
48
|
+
self.activity_verb = ActivityVerb[name]
|
49
|
+
end
|
50
|
+
|
51
|
+
# The comments about this activity
|
52
|
+
def comments
|
53
|
+
children.includes(:activity_objects).where('activity_objects.object_type' => "Comment")
|
54
|
+
end
|
55
|
+
|
56
|
+
# The 'like' qualifications emmited to this activities
|
57
|
+
def likes
|
58
|
+
children.joins(:activity_verb).where('activity_verbs.name' => "like")
|
59
|
+
end
|
60
|
+
|
61
|
+
def liked_by(user) #:nodoc:
|
62
|
+
likes.includes(:tie) & Tie.sent_by(user)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Does user like this activity?
|
66
|
+
def liked_by?(user)
|
67
|
+
liked_by(user).present?
|
68
|
+
end
|
69
|
+
|
70
|
+
# The first object of this activity
|
71
|
+
def direct_object
|
72
|
+
activity_objects.first.try(:object)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class ActivityObject < ActiveRecord::Base
|
2
|
+
include SocialStream::Models::Supertype
|
3
|
+
|
4
|
+
has_many :activity_object_activities, :dependent => :destroy
|
5
|
+
has_many :activities, :through => :activity_object_activities
|
6
|
+
has_one :actor
|
7
|
+
|
8
|
+
# The object of this activity object
|
9
|
+
def object
|
10
|
+
subtype_instance ||
|
11
|
+
actor.try(:subject)
|
12
|
+
end
|
13
|
+
|
14
|
+
# The activity in which this activity_object was created
|
15
|
+
def post_activity
|
16
|
+
activities.includes(:activity_verb).where('activity_verbs.name' => 'post').first
|
17
|
+
end
|
18
|
+
end
|
data/app/models/actor.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# An actor is a social entity. This includes individuals, but also groups, departments, organizations even nations or states. Actors are linked by ties.
|
2
|
+
class Actor < ActiveRecord::Base
|
3
|
+
include SocialStream::Models::Supertype
|
4
|
+
|
5
|
+
has_many :sent_ties,
|
6
|
+
:class_name => "Tie",
|
7
|
+
:foreign_key => 'sender_id',
|
8
|
+
:dependent => :destroy
|
9
|
+
|
10
|
+
has_many :received_ties,
|
11
|
+
:class_name => "Tie",
|
12
|
+
:foreign_key => 'receiver_id',
|
13
|
+
:dependent => :destroy
|
14
|
+
|
15
|
+
# The subject instance for this actor
|
16
|
+
def subject
|
17
|
+
subtype_instance ||
|
18
|
+
activity_object.try(:object)
|
19
|
+
end
|
20
|
+
|
21
|
+
# All the ties sent or received by this actor
|
22
|
+
def ties
|
23
|
+
Tie.sent_or_received_by(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
# The set of activities in the wall of this actor
|
27
|
+
# TODO: authorization
|
28
|
+
def wall
|
29
|
+
Activity.wall ties
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# A Relation defines a type of Tie. Relations are affective (friendship, liking,
|
2
|
+
# respect), formal or biological (authority, kinship), transfer of material
|
3
|
+
# resources (transactions, lending and borrowing), messages or conversations,
|
4
|
+
# physical connection and affiliation to same organizations.
|
5
|
+
#
|
6
|
+
# == Strength hierarchies
|
7
|
+
# Relations are arranged in strength hierarchies, denoting that some ties between
|
8
|
+
# two actors are stronger than others.
|
9
|
+
# When a strong tie is established, ties with weaker relations are establised as well
|
10
|
+
#
|
11
|
+
# == Inverse relations
|
12
|
+
# A Relation can have its inverse. When a tie is established, an inverse tie will be
|
13
|
+
# established if an inverse relation exists. An example is a relation of friendship,
|
14
|
+
# whose inverse relation is itself. When A is friend of B, the inverse tie B is friend of A
|
15
|
+
# is establised as well.
|
16
|
+
#
|
17
|
+
# == Granted relations
|
18
|
+
# There are cases when relations need previous invitation or request to be granted.
|
19
|
+
# This is the case of friendship requests. When A wants to become friend of B, A
|
20
|
+
# sends a friendship_request to B. A is granting the friend relation with B, that is,
|
21
|
+
# friendship_request grants friend relation.
|
22
|
+
#
|
23
|
+
class Relation < ActiveRecord::Base
|
24
|
+
has_ancestry
|
25
|
+
|
26
|
+
scope :mode, lambda { |st, rt|
|
27
|
+
where(:sender_type => st, :receiver_type => rt)
|
28
|
+
}
|
29
|
+
|
30
|
+
belongs_to :inverse,
|
31
|
+
:class_name => "Relation"
|
32
|
+
belongs_to :granted,
|
33
|
+
:class_name => "Relation"
|
34
|
+
|
35
|
+
scope :request, where('relations.granted_id IS NOT NULL')
|
36
|
+
|
37
|
+
has_many :relation_permissions, :dependent => :destroy
|
38
|
+
has_many :permissions, :through => :relation_permissions
|
39
|
+
|
40
|
+
has_many :ties, :dependent => :destroy
|
41
|
+
|
42
|
+
class << self
|
43
|
+
# A relation in the top of a strength hierarchy
|
44
|
+
def strongest
|
45
|
+
roots.first
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Other relations below in the same hierarchy that this relation
|
50
|
+
def weaker
|
51
|
+
descendants
|
52
|
+
end
|
53
|
+
|
54
|
+
# Relations below or at the same level of this relation
|
55
|
+
def weaker_or_equal
|
56
|
+
Array(self) + descendants
|
57
|
+
end
|
58
|
+
|
59
|
+
# Other relations above in the same hierarchy that this relation
|
60
|
+
def stronger
|
61
|
+
ancestors
|
62
|
+
end
|
63
|
+
|
64
|
+
# Relations above or at the same level of this relation
|
65
|
+
def stronger_or_equal
|
66
|
+
ancestors + Array(self)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Relation class scoped in the same mode that this relation
|
70
|
+
def mode
|
71
|
+
Relation.mode(sender_type, receiver_type)
|
72
|
+
end
|
73
|
+
end
|