Skip to content

Commit 0405973

Browse files
committed
updated preferences to use JSON hash and be contained in a new model, addresses #481
1 parent 131cef1 commit 0405973

File tree

8 files changed

+346
-409
lines changed

8 files changed

+346
-409
lines changed

app/controllers/registrations_controller.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
class RegistrationsController < Devise::RegistrationsController
33

44
def edit
5-
@user.create_default_preferences if @user.prefs == {}
5+
@user = current_user
6+
@prefs = @user.get_preferences(:email)
67
@languages = Language.sorted_by_abbreviation
78
@orgs = Org.where(parent_id: nil).order("name")
89
@other_organisations = Org.where(parent_id: nil, is_other: true).pluck(:id)

app/controllers/users_controller.rb

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,36 @@ def admin_update_permissions
5858
end
5959
end
6060

61-
def update_preferences
62-
@user = User.find(params[:user_id])
61+
def update_email_preferences
6362
prefs = params[:prefs]
64-
authorize @user, :update?
65-
# Set all preferences to false
66-
@user.prefs.each do |key, value|
67-
value.each_key do |k|
68-
@user.prefs[key][k] = false
69-
end
63+
authorize current_user, :update?
64+
pref = current_user.pref
65+
# does user not have prefs?
66+
if pref.blank?
67+
pref = Pref.new
68+
pref.settings = {}
69+
pref.user = current_user
7070
end
71+
pref.settings[:email] = booleanize_hash(prefs)
72+
pref.save
7173

72-
# Sets the preferences the user wants to true
73-
if prefs
74-
prefs.each_key do |key|
75-
prefs[key].each_key do |k|
76-
@user.prefs[key.to_sym][k.to_sym] = true
77-
end
78-
end
79-
end
8074
@tab = params[:tab]
81-
@user.save
8275
redirect_to edit_user_registration_path(tab: @tab), notice: success_message(_('preferences'), _('saved'))
8376
end
8477

78+
private
79+
80+
##
81+
# html forms return our boolean values as strings, this converts them to true/false
82+
def booleanize_hash(node)
83+
#leaf: convert to boolean and return
84+
#hash: iterate over leaves
85+
unless node.is_a?(Hash)
86+
return node == "true"
87+
end
88+
node.each do |key, value|
89+
node[key] = booleanize_hash(value)
90+
end
91+
end
92+
8593
end

app/models/pref.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class Pref < ActiveRecord::Base
2+
##
3+
# Serialize prefs to JSON
4+
# The settings object only stores deviations from the default
5+
serialize :settings, JSON
6+
7+
##
8+
# Associations
9+
belongs_to :user
10+
11+
##
12+
# Returns the hash generated from default preferences
13+
#
14+
# @return [JSON] preferences hash
15+
def self.default_settings
16+
return Rails.configuration.branding[:preferences]
17+
end
18+
19+
end

app/models/user.rb

Lines changed: 13 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
class User < ActiveRecord::Base
2-
include GlobalHelpers
32

43
##
54
# Devise
@@ -20,6 +19,7 @@ class User < ActiveRecord::Base
2019
has_and_belongs_to_many :perms, join_table: :users_perms
2120
belongs_to :language
2221
belongs_to :org
22+
has_one :pref
2323
has_many :answers
2424
has_many :notes
2525
has_many :exported_plans
@@ -42,24 +42,8 @@ def filter(query)
4242
has_many :user_identifiers
4343
has_many :identifier_schemes, through: :user_identifiers
4444

45-
##
46-
# Possibly needed for active_admin
47-
# -relies on protected_attributes gem as syntax depricated in rails 4.2
48-
#accepts_nested_attributes_for :roles
49-
#attr_accessible :password_confirmation, :encrypted_password, :remember_me,
50-
# :id, :email, :firstname, :last_login,:login_count, :orcid_id,
51-
# :password, :shibboleth_id, :user_status_id, :surname,
52-
# :user_type_id, :org_id, :skip_invitation, :other_organisation,
53-
# :accept_terms, :role_ids, :dmponline3, :api_token,
54-
# :organisation, :language, :language_id, :org, :perms,
55-
# :confirmed_at, :org_id
56-
5745
validates :email, email: true, allow_nil: true, uniqueness: {message: _("must be unique")}
5846

59-
60-
validates :prefs, presence: true
61-
before_validation :create_default_preferences
62-
6347
##
6448
# Scopes
6549
default_scope { includes(:org, :perms, :plans) }
@@ -222,17 +206,6 @@ def can_grant_api_to_orgs?
222206
perms.include? Perm.grant_api
223207
end
224208

225-
##
226-
# checks what type the user's organisation is
227-
#
228-
# @return [String] the organisation type
229-
=begin
230-
def org_type
231-
org_type = org.organisation_type
232-
return org_type
233-
end
234-
=end
235-
236209
##
237210
# removes the api_token from the user
238211
# modifies the user model
@@ -272,54 +245,23 @@ def self.from_omniauth(auth)
272245
end
273246
end
274247

248+
##
249+
# Return the user's preferences for a given base key
250+
#
251+
# @return [JSON] with symbols as keys
252+
def get_preferences(key)
253+
if self.pref.present? && self.pref.settings[key.to_s].present?
254+
return self.pref.settings[key.to_s].deep_symbolize_keys
255+
else
256+
return Pref.default_settings[key]
257+
end
258+
end
259+
275260
##
276261
# Override devise_invitable email title
277262
# --------------------------------------------------------------
278263
def deliver_invitation(options = {})
279264
super(options.merge(subject: _('A Data Management Plan in %{application_name} has been shared with you') % {application_name: Rails.configuration.branding[:application][:name]}))
280265
end
281266

282-
283-
##
284-
# User Notification Preferences
285-
def create_default_preferences
286-
# Set the default preferences for a new user or if existing user if null
287-
if self.id.nil? || self.prefs == {}
288-
self.prefs = self.class.create_default_preferences
289-
end
290-
end
291-
292-
def self.create_default_preferences
293-
default_prefs = {
294-
users: {
295-
new_comment: true,
296-
admin_privileges: true,
297-
added_as_coowner: true
298-
},
299-
owners_and_coowners: {
300-
visibility_changed: true
301-
},
302-
admins: {
303-
template_published: true,
304-
template_unpublished: true,
305-
feedback_requested: true
306-
}
307-
}
308-
end
309-
310-
# TODO: Remove this, its never called.
311-
# this generates a reset password link for a given user
312-
# which can then be sent to them with the appropriate host
313-
# prepended.
314-
=begin
315-
def reset_password_link
316-
raw, enc = Devise.token_generator.generate(self.class, :reset_password_token)
317-
self.reset_password_token = enc
318-
self.reset_password_sent_at = Time.now.utc
319-
save(validate: false)
320-
321-
edit_user_password_path + '?reset_password_token=' + raw
322-
end
323-
=end
324-
325267
end

config/branding_example.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ defaults: &defaults
1717
issue_list_url: 'https://github.com/DMPRoadmap/roadmap/issues'
1818
user_group_subscription_url: 'http://listserv.ucop.edu/cgi-bin/wa.exe?SUBED1=ROADMAP-L&A=1'
1919

20+
preferences:
21+
email:
22+
users:
23+
new_comment: true
24+
admin_privileges: true
25+
added_as_coowner: true
26+
owners_and_coowners:
27+
visibility_changed: true
28+
admins:
29+
template_published: true
30+
template_unpublished: true
31+
feedback_requested: true
32+
2033
development:
2134
<<: *defaults
2235

config/routes.rb

Lines changed: 5 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
get "/users/sign_out", :to => "devise/sessions#destroy"
4040
end
4141

42-
match '/users/update_preferences/' => 'users#update_preferences', as: 'user_update_preferences', via: [:put, :post]
4342

4443
# WAYFless access point - use query param idp
4544
#get 'auth/shibboleth' => 'users/omniauth_shibboleth_request#redirect', :as => 'user_omniauth_shibboleth'
@@ -57,7 +56,11 @@
5756
get '/orgs/shibboleth/:org_name', to: 'orgs#shibboleth_ds_passthru'
5857
post '/orgs/shibboleth', to: 'orgs#shibboleth_ds_passthru'
5958

60-
#ActiveAdmin.routes(self)
59+
resources :users, path: 'users', only: [] do
60+
member do
61+
put 'update_email_preferences'
62+
end
63+
end
6164

6265
#organisation admin area
6366
resources :users, :path => 'org/admin/users', only: [] do
@@ -220,34 +223,6 @@
220223
end
221224
end
222225

223-
# resources :projects do
224-
# resources :plans , only: [:edit, :update] do
225-
# member do
226-
# get 'status'
227-
# get 'locked'
228-
# get 'answer'
229-
# #get 'edit'
230-
# post 'delete_recent_locks'
231-
# post 'lock_section', constraints: {format: [:html, :json]}
232-
# post 'unlock_section', constraints: {format: [:html, :json]}
233-
# post 'unlock_all_sections'
234-
# get 'export'
235-
# get 'warning'
236-
# get 'section_answers'
237-
# end
238-
# end
239-
#
240-
# member do
241-
# get 'share'
242-
# get 'export'
243-
# post 'invite'
244-
# end
245-
# collection do
246-
# get 'possible_templates'
247-
# get 'possible_guidance'
248-
# end
249-
# end
250-
251226
resources :roles, only: [:create, :update, :destroy]
252227

253228
namespace :settings do
@@ -272,57 +247,4 @@
272247
end
273248
end
274249

275-
# The priority is based upon order of creation:
276-
# first created -> highest priority.
277-
278-
# Sample of regular route:
279-
# match 'products/:id' => 'catalog#view'
280-
# Keep in mind you can assign values other than :controller and :action
281-
282-
# Sample of named route:
283-
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
284-
# This route can be invoked with purchase_url(:id => product.id)
285-
286-
# Sample resource route (maps HTTP verbs to controller actions automatically):
287-
# resources :products
288-
289-
# Sample resource route with options:
290-
# resources :products do
291-
# member do
292-
# get 'short'
293-
# post 'toggle'
294-
# end
295-
#
296-
# collection do
297-
# get 'sold'
298-
# end
299-
# end
300-
301-
# Sample resource route with sub-resources:
302-
# resources :products do
303-
# resources :comments, :sales
304-
# resource :seller
305-
# end
306-
307-
# Sample resource route with more complex sub-resources
308-
# resources :products do
309-
# resources :comments
310-
# resources :sales do
311-
# get 'recent', :on => :collection
312-
# end
313-
# end
314-
315-
# Sample resource route within a namespace:
316-
# namespace :admin do
317-
# # Directs /admin/products/* to Admin::ProductsController
318-
# # (app/controllers/admin/products_controller.rb)
319-
# resources :products
320-
# end
321-
322-
323-
# See how all your routes lay out with "rake routes"
324-
325-
# This is a legacy wild controller route that's not recommended for RESTful applications.
326-
# Note: This route will make all actions in every controller accessible via GET requests.
327-
# match ':controller(/:action(/:id))(.:format)'
328250
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class MovePrefsToTable < ActiveRecord::Migration
2+
def change
3+
remove_column :users, :prefs
4+
5+
create_table :prefs do |t|
6+
t.string :settings
7+
t.integer :user_id
8+
end
9+
end
10+
end
11+
12+

0 commit comments

Comments
 (0)