social_stream-base 0.13.2 → 0.14.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/app/assets/javascripts/activities.js.erb +5 -5
- data/app/assets/javascripts/social_stream-base.js +2 -0
- data/app/assets/stylesheets/cheesecake.css.scss +13 -0
- data/app/controllers/omniauth_callbacks_controller.rb +3 -3
- data/app/helpers/notifications_helper.rb +2 -2
- data/app/models/user.rb +15 -14
- data/app/views/cheesecake/_cheesecake.html.erb +69 -1
- data/app/views/frontpage/_social_networks.html.erb +1 -1
- data/app/views/layouts/application.html.erb +6 -1
- data/lib/acts_as_taggable_on/social_stream.rb +59 -31
- data/lib/i18n-js/social_stream-base.rb +36 -0
- data/lib/social_stream/base/dependencies.rb +6 -2
- data/lib/social_stream/base/version.rb +1 -1
- data/lib/social_stream/controllers/cancan_devise_integration.rb +15 -18
- data/lib/social_stream/controllers/helpers.rb +81 -83
- data/lib/social_stream/controllers/i18n_integration.rb +11 -13
- data/lib/social_stream/controllers/objects.rb +4 -7
- data/lib/social_stream/controllers/subjects.rb +3 -5
- data/lib/social_stream/models/channeled.rb +24 -26
- data/lib/social_stream/models/object.rb +57 -61
- data/lib/social_stream/models/subject.rb +4 -8
- data/lib/social_stream/models/subtype.rb +36 -34
- data/lib/social_stream/models/supertype.rb +17 -21
- data/lib/tasks/db/populate.rake +11 -3
- data/social_stream-base.gemspec +9 -5
- data/spec/dummy/config/initializers/devise.rb +1 -1
- metadata +99 -65
@@ -57,7 +57,7 @@ activate_anti_rebounds = function(){
|
|
57
57
|
$(this).find('input[type=text]').each(function() {
|
58
58
|
$(this).blur().attr('readonly', true);
|
59
59
|
});
|
60
|
-
$("#masterSubmitButton").val(
|
60
|
+
$("#masterSubmitButton").val(I18n.t('activity.sending') + '...').attr("disabled", true);
|
61
61
|
|
62
62
|
// Add _relation_ids[] parameter from authorization selector
|
63
63
|
$('.liveAdded').remove();
|
@@ -81,7 +81,7 @@ activate_anti_rebounds = function(){
|
|
81
81
|
$(this).blur().attr('readonly', true);
|
82
82
|
});
|
83
83
|
$(this).find(".submitActivity").each(function() {
|
84
|
-
$(this).val(
|
84
|
+
$(this).val(I18n.t('activity.sending') + '...').attr("disabled", true);
|
85
85
|
});
|
86
86
|
return true;
|
87
87
|
});
|
@@ -90,9 +90,9 @@ activate_anti_rebounds = function(){
|
|
90
90
|
|
91
91
|
unblock_all_forms = function() {
|
92
92
|
//Sharing buttons
|
93
|
-
$(".submitActivity").val(
|
93
|
+
$(".submitActivity").val(I18n.t('share')).removeAttr("disabled");
|
94
94
|
//Header activities form
|
95
|
-
$("#masterSubmitButton").val(
|
95
|
+
$("#masterSubmitButton").val(I18n.t('share')).removeAttr("disabled");
|
96
96
|
$('#wrapper_activities_header form').find('input[type=text]').each(function() {
|
97
97
|
$(this).removeAttr("readonly").val("").blur();
|
98
98
|
});
|
@@ -141,7 +141,7 @@ $(function() {
|
|
141
141
|
//check if there are more than 3 comments
|
142
142
|
if (comments.size() > 3){
|
143
143
|
$(this).prepend("<div class='hide_show_comments'><a href='#' onclick='showAllComments(\""+
|
144
|
-
$(this).attr('id') +"\"); return false;'
|
144
|
+
$(this).attr('id') +"\"); return false;'>" + I18n.t('comment.view_all') + "(" +
|
145
145
|
comments.size() + ")</a></div><div class='space_comments'></div>");
|
146
146
|
comments.slice(0,comments.size()-2).hide();
|
147
147
|
//hide alto space_comments
|
@@ -84,10 +84,23 @@
|
|
84
84
|
padding: 5px;
|
85
85
|
display: none;
|
86
86
|
max-height: 200px;
|
87
|
+
overflow-y: auto;
|
87
88
|
}
|
88
89
|
#contacts_changes_details ul{
|
89
90
|
padding-left: 20px;
|
90
91
|
}
|
92
|
+
#contacts_changes_details .change_deleted{
|
93
|
+
font-weight: bold;
|
94
|
+
color: $error-color;
|
95
|
+
}
|
96
|
+
#contacts_changes_details .change_modified{
|
97
|
+
font-weight: bold;
|
98
|
+
color: $alert-color;
|
99
|
+
}
|
100
|
+
#contacts_changes_details .change_added{
|
101
|
+
font-weight: bold;
|
102
|
+
color: $success-color;
|
103
|
+
}
|
91
104
|
#contacts_grid .actor {
|
92
105
|
width: 48px;
|
93
106
|
height: 48px;
|
@@ -1,15 +1,15 @@
|
|
1
1
|
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
2
2
|
def facebook
|
3
|
-
#print env['omniauth.auth']
|
4
3
|
@user = User.find_or_create_for_facebook_oauth(env['omniauth.auth'],current_user)
|
4
|
+
|
5
5
|
if @user.persisted?
|
6
6
|
sign_in_and_redirect @user, :event => :authentication
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
#print env['omniauth.auth']
|
10
|
+
def linkedin
|
12
11
|
@user = User.find_or_create_for_linkedin_oauth(env['omniauth.auth'],current_user)
|
12
|
+
|
13
13
|
if @user.persisted?
|
14
14
|
sign_in_and_redirect @user, :event => :authentication
|
15
15
|
end
|
@@ -10,7 +10,7 @@ module NotificationsHelper
|
|
10
10
|
act_obj.title.truncate(30, :separator => ' ')
|
11
11
|
elsif act_obj.respond_to? :url and (not act_obj.url.nil?)
|
12
12
|
act_obj.url.truncate(30, :separator => ' ')
|
13
|
-
else t('notification.default')
|
13
|
+
else I18n.t('notification.default')
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -21,7 +21,7 @@ module NotificationsHelper
|
|
21
21
|
elsif act_obj.respond_to? :description and (not act_obj.description.nil?)
|
22
22
|
sanitize(act_obj.description.truncate(100, :separator =>' '))
|
23
23
|
else
|
24
|
-
t('notification.watch_it')
|
24
|
+
I18n.t('notification.watch_it')
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
data/app/models/user.rb
CHANGED
@@ -115,26 +115,27 @@ class User < ActiveRecord::Base
|
|
115
115
|
record
|
116
116
|
end
|
117
117
|
|
118
|
-
def find_or_create_for_facebook_oauth(
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
user = User.create!(:name => data["name"], :email => data["email"], :password => Devise.friendly_token[0,20])
|
118
|
+
def find_or_create_for_facebook_oauth(hash, signed_in_resource = nil)
|
119
|
+
puts hash.inspect
|
120
|
+
auth = Authentication.find_by_provider_and_uid(hash["provider"], hash["uid"])
|
121
|
+
user = User.find_by_email(hash["info"]["email"])
|
122
|
+
|
123
|
+
if user.nil?
|
124
|
+
user = User.create!(:name => hash["info"]["name"], :email => hash["info"]["email"], :password => Devise.friendly_token[0,20])
|
126
125
|
end
|
127
|
-
|
128
|
-
|
126
|
+
|
127
|
+
if auth.nil?
|
128
|
+
auth = Authentication.create!(:user_id => user.id, :uid =>hash["uid"], :provider => hash["provider"])
|
129
129
|
end
|
130
|
+
|
130
131
|
user
|
131
132
|
end
|
132
133
|
|
133
|
-
def find_or_create_for_linkedin_oauth(
|
134
|
-
auth = Authentication.find_by_uid_and_provider(
|
134
|
+
def find_or_create_for_linkedin_oauth(hash,signed_in_resource=nil)
|
135
|
+
auth = Authentication.find_by_uid_and_provider(hash["uid"],hash["provider"])
|
135
136
|
if auth==nil
|
136
|
-
user = User.create!(:name =>
|
137
|
-
auth = Authentication.create!(:user_id => user.id, :uid =>
|
137
|
+
user = User.create!(:name => hash["info"]["name"], :email => 'demo@socialstream.com', :password => Devise.friendly_token[0,20])
|
138
|
+
auth = Authentication.create!(:user_id => user.id, :uid =>hash["uid"], :provider => hash["provider"])
|
138
139
|
user
|
139
140
|
else
|
140
141
|
user = User.find_by_id(auth.user_id)
|
@@ -48,7 +48,75 @@ $(function(){
|
|
48
48
|
cheesecakeData.highlightedSectorCallback(cheese);
|
49
49
|
});
|
50
50
|
cheese.onChange = function(cheesecake){
|
51
|
-
|
51
|
+
var initial = cheesecake.getInitialState();
|
52
|
+
var changes = cheesecake.getChanges();
|
53
|
+
var changes_html = "";
|
54
|
+
var actors = changes.actors;
|
55
|
+
$("#contacts_save_changes").val(JSON.stringify(changes));
|
56
|
+
for(var i in actors){
|
57
|
+
actor = actors[i];
|
58
|
+
if(actor.justAdded){
|
59
|
+
var new_subsectors = actor.subsectors;
|
60
|
+
var new_subsectors_string = "";
|
61
|
+
for(var i in new_subsectors){
|
62
|
+
if(i > 0) new_subsectors_string += ", ";
|
63
|
+
new_subsectors_string += cheesecake.getSubsectorById(new_subsectors[i]).label;
|
64
|
+
}
|
65
|
+
changes_html += "<div class=\"change_added\">" + actor.name + " has been removed from " + old_subsectors_string + "</div>";
|
66
|
+
}else if(actor.subsectors.length==0){
|
67
|
+
var old_subsectors = [];
|
68
|
+
var old_subsectors_string = "";
|
69
|
+
for(var i in initial.actors){
|
70
|
+
if(actor.id==initial.actors[i].id){
|
71
|
+
old_subsectors = initial.actors[i].subsectors;
|
72
|
+
break;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
for(var i in old_subsectors){
|
76
|
+
if(i > 0) old_subsectors_string += ", ";
|
77
|
+
old_subsectors_string += cheesecake.getSubsectorById(old_subsectors[i]).label;
|
78
|
+
}
|
79
|
+
changes_html += "<div class=\"change_deleted\">" + actor.name + " has been removed from " + old_subsectors_string + "</div>";
|
80
|
+
}else{
|
81
|
+
var old_subsectors = [];
|
82
|
+
var new_subsectors = actor.subsectors;
|
83
|
+
var left_subsectors = "";
|
84
|
+
var joined_subsectors = "";
|
85
|
+
for(var i in initial.actors){
|
86
|
+
if(actor.id==initial.actors[i].id){
|
87
|
+
old_subsectors = initial.actors[i].subsectors;
|
88
|
+
break;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
for(var i in old_subsectors){
|
92
|
+
if(new_subsectors.indexOf(old_subsectors[i])==-1){
|
93
|
+
if(left_subsectors.length!=0){
|
94
|
+
left_subsectors += ", ";
|
95
|
+
}
|
96
|
+
left_subsectors += cheesecake.getSubsectorById(old_subsectors[i]).label;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
for(var i in new_subsectors){
|
100
|
+
if(old_subsectors.indexOf(new_subsectors[i])==-1){
|
101
|
+
if(joined_subsectors.length!=0){
|
102
|
+
joined_subsectors += ", ";
|
103
|
+
}
|
104
|
+
joined_subsectors += cheesecake.getSubsectorById(new_subsectors[i]).label;
|
105
|
+
}
|
106
|
+
}
|
107
|
+
if((joined_subsectors.length!=0)&&(left_subsectors.length!=0)){
|
108
|
+
changes_html += "<div class=\"change_modified\">" + actor.name + " has been removed from " + left_subsectors + " and added to " + joined_subsectors + "</div>";
|
109
|
+
}else if(joined_subsectors.length!=0){
|
110
|
+
changes_html += "<div class=\"change_added\">" + actor.name + " has been added to " + joined_subsectors + "</div>";
|
111
|
+
}else{
|
112
|
+
changes_html += "<div class=\"change_deleted\">" + actor.name + " has been removed from " + left_subsectors + "</div>";
|
113
|
+
}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
$("#contacts_changes_details").html(changes_html);
|
117
|
+
if (!$("#contacts_changes_details").is (":visible")){
|
118
|
+
$("#contacts_changes_details").slideToggle("slow");
|
119
|
+
}
|
52
120
|
}
|
53
121
|
if(cheese.grid.actors.length > 30){
|
54
122
|
var extra_text = ["<%= t('cheesecake.hidden_contact.one')%>","<%= t('cheesecake.hidden_contact.other')%>"];
|
@@ -1,3 +1,3 @@
|
|
1
1
|
<span>|</span>
|
2
2
|
<%= link_to image_tag('btn/facebook.png'), user_omniauth_authorize_path(:facebook), :class => "menu_icon" %>
|
3
|
-
<%= link_to image_tag('btn/linkedin.png'), user_omniauth_authorize_path(:
|
3
|
+
<%= link_to image_tag('btn/linkedin.png'), user_omniauth_authorize_path(:linkedin), :class => "menu_icon" %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<!-- HTML5 DOCTYPE -->
|
2
2
|
<!DOCTYPE html>
|
3
|
-
<html lang="
|
3
|
+
<html lang="<%= I18n.locale.to_s %>">
|
4
4
|
<head>
|
5
5
|
<meta charset="utf-8">
|
6
6
|
<title><%= yield(:title).empty? ? t('site.name') : yield(:title)%></title>
|
@@ -20,6 +20,11 @@
|
|
20
20
|
<%= csrf_meta_tag %>
|
21
21
|
<% end %>
|
22
22
|
|
23
|
+
<script type="text/javascript">
|
24
|
+
I18n.defaultLocale = "<%= I18n.default_locale %>";
|
25
|
+
I18n.locale = "<%= I18n.locale %>";
|
26
|
+
</script>
|
27
|
+
|
23
28
|
<script type="text/javascript">
|
24
29
|
$(document).ready(function() {
|
25
30
|
<%= yield :javascript %>
|
@@ -1,14 +1,69 @@
|
|
1
1
|
require "acts_as_taggable_on/acts_as_taggable_on/dirty"
|
2
2
|
|
3
|
+
module ActsAsTaggableOn::Taggable::Core::ClassMethods
|
4
|
+
def initialize_acts_as_taggable_on_core
|
5
|
+
tag_types.map(&:to_s).each do |tags_type|
|
6
|
+
tag_type = tags_type.to_s.singularize
|
7
|
+
context_taggings = "#{tag_type}_taggings".to_sym
|
8
|
+
context_tags = tags_type.to_sym
|
9
|
+
|
10
|
+
class_eval do
|
11
|
+
has_many context_taggings, :as => :taggable, :dependent => :destroy, :include => :tag, :class_name => "ActsAsTaggableOn::Tagging",
|
12
|
+
:conditions => ["#{ActsAsTaggableOn::Tagging.table_name}.context = ?", tags_type]
|
13
|
+
has_many context_tags, :through => context_taggings, :source => :tag, :class_name => "ActsAsTaggableOn::Tag"
|
14
|
+
end
|
15
|
+
|
16
|
+
class_eval %(
|
17
|
+
def #{tag_type}_list
|
18
|
+
tag_list_on('#{tags_type}')
|
19
|
+
end
|
20
|
+
|
21
|
+
def #{tag_type}_list=(new_tags)
|
22
|
+
set_tag_list_on('#{tags_type}', new_tags)
|
23
|
+
end
|
24
|
+
|
25
|
+
def all_#{tags_type}_list
|
26
|
+
all_tags_list_on('#{tags_type}')
|
27
|
+
end
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module ActsAsTaggableOn::Taggable::Core::InstanceMethods
|
34
|
+
def set_tag_list_on(context, new_list)
|
35
|
+
add_custom_context(context)
|
36
|
+
|
37
|
+
variable_name = "@#{context.to_s.singularize}_list"
|
38
|
+
process_dirty_object(context, new_list) unless custom_contexts.include?(context.to_s)
|
39
|
+
|
40
|
+
instance_variable_set(variable_name, ActsAsTaggableOn::TagList.from(new_list))
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_dirty_object(context,new_list)
|
44
|
+
value = new_list.is_a?(Array) ? new_list.join(', ') : new_list
|
45
|
+
attrib = "#{context.to_s.singularize}_list"
|
46
|
+
|
47
|
+
if changed_attributes.include?(attrib)
|
48
|
+
# The attribute already has an unsaved change.
|
49
|
+
old = changed_attributes[attrib]
|
50
|
+
changed_attributes.delete(attrib) if (old.to_s == value.to_s)
|
51
|
+
else
|
52
|
+
old = tag_list_on(context).to_s
|
53
|
+
changed_attributes[attrib] = old if (old.to_s != value.to_s)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
3
58
|
module ActsAsTaggableOn::Taggable
|
4
59
|
def acts_as_taggable_on(*tag_types)
|
5
60
|
tag_types = tag_types.to_a.flatten.compact.map(&:to_sym)
|
6
61
|
|
7
62
|
if taggable?
|
8
|
-
|
63
|
+
self.tag_types = (self.tag_types + tag_types).uniq
|
9
64
|
else
|
10
|
-
|
11
|
-
|
65
|
+
class_attribute :tag_types
|
66
|
+
self.tag_types = tag_types
|
12
67
|
|
13
68
|
class_eval do
|
14
69
|
has_many :taggings, :as => :taggable, :dependent => :destroy, :include => :tag, :class_name => "ActsAsTaggableOn::Tagging"
|
@@ -18,6 +73,7 @@ module ActsAsTaggableOn::Taggable
|
|
18
73
|
true
|
19
74
|
end
|
20
75
|
|
76
|
+
include ActsAsTaggableOn::Utils
|
21
77
|
include ActsAsTaggableOn::Taggable::Core
|
22
78
|
include ActsAsTaggableOn::Taggable::Collection
|
23
79
|
include ActsAsTaggableOn::Taggable::Cache
|
@@ -28,31 +84,3 @@ module ActsAsTaggableOn::Taggable
|
|
28
84
|
end
|
29
85
|
end
|
30
86
|
end
|
31
|
-
|
32
|
-
|
33
|
-
module ActsAsTaggableOn::Taggable::Core::InstanceMethods
|
34
|
-
def set_tag_list_on(context, new_list)
|
35
|
-
add_custom_context(context)
|
36
|
-
|
37
|
-
variable_name = "@#{context.to_s.singularize}_list"
|
38
|
-
process_dirty_object(context, new_list)
|
39
|
-
|
40
|
-
instance_variable_set(variable_name, ActsAsTaggableOn::TagList.from(new_list))
|
41
|
-
end
|
42
|
-
|
43
|
-
def process_dirty_object(context,new_list)
|
44
|
-
value = new_list.is_a?(Array) ? new_list.join(', ') : new_list
|
45
|
-
attr = "#{context.to_s.singularize}_list"
|
46
|
-
|
47
|
-
if changed_attributes.include?(attr)
|
48
|
-
# The attribute already has an unsaved change.
|
49
|
-
old = changed_attributes[attr]
|
50
|
-
changed_attributes.delete(attr) if (old.to_s == value.to_s)
|
51
|
-
else
|
52
|
-
old = tag_list_on(context).to_s
|
53
|
-
changed_attributes[attr] = old if (old.to_s != value.to_s)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Monkey patch https://github.com/fnando/i18n-js/commit/888e9c59dfb5164a85f136705186b02d9ef33d5a
|
2
|
+
#
|
3
|
+
# Remove with i18n-js > 2.1.2
|
4
|
+
require 'i18n-js'
|
5
|
+
|
6
|
+
module SimplesIdeias
|
7
|
+
module I18n
|
8
|
+
class Engine
|
9
|
+
initializers.pop
|
10
|
+
|
11
|
+
initializer "i18n-js.asset_dependencies", :after => "sprockets.environment" do
|
12
|
+
next unless I18n.has_asset_pipeline?
|
13
|
+
|
14
|
+
config = I18n.config_file
|
15
|
+
cache_file = I18n::Engine.load_path_hash_cache
|
16
|
+
|
17
|
+
Rails.application.assets.register_preprocessor "application/javascript", :"i18n-js_dependencies" do |context, data|
|
18
|
+
if context.logical_path == I18N_TRANSLATIONS_ASSET
|
19
|
+
context.depend_on(config) if I18n.config?
|
20
|
+
# also set up dependencies on every locale file
|
21
|
+
::I18n.load_path.each {|path| context.depend_on(path)}
|
22
|
+
|
23
|
+
# Set up a dependency on the contents of the load path
|
24
|
+
# itself. In some situations it is possible to get here
|
25
|
+
# before the path hash cache file has been written; in
|
26
|
+
# this situation, write it now.
|
27
|
+
I18n::Engine.write_hash! unless File.exists?(cache_file)
|
28
|
+
context.depend_on(cache_file)
|
29
|
+
end
|
30
|
+
|
31
|
+
data
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -23,7 +23,9 @@ require 'avatars_for_rails'
|
|
23
23
|
# Pagination
|
24
24
|
require 'kaminari'
|
25
25
|
# Oauth
|
26
|
-
require 'omniauth
|
26
|
+
require 'omniauth'
|
27
|
+
require 'omniauth-facebook'
|
28
|
+
require 'omniauth-linkedin'
|
27
29
|
#Tags
|
28
30
|
require 'acts-as-taggable-on'
|
29
31
|
require 'acts_as_taggable_on/social_stream'
|
@@ -43,5 +45,7 @@ require 'sass-rails'
|
|
43
45
|
require 'rails_autolink'
|
44
46
|
# SocialCheesecake
|
45
47
|
require 'social_cheesecake'
|
46
|
-
|
48
|
+
# I18n-js
|
49
|
+
require 'i18n-js'
|
50
|
+
require 'i18n-js/social_stream-base'
|
47
51
|
|
@@ -4,27 +4,24 @@ module SocialStream
|
|
4
4
|
module CancanDeviseIntegration
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
|
7
|
+
private
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
if params[:s].present? && controller_name != 'home'
|
21
|
-
redirect_to :home
|
22
|
-
else
|
23
|
-
raise exception
|
24
|
-
end
|
9
|
+
# Catch some authorization errors:
|
10
|
+
#
|
11
|
+
# * Redirect to home when the user changes the session and the resource
|
12
|
+
# is not accesible with the new representation
|
13
|
+
#
|
14
|
+
# * Redirect to login if the user is trying to access a protected resource
|
15
|
+
# and she is not authenticated
|
16
|
+
def rescue_from_access_denied(exception)
|
17
|
+
if user_signed_in?
|
18
|
+
if params[:s].present? && controller_name != 'home'
|
19
|
+
redirect_to :home
|
25
20
|
else
|
26
|
-
|
21
|
+
raise exception
|
27
22
|
end
|
23
|
+
else
|
24
|
+
redirect_to new_user_session_path
|
28
25
|
end
|
29
26
|
end
|
30
27
|
end
|