diff --git a/Gemfile b/Gemfile index 6da36d1..35ee76e 100644 --- a/Gemfile +++ b/Gemfile @@ -15,6 +15,7 @@ # ------------------------------------------------ # DATABASE/SERVER +gem 'mysql2', '~> 0.3.18' gem 'pg' gem 'flag_shih_tzu' # Allows for bitfields in activereccord diff --git a/Gemfile.lock b/Gemfile.lock index 3e73784..8359a7c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -218,6 +218,7 @@ multi_json (1.12.1) multi_xml (0.5.5) multipart-post (2.0.0) + mysql2 (0.3.21) nokogiri (1.6.8) mini_portile2 (~> 2.1.0) pkg-config (~> 1.1.7) @@ -381,6 +382,7 @@ libv8 minitest-rails-capybara minitest-reporters + mysql2 (~> 0.3.18) omniauth omniauth-orcid omniauth-shibboleth diff --git a/app/models/answer.rb b/app/models/answer.rb index 00705da..385f4fe 100644 --- a/app/models/answer.rb +++ b/app/models/answer.rb @@ -11,11 +11,12 @@ # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 attr_accessible :text, :plan_id, :question_id, :user_id, :option_ids, - :question, :user, :plan, :as => [:default, :admin] + :question, :user, :plan, :question_options, + :as => [:default, :admin] ## # Validations - validates :user, :plan, :question, :text, presence: true + validates :user, :plan, :question, presence: true # Make sure there is only one answer per question! validates :question, uniqueness: {scope: [:user, :plan], diff --git a/app/models/guidance_group.rb b/app/models/guidance_group.rb index 932a921..f55b5d0 100644 --- a/app/models/guidance_group.rb +++ b/app/models/guidance_group.rb @@ -11,7 +11,7 @@ # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 attr_accessible :organisation_id, :name, :optional_subset, :published, - :organisation, :as => [:default, :admin] + :organisation, :org, :as => [:default, :admin] attr_accessible :dmptemplate_ids, :as => [:default, :admin] @@ -25,7 +25,7 @@ - validates :name, :organisation, presence: true + validates :name, :org, presence: true ## # Converts a guidance group to a string containing the display name diff --git a/app/models/org.rb b/app/models/org.rb index 46f5d72..83899ae 100644 --- a/app/models/org.rb +++ b/app/models/org.rb @@ -20,7 +20,8 @@ attr_accessible :abbreviation, :banner_text, :logo, :remove_logo, :logo_file_name, :name, :target_url, :organisation_type_id, :wayfless_entity, :parent_id, :sort_name, - :token_permission_type_ids, :language_id, :contact_email, :language + :token_permission_type_ids, :language_id, :contact_email, + :language, :org_type, :region, :token_permission_types ## # Validators diff --git a/app/models/phase.rb b/app/models/phase.rb index df47877..a7be93d 100644 --- a/app/models/phase.rb +++ b/app/models/phase.rb @@ -15,7 +15,7 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :description, :number, :title, :template_id, + attr_accessible :description, :number, :title, :template_id, :modifiable, :template, :sections, :as => [:default, :admin] ## diff --git a/app/models/plan.rb b/app/models/plan.rb index a6c36c6..fc52536 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -13,7 +13,10 @@ # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 attr_accessible :locked, :project_id, :version_id, :version, :plan_sections, - :exported_plans, :project, :as => [:default, :admin] + :exported_plans, :project, :title, :template, :grant_number, + :identifier, :principal_investigator, :principal_investigator_identifier, + :description, :data_contact, :funder_name, :visibility, + :as => [:default, :admin] # public is a Ruby keyword so using publicly enum visibility: [:organisationally_visible, :publicly_visible, :is_test, :privately_visible] diff --git a/app/models/question.rb b/app/models/question.rb index d0fde11..7a91897 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -24,7 +24,8 @@ :suggested_answer, :text, :section_id, :question_format_id, :question_options_attributes, :suggested_answers_attributes, :option_comment_display, :theme_ids, :section, :question_format, - :question_options, :suggested_answers, :answers, :themes, :as => [:default, :admin] + :question_options, :suggested_answers, :answers, :themes, + :modifiable, :option_comment_display, :as => [:default, :admin] diff --git a/app/models/question_option.rb b/app/models/question_option.rb index b16b0d9..6fa289d 100644 --- a/app/models/question_option.rb +++ b/app/models/question_option.rb @@ -7,5 +7,6 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :text, :question_id, :is_default, :number, :as => [:default, :admin] + attr_accessible :text, :question_id, :is_default, :number, :question, + :as => [:default, :admin] end diff --git a/app/models/section.rb b/app/models/section.rb index 3577dd9..f967e16 100644 --- a/app/models/section.rb +++ b/app/models/section.rb @@ -10,8 +10,9 @@ accepts_nested_attributes_for :questions, :reject_if => lambda {|a| a[:text].blank? }, :allow_destroy => true # accepts_nested_attributes_for :version - attr_accessible :organisation_id, :description, :number, :title, :published, :questions_attributes, - :organisation, :as => [:default, :admin] + attr_accessible :organisation_id, :description, :number, :title, :published, + :questions_attributes, :organisation, :phase, :modifiable, + :as => [:default, :admin] ## # return the title of the section diff --git a/app/models/suggested_answer.rb b/app/models/suggested_answer.rb index b4df355..5b94c8d 100644 --- a/app/models/suggested_answer.rb +++ b/app/models/suggested_answer.rb @@ -8,7 +8,8 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :org_id, :question_id, :text, :is_example, :as => [:default, :admin] + attr_accessible :org_id, :question_id, :text, :is_example, + :org, :question, :as => [:default, :admin] # EVALUATE CLASS AND INSTANCE METHODS BELOW diff --git a/app/models/template.rb b/app/models/template.rb index fbee582..63b48de 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -12,8 +12,9 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :id, :organisation_id, :description, :published, :title, :locale, :is_default, - :guidance_group_ids, :organisation, :plans, :phases, :as => [:default, :admin] + attr_accessible :id, :org_id, :description, :published, :title, :locale, + :is_default, :guidance_group_ids, :org, :plans, :phases, + :version, :visibility, :published, :as => [:default, :admin] # defines the export setting for a template object has_settings :export, class_name: 'Settings::Template' do |s| diff --git a/app/models/user.rb b/app/models/user.rb index 4070aac..dec3d0e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -43,7 +43,7 @@ :firstname, :last_login,:login_count, :orcid_id, :password, :shibboleth_id, :user_status_id, :surname, :user_type_id, :org_id, :skip_invitation, :other_organisation, :accept_terms, :role_ids, :dmponline3, :api_token, - :organisation, :language, :language_id + :organisation, :language, :language_id, :perms, :confirmed_at validates :email, email: true, allow_nil: true, uniqueness: true diff --git a/db/schema.rb b/db/schema.rb index 4b37f74..d5a1e90 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -14,349 +14,428 @@ ActiveRecord::Schema.define(version: 20170124235829) do create_table "answers", force: :cascade do |t| - t.text "text" - t.integer "plan_id" - t.integer "user_id" - t.integer "question_id" + t.text "text", limit: 65535 + t.integer "plan_id", limit: 4 + t.integer "user_id", limit: 4 + t.integer "question_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end + add_index "answers", ["plan_id"], name: "fk_rails_84a6005a3e", using: :btree + add_index "answers", ["question_id"], name: "fk_rails_3d5ed4418f", using: :btree + add_index "answers", ["user_id"], name: "fk_rails_584be190c2", using: :btree + create_table "answers_question_options", id: false, force: :cascade do |t| - t.integer "answer_id", null: false - t.integer "question_option_id", null: false + t.integer "answer_id", limit: 4, null: false + t.integer "question_option_id", limit: 4, null: false end - add_index "answers_question_options", ["answer_id", "question_option_id"], name: "answer_question_option_index" - add_index "answers_question_options", ["question_option_id", "answer_id"], name: "question_option_answer_index" + add_index "answers_question_options", ["answer_id", "question_option_id"], name: "answer_question_option_index", using: :btree + add_index "answers_question_options", ["question_option_id", "answer_id"], name: "question_option_answer_index", using: :btree create_table "exported_plans", force: :cascade do |t| - t.integer "plan_id" - t.integer "user_id" - t.string "format" + t.integer "plan_id", limit: 4 + t.integer "user_id", limit: 4 + t.string "format", limit: 255 t.datetime "created_at" t.datetime "updated_at" end create_table "file_types", force: :cascade do |t| - t.string "name" - t.string "icon_name" - t.integer "icon_size" - t.string "icon_location" + t.string "name", limit: 255 + t.string "icon_name", limit: 255 + t.integer "icon_size", limit: 4 + t.string "icon_location", limit: 255 t.datetime "created_at" t.datetime "updated_at" end create_table "file_uploads", force: :cascade do |t| - t.string "name" - t.string "title" - t.text "description" - t.integer "size" + t.string "name", limit: 255 + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.integer "size", limit: 4 t.boolean "published" - t.string "location" - t.integer "file_type_id" + t.string "location", limit: 255 + t.integer "file_type_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end create_table "friendly_id_slugs", force: :cascade do |t| - t.string "slug", null: false - t.integer "sluggable_id", null: false + t.string "slug", limit: 255, null: false + t.integer "sluggable_id", limit: 4, null: false t.string "sluggable_type", limit: 40 t.datetime "created_at" end - add_index "friendly_id_slugs", ["slug", "sluggable_type"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type", unique: true - add_index "friendly_id_slugs", ["sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_id" - add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type" + add_index "friendly_id_slugs", ["slug", "sluggable_type"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type", unique: true, using: :btree + add_index "friendly_id_slugs", ["sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_id", using: :btree + add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree create_table "guidance_groups", force: :cascade do |t| - t.string "name" - t.integer "org_id" + t.string "name", limit: 255 + t.integer "org_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" t.boolean "optional_subset" t.boolean "published" end + add_index "guidance_groups", ["org_id"], name: "fk_rails_819c1dbbc7", using: :btree + create_table "guidances", force: :cascade do |t| - t.text "text" - t.integer "guidance_group_id" + t.text "text", limit: 65535 + t.integer "guidance_group_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.integer "question_id" + t.integer "question_id", limit: 4 t.boolean "published" end + add_index "guidances", ["guidance_group_id"], name: "fk_rails_20d29da787", using: :btree + create_table "identifier_schemes", force: :cascade do |t| - t.string "name" - t.string "description" + t.string "name", limit: 255 + t.string "description", limit: 255 t.boolean "active" t.datetime "created_at" t.datetime "updated_at" end create_table "languages", force: :cascade do |t| - t.string "abbreviation" - t.string "description" - t.string "name" + t.string "abbreviation", limit: 255 + t.string "description", limit: 255 + t.string "name", limit: 255 t.boolean "default_language" end create_table "notes", force: :cascade do |t| - t.integer "user_id" - t.text "text" + t.integer "user_id", limit: 4 + t.text "text", limit: 65535 t.boolean "archived" - t.integer "answer_id" - t.integer "archived_by" + t.integer "answer_id", limit: 4 + t.integer "archived_by", limit: 4 t.datetime "created_at" t.datetime "updated_at" end + add_index "notes", ["answer_id"], name: "fk_rails_907f8d48bf", using: :btree + add_index "notes", ["user_id"], name: "fk_rails_7f2323ad43", using: :btree + create_table "org_token_permissions", force: :cascade do |t| - t.integer "org_id" - t.integer "token_permission_type_id" + t.integer "org_id", limit: 4 + t.integer "token_permission_type_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end + add_index "org_token_permissions", ["org_id"], name: "fk_rails_e1db1b22c5", using: :btree + add_index "org_token_permissions", ["token_permission_type_id"], name: "fk_rails_2aa265f538", using: :btree + create_table "orgs", force: :cascade do |t| - t.string "name" - t.string "abbreviation" - t.string "target_url" - t.string "wayfless_entity" + t.string "name", limit: 255 + t.string "abbreviation", limit: 255 + t.string "target_url", limit: 255 + t.string "wayfless_entity", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.integer "parent_id" + t.integer "parent_id", limit: 4 t.boolean "is_other" - t.string "sort_name" - t.text "banner_text" - t.string "logo_file_name" - t.integer "region_id" - t.integer "language_id" - t.string "logo_uid" - t.string "logo_name" - t.string "contact_email" - t.integer "org_type", default: 0, null: false + t.string "sort_name", limit: 255 + t.text "banner_text", limit: 65535 + t.string "logo_file_name", limit: 255 + t.integer "region_id", limit: 4 + t.integer "language_id", limit: 4 + t.string "logo_uid", limit: 255 + t.string "logo_name", limit: 255 + t.string "contact_email", limit: 255 + t.integer "org_type", limit: 4, default: 0, null: false end + add_index "orgs", ["language_id"], name: "fk_rails_5640112cab", using: :btree + add_index "orgs", ["region_id"], name: "fk_rails_5a6adf6bab", using: :btree + create_table "perms", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.datetime "created_at" t.datetime "updated_at" end - add_index "perms", ["name"], name: "index_perms_on_name" - add_index "perms", ["name"], name: "index_roles_on_name_and_resource_type_and_resource_id" + add_index "perms", ["name"], name: "index_perms_on_name", using: :btree + add_index "perms", ["name"], name: "index_roles_on_name_and_resource_type_and_resource_id", using: :btree create_table "phases", force: :cascade do |t| - t.string "title" - t.text "description" - t.integer "number" - t.integer "template_id" + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.integer "number", limit: 4 + t.integer "template_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug", limit: 255 t.boolean "modifiable" end + add_index "phases", ["template_id"], name: "fk_rails_0f8036cb2e", using: :btree + create_table "plans", force: :cascade do |t| - t.integer "project_id" - t.string "title" - t.integer "template_id" + t.integer "project_id", limit: 4 + t.string "title", limit: 255 + t.integer "template_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.string "slug" - t.string "grant_number" - t.string "identifier" - t.text "description" - t.string "principal_investigator" - t.string "principal_investigator_identifier" - t.string "data_contact" - t.string "funder_name" - t.integer "visibility", default: 0, null: false + t.string "slug", limit: 255 + t.string "grant_number", limit: 255 + t.string "identifier", limit: 255 + t.text "description", limit: 65535 + t.string "principal_investigator", limit: 255 + t.string "principal_investigator_identifier", limit: 255 + t.string "data_contact", limit: 255 + t.string "funder_name", limit: 255 + t.integer "visibility", limit: 4, default: 0, null: false end + add_index "plans", ["template_id"], name: "fk_rails_3424ca281f", using: :btree + create_table "question_formats", force: :cascade do |t| - t.string "title" - t.text "description" + t.string "title", limit: 255 + t.text "description", limit: 65535 t.datetime "created_at" t.datetime "updated_at" end create_table "question_options", force: :cascade do |t| - t.integer "question_id" - t.string "text" - t.integer "number" + t.integer "question_id", limit: 4 + t.string "text", limit: 255 + t.integer "number", limit: 4 t.boolean "is_default" t.datetime "created_at" t.datetime "updated_at" end + add_index "question_options", ["question_id"], name: "fk_rails_b9c5f61cf9", using: :btree + create_table "questions", force: :cascade do |t| - t.text "text" - t.text "default_value" - t.text "guidance" - t.integer "number" - t.integer "section_id" + t.text "text", limit: 65535 + t.text "default_value", limit: 65535 + t.text "guidance", limit: 65535 + t.integer "number", limit: 4 + t.integer "section_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.integer "question_format_id" - t.boolean "option_comment_display", default: true + t.integer "question_format_id", limit: 4 + t.boolean "option_comment_display", default: true t.boolean "modifiable" end + add_index "questions", ["question_format_id"], name: "fk_rails_4fbc38c8c7", using: :btree + add_index "questions", ["section_id"], name: "fk_rails_c50eadc3e3", using: :btree + create_table "questions_themes", id: false, force: :cascade do |t| - t.integer "question_id", null: false - t.integer "theme_id", null: false + t.integer "question_id", limit: 4, null: false + t.integer "theme_id", limit: 4, null: false end - add_index "questions_themes", ["question_id", "theme_id"], name: "question_theme_index" - add_index "questions_themes", ["theme_id", "question_id"], name: "theme_question_index" + add_index "questions_themes", ["question_id", "theme_id"], name: "question_theme_index", using: :btree + add_index "questions_themes", ["theme_id", "question_id"], name: "theme_question_index", using: :btree create_table "region_groups", force: :cascade do |t| - t.integer "super_region_id" - t.integer "region_id" + t.integer "super_region_id", limit: 4 + t.integer "region_id", limit: 4 end create_table "regions", force: :cascade do |t| - t.string "abbreviation" - t.string "description" - t.string "name" + t.string "abbreviation", limit: 255 + t.string "description", limit: 255 + t.string "name", limit: 255 end create_table "roles", force: :cascade do |t| - t.integer "user_id" - t.integer "plan_id" + t.integer "user_id", limit: 4 + t.integer "plan_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.integer "access", default: 0, null: false + t.integer "access", limit: 4, default: 0, null: false end + add_index "roles", ["plan_id"], name: "fk_rails_a1ce6c2772", using: :btree + add_index "roles", ["user_id"], name: "fk_rails_ab35d699f0", using: :btree + create_table "sections", force: :cascade do |t| - t.string "title" - t.text "description" - t.integer "number" + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.integer "number", limit: 4 t.datetime "created_at" t.datetime "updated_at" t.boolean "published" - t.integer "phase_id" + t.integer "phase_id", limit: 4 t.boolean "modifiable" end + add_index "sections", ["phase_id"], name: "fk_rails_1853581585", using: :btree + create_table "settings", force: :cascade do |t| - t.string "var", null: false - t.text "value" - t.integer "target_id", null: false - t.string "target_type", null: false + t.string "var", limit: 255, null: false + t.text "value", limit: 65535 + t.integer "target_id", limit: 4, null: false + t.string "target_type", limit: 255, null: false t.datetime "created_at" t.datetime "updated_at" end - add_index "settings", ["target_type", "target_id", "var"], name: "index_settings_on_target_type_and_target_id_and_var", unique: true + add_index "settings", ["target_type", "target_id", "var"], name: "index_settings_on_target_type_and_target_id_and_var", unique: true, using: :btree create_table "splash_logs", force: :cascade do |t| - t.string "destination" + t.string "destination", limit: 255 t.datetime "created_at" t.datetime "updated_at" end create_table "suggested_answers", force: :cascade do |t| - t.integer "question_id" - t.integer "org_id" - t.text "text" + t.integer "question_id", limit: 4 + t.integer "org_id", limit: 4 + t.text "text", limit: 65535 t.boolean "is_example" t.datetime "created_at" t.datetime "updated_at" end + add_index "suggested_answers", ["org_id"], name: "fk_rails_473de65779", using: :btree + add_index "suggested_answers", ["question_id"], name: "fk_rails_daa60b5b70", using: :btree + create_table "templates", force: :cascade do |t| - t.string "title" - t.text "description" + t.string "title", limit: 255 + t.text "description", limit: 65535 t.boolean "published" - t.integer "org_id" - t.string "locale" + t.integer "org_id", limit: 4 + t.string "locale", limit: 255 t.boolean "is_default" t.datetime "created_at" t.datetime "updated_at" - t.integer "version" - t.integer "visibility" - t.integer "customization_of" - t.integer "dmptemplate_id" + t.integer "version", limit: 4 + t.integer "visibility", limit: 4 + t.integer "customization_of", limit: 4 + t.integer "dmptemplate_id", limit: 4 end + add_index "templates", ["org_id"], name: "fk_rails_481431e1bd", using: :btree + create_table "themes", force: :cascade do |t| - t.string "title" - t.text "description" + t.string "title", limit: 255 + t.text "description", limit: 65535 t.datetime "created_at" t.datetime "updated_at" - t.string "locale" + t.string "locale", limit: 255 end create_table "themes_in_guidance", id: false, force: :cascade do |t| - t.integer "theme_id" - t.integer "guidance_id" + t.integer "theme_id", limit: 4 + t.integer "guidance_id", limit: 4 end + add_index "themes_in_guidance", ["guidance_id"], name: "fk_rails_a5ab9402df", using: :btree + add_index "themes_in_guidance", ["theme_id"], name: "fk_rails_7d708f6f1e", using: :btree + create_table "token_permission_types", force: :cascade do |t| - t.string "token_type" - t.text "text_description" + t.string "token_type", limit: 255 + t.text "text_description", limit: 65535 t.datetime "created_at" t.datetime "updated_at" end create_table "user_identifiers", force: :cascade do |t| - t.string "identifier" + t.string "identifier", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.integer "user_id" - t.integer "identifier_scheme_id" + t.integer "user_id", limit: 4 + t.integer "identifier_scheme_id", limit: 4 end + add_index "user_identifiers", ["identifier_scheme_id"], name: "fk_rails_fe95df7db0", using: :btree + add_index "user_identifiers", ["user_id"], name: "fk_rails_65c9a98cdb", using: :btree + create_table "users", force: :cascade do |t| - t.string "firstname" - t.string "surname" - t.string "email", default: "", null: false - t.string "orcid_id" - t.string "shibboleth_id" + t.string "firstname", limit: 255 + t.string "surname", limit: 255 + t.string "email", limit: 255, default: "", null: false + t.string "orcid_id", limit: 255 + t.string "shibboleth_id", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.string "encrypted_password", default: "" - t.string "reset_password_token" + t.string "encrypted_password", limit: 255, default: "" + t.string "reset_password_token", limit: 255 t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0 + t.integer "sign_in_count", limit: 4, default: 0 t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.string "confirmation_token" + t.string "current_sign_in_ip", limit: 255 + t.string "last_sign_in_ip", limit: 255 + t.string "confirmation_token", limit: 255 t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "invitation_token" + t.string "invitation_token", limit: 255 t.datetime "invitation_created_at" t.datetime "invitation_sent_at" t.datetime "invitation_accepted_at" - t.string "other_organisation" + t.string "other_organisation", limit: 255 t.boolean "dmponline3" t.boolean "accept_terms" - t.integer "org_id" - t.string "api_token" - t.integer "invited_by_id" - t.string "invited_by_type" - t.integer "language_id" + t.integer "org_id", limit: 4 + t.string "api_token", limit: 255 + t.integer "invited_by_id", limit: 4 + t.string "invited_by_type", limit: 255 + t.integer "language_id", limit: 4 end - add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true - add_index "users", ["email"], name: "index_users_on_email", unique: true - add_index "users", ["invitation_token"], name: "index_users_on_invitation_token", unique: true - add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true + add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree + add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree + add_index "users", ["invitation_token"], name: "index_users_on_invitation_token", unique: true, using: :btree + add_index "users", ["language_id"], name: "fk_rails_45f4f12508", using: :btree + add_index "users", ["org_id"], name: "fk_rails_e73753bccb", using: :btree + add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree create_table "users_perms", id: false, force: :cascade do |t| - t.integer "user_id" - t.integer "perm_id" + t.integer "user_id", limit: 4 + t.integer "perm_id", limit: 4 end - add_index "users_perms", ["user_id", "perm_id"], name: "index_users_perms_on_user_id_and_perm_id" + add_index "users_perms", ["perm_id"], name: "fk_rails_457217c31c", using: :btree + add_index "users_perms", ["user_id", "perm_id"], name: "index_users_perms_on_user_id_and_perm_id", using: :btree + add_foreign_key "answers", "plans" + add_foreign_key "answers", "questions" + add_foreign_key "answers", "users" + add_foreign_key "answers_question_options", "answers" + add_foreign_key "answers_question_options", "question_options" + add_foreign_key "guidance_groups", "orgs" + add_foreign_key "guidances", "guidance_groups" + add_foreign_key "notes", "answers" + add_foreign_key "notes", "users" + add_foreign_key "org_token_permissions", "orgs" + add_foreign_key "org_token_permissions", "token_permission_types" + add_foreign_key "orgs", "languages" + add_foreign_key "orgs", "regions" + add_foreign_key "phases", "templates" + add_foreign_key "plans", "templates" + add_foreign_key "question_options", "questions" + add_foreign_key "questions", "question_formats" + add_foreign_key "questions", "sections" + add_foreign_key "questions_themes", "questions" + add_foreign_key "questions_themes", "themes" + add_foreign_key "roles", "plans" + add_foreign_key "roles", "users" + add_foreign_key "sections", "phases" + add_foreign_key "suggested_answers", "orgs" + add_foreign_key "suggested_answers", "questions" + add_foreign_key "templates", "orgs" + add_foreign_key "themes_in_guidance", "guidances" + add_foreign_key "themes_in_guidance", "themes" + add_foreign_key "user_identifiers", "identifier_schemes" + add_foreign_key "user_identifiers", "users" + add_foreign_key "users", "languages" + add_foreign_key "users", "orgs" + add_foreign_key "users_perms", "perms" + add_foreign_key "users_perms", "users" end diff --git a/db/seeds.rb b/db/seeds.rb index 8a016e0..f4188d4 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -2,777 +2,794 @@ # This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). -languages = { - 'English(UK)' => { - abbreviation: 'en-UK', - description: 'UK English language used as default', - name: 'English(UK)', - default_language: true - }, - 'FR' => { - abbreviation: 'fr', - description: '', - name: 'fr', +# Identifier Schemes +# ------------------------------------------------------- +identifier_schemes = [ + {name: 'orcid', description: 'ORCID researcher identifiers', active: true}, + {name: 'shibboleth', description: 'Shibboleth', active: false}, + {name: 'facebook', description: 'Facebook OAuth', active: false} +] +identifier_schemes.map{ |is| IdentifierScheme.create!(is) if IdentifierScheme.find_by(name: is[:name]).nil? } + +# Question Formats +# ------------------------------------------------------- +question_formats = [ + {title: "Text area"}, + {title: "Text field"}, + {title: "Radio buttons"}, + {title: "Check box"}, + {title: "Dropdown"}, + {title: "Multi select box"}, + {title: "Date"} +] +question_formats.map{ |qf| QuestionFormat.create!(qf) if QuestionFormat.find_by(title: qf[:title]).nil? } + +# Languages (check config/locales for any ones not defined here) +# ------------------------------------------------------- +languages = [ + {abbreviation: 'en-UK', + description: 'UK English', + name: 'English (UK)', + default_language: true}, + {abbreviation: 'en-US', + description: 'US English', + name: 'English (US)', + default_language: false}, + {abbreviation: 'fr', + description: 'French', + name: 'French', + default_language: false}, + {abbreviation: 'de', + description: 'German', + name: 'German', + default_language: false}, + {abbreviation: 'es', + description: 'Spanish', + name: 'Spanish', + default_language: false} +] +languages.map{ |l| Language.create!(l) if Language.find_by(abbreviation: l[:abbreviation]).nil? } + +# Scan through the locale files and add an entry if a file is present but +# not defined in this seed file +Dir.entries("#{Rails.root.join("config", "locales").to_s}").each do |f| + if f[-4..-1] == '.yml' + lang = f.gsub('.yml', '') + + if Language.where(abbreviation: lang).empty? + Language.create!({ + abbreviation: lang, + description: lang, + name: lang, default_language: false - }, - 'DE' => { - abbreviation: 'de', - description: '', - name: 'de', - default_language: false - }, - 'ES' => { - abbreviation: 'es', - description: '', - name: 'es', - default_language: false - } -} - -languages.each do |l, details| - if Language.where(name: details[:name]).empty? - language = Language.new - language.abbreviation = details[:abbreviation] - language.description = details[:description] - language.name = details[:name] - language.default_language = details[:default_language] - language.save! - end -end - -regions = { - 'UK' => { - abbreviation: 'uk', - description: 'default region', - name: 'UK', - }, - 'DE' => { - abbreviation: 'de', - description: '', - name: 'DE', - }, - 'Horizon2020' => { - abbreviation: 'horizon', - description: 'European super region', - name: 'Horizon2020', - } -} - -regions.each do |l, details| - if Region.where(name: details[:name]).empty? - region = Region.new - region.abbreviation = details[:abbreviation] - region.description = details[:description] - region.name = details[:name] - region.save! - end -end - -region_groups = { - 'UK' => { - super_region_name: 'Horizon2020', - region_name: 'UK', - }, - 'DE' => { - super_region_name: 'Horizon2020', - region_name: 'DE', - } -} - -region_groups.each do |l, details| - if RegionGroup.find_by(region_id: details[:region_name]).blank? - region_group = RegionGroup.new - region_group.super_region_id = Region.find_by_name(details[:super_region_name]).id - region_group.region_id = Region.find_by_name(details[:region_name]).id - region_group.save! - end -end - -identifier_schemes = { - 'orcid' => { - name: 'orcid', - description: 'ORCID provides a persistent digital identifier for researchers', - active: true - } -} - -identifier_schemes.each do |l, details| - if IdentifierScheme.where(name: details[:name]).empty? - scheme = IdentifierScheme.new({ - name: details[:name], - description: details[:description], - active: details[:active] - }) - scheme.save! - end -end - -organisation_types = { - 'Organisation' => { - name: "Organisation" - }, - 'Funder' => { - name: "Funder" - }, - 'Project' => { - name: "Project" - }, - 'Institution' => { - name: "Institution" - }, - 'Research Institute' => { - name: "Research Institute" - } - } - - organisation_types.each do |org_type, details| - if OrganisationType.where(name: details[:name]).empty? - organisation_type = OrganisationType.new - organisation_type.name = details[:name] - organisation_type.save! - end - end - - organisations = { - 'Your Organization' => { - name: "My Regional Curation Centre", - abbreviation: "RCC", - sort_name: "MyRegionalCurationCenter", - organisation_type: "Organisation", - description: "An example: Regional Curation Center concerned with research data management (typically the organization hosting this website)", - banner_text: "Example: Your Regional Curation Center", - region: 'UK', - language: 'English(UK)' - }, - 'Global Funding Organization' => { - name: "Global Research Center", - abbreviation: "EGRC", - sort_name: "GlobalResearchCenter", - organisation_type: "Funder", - description: "An example: Research funding agency", - banner_text: "Example: Global Research Center", - region: 'UK', - language: 'English(UK)' - }, - 'Regional Funding Organization' => { - name: "Regional Science Federation", - abbreviation: "RegSciFed", - sort_name: "RegionalScienceFederation", - organisation_type: "Funder", - description: "An example: Regional funding agency for scientific research", - banner_text: "Example: Regional Science Federation", - region: 'UK', - language: 'English(UK)' - }, - 'Example Institution'=> { - name: "Capital City College", - abbreviation: "CapColl", - sort_name: "CapitalCityCollege", - organisation_type: "Institution", - description: "An example: Academic institution", - banner_text: "Example: Capital City College ... go mascots!!", - region: 'UK', - language: 'English(UK)' - } - } - - organisations.each do |org, details| - if Org.where(abbreviation: details[:abbreviation]).empty? - organisation = Org.new - organisation.name = details[:name] - organisation.abbreviation = details[:abbreviation] - organisation.sort_name = details[:sort_name] - organisation.organisation_type = OrganisationType.find_by_name(details[:organisation_type]) - organisation.region_id = Region.find_by_name(details[:region]).id - organisation.language_id = Language.find_by_name(details[:language]).id - organisation.save! - end - end - -roles = { - 'admin' => { - name: "admin" #depricated - }, - 'org_admin' => { - name: "org_admin" #depricated - }, - 'user' => { - name: "user" #depricated - }, - 'add_organisations' => { - name: 'add_organisations' - }, - 'change_org_affiliation' => { - name: 'change_org_affiliation' - }, - 'grant_permissions' => { - name: 'grant_permissions' - }, - 'modify_templates' => { - name: 'modify_templates' - }, - 'modify_guidance' => { - name: 'modify_guidance' - }, - 'use_api' => { - name: 'use_api' - }, - 'change_org_details' => { - name: 'change_org_details' - }, - 'grant_api_to_orgs' => { - name: 'grant_api_to_orgs' - } -} - -roles.each do |role, details| - if Role.where(name: details[:name]).empty? - role = Role.new - role.name = details[:name] - role.save! - end -end - -users = { - 'Super admin' => { - email: "super_admin@example.com", - password: "password123", - firstname: "RCC Super", - surname: "Admin", - password_confirmation: "password123", - organisation: "RCC", - language: 'English(UK)', - roles: ['admin','org_admin','add_organisations','change_org_affiliation','grant_permissions','modify_templates','modify_guidance','use_api','change_org_details','grant_api_to_orgs'], - accept_terms: true, - confirmed_at: Time.zone.now - }, - 'Funder admin' => { - email: "funder_admin@example.com", - password: "password123", - password_confirmation: "password123", - firstname: "Funder", - surname: "Admin", - organisation: "RegSciFed", - language: 'English(UK)', - roles: ['org_admin','grant_permissions','modify_templates','modify_guidance','change_org_details'], - accept_terms: true, - confirmed_at: Time.zone.now - }, - 'Organizational admin' => { - email: "org_admin@example.com", - password: "password123", - password_confirmation: "password123", - firstname: "Organization", - surname: "Admin", - organisation: "CapColl", - language: 'English(UK)', - roles: ['org_admin','grant_permissions','modify_templates','modify_guidance','change_org_details'], - accept_terms: true, - confirmed_at: Time.zone.now - }, - 'Organizational user' => { - email: "org_user@example.com", - password: "password123", - password_confirmation: "password123", - firstname: "Jane", - surname: "Researcher", - organisation: "CapColl", - language: 'English(UK)', - roles: ['user'], - accept_terms: true, - confirmed_at: Time.zone.now - }, - 'Organizational user' => { - email: "org_user@example.com", - password: "password123", - password_confirmation: "password123", - firstname: "Jane", - surname: "Researcher", - organisation: "CapColl", - language: 'English(UK)', - roles: ['user'], - accept_terms: true, - confirmed_at: Time.zone.now - } - } - -users.each do |user, details| - if User.where(email: details[:email]).empty? - usr = User.new - else - usr = User.where(email: details[:email]) - end - usr.email = details[:email] - usr.password = details[:password] - usr.password_confirmation = details[:password_confirmation] - usr.confirmed_at = details[:confirmed_at] - usr.organisation_id = Org.find_by_abbreviation(details[:organisation]).id - usr.language_id = Language.find_by_name(details[:language]).id - details[:roles].each do |role| - usr.roles << Role.find_by_name(role) + }) end - usr.accept_terms = details[:accept_terms] - usr.save! -end - - themes = { - "Theme 1" => { - title: "Theme 1", - locale: "en" - }, - "Theme 2" => { - title: "Theme 2", - locale: "en" - }, - "Theme 3" => { - title: "Theme 3", - locale: "en", - description: "Theme 3 description." - }, - "Theme 4" => { - title: "Theme 4", - locale: "en", - description: "Theme 4 description." - } - } - - themes.each do |t, details| - if Theme.where(title: details[:title]).empty? - theme = Theme.new - theme.title = details[:title] - theme.locale = details[:locale] - theme.description = details[:description] - theme.save! - end - end - - question_formats = { - "Text area" => { - title: "Text area" - }, - "Text field" => { - title: "Text field" - }, - "Radio buttons" => { - title: "Radio buttons" - }, - "Check box" => { - title: "Check box" - }, - "Dropdown" => { - title: "Dropdown" - }, - "Multi select box" => { - title: "Multi select box" - }, - } - - question_formats.each do |qf, details| - if QuestionFormat.where(title: details[:title]).empty? - question_format = QuestionFormat.new - question_format.title = details[:title] - question_format.save! - end - end - - guidance_groups = { - "RCC Guidance" => { - name: "My organization guidance (optional generic guidance you provide for users)", - organisation: "RCC", - optional_subset: true - }, - "Global Research Center Guidance" => { - name: "Global Research Center (Funder specific guidance)", - organisation: "EGRC", - optional_subset: false - }, - "Regional Science Federation Guidance" => { - name: "Regional Science Federation (Funder specific guidance)", - organisation: "RegSciFed", - optional_subset: false - }, - "Institutional Guidance" => { - name: "CapColl - School of Math and Science (optional institutional guidance)", - organisation: "CapColl", - optional_subset: true - } - } - - guidance_groups.each do |gg, details| - if GuidanceGroup.where(name: details[:name]).empty? - guidance_group = GuidanceGroup.new - guidance_group.name = details[:name] - guidance_group.organisation = Org.find_by_abbreviation(details[:organisation]) - guidance_group.optional_subset = details[:optional_subset] - guidance_group.save! - end - end - - guidances = { - "Guidance 1" => { - text: "Guidance text", - guidance_group: "My organization guidance (optional generic guidance you provide for users)", - themes: ["Theme 4"] - }, - "Guidance 2" => { - text: "Guidance text", - guidance_group: "Global Research Center (Funder specific guidance)", - themes: ["Theme 2"] - }, - "Guidance 3" => { - text: "Guidance text", - guidance_group: "Global Research Center (Funder specific guidance)", - themes: ["Theme 3"] - }, - "Guidance 4" => { - text: "Guidance text", - guidance_group: "Regional Science Federation (Funder specific guidance)", - themes: ["Theme 1"] - }, - "Guidance 4" => { - text: "Guidance text", - guidance_group: "CapColl - School of Math and Science (optional institutional guidance)", - themes: ["Theme 1"] - } - } - - guidances.each do |g, details| - if Guidance.where(text: details[:text]).empty? - guidance = Guidance.new - guidance.text = details[:text] - guidance.guidance_groups << GuidanceGroup.find_by_name(details[:guidance_group]) - details[:themes].each do |theme| - guidance.themes << Theme.find_by_title(theme) - end - guidance.save! - end - end - - templates = { - "RCC" => { - title: "Regional Curation Center Template", - description: "The default RCC template", - published: true, - organisation: "RCC", - locale: "en", - is_default: true - }, - "Global Research Center" => { - title: "Global Research Center Award", - description: "Funder template description", - published: true, - organisation: "EGRC", - locale: "en", - is_default: false - }, - "Regional Science Federation" => { - title: "Regional Science Federation Grant - Summary", - description: "Funder template description for phase 1", - published: true, - organisation: "RegSciFed", - locale: "en", - is_default: false - }, - "Regional Science Federation2" => { - title: "Regional Science Federation Grant - Finalized", - description: "Funder template description for phase 2", - published: true, - organisation: "RegSciFed", - locale: "en", - is_default: false - } - } - - templates.each do |t, details| - org = Org.where(abbreviation: details[:organisation]).first - - if Dmptemplate.where(organisation: org).where(title: details[:title]).empty? - template = Dmptemplate.new - template.title = details[:title] - template.description = details[:description] - template.published = details[:published] - template.locale = details[:locale] - template.is_default = details[:is_default] - template.organisation = org - template.save! - end - end - - phases = { - "RCC" => { - title: "Regional CurationCenter Data Management Plan", - number: 1, - template: "Regional Curation Center Template" - }, - "EGRC Template" => { - title: "Global Research Center Annual Award", - number: 1, - template: "Global Research Center Award" - }, - "RegSciFed Template" => { - title: "Regional Science Federation - Preliminary", - number: 1, - template: "Regional Science Federation Grant - Summary" - }, - "RegSciFed Template2" => { - title: "Regional Science Federation - Final", - number: 1, - template: "Regional Science Federation Grant - Finalized" - } - } - - phases.each do |p, details| - if Phase.where(title: details[:title]).empty? - phase = Phase.new - phase.title = details[:title] - phase.number = details[:number] - phase.dmptemplate = Dmptemplate.find_by_title(details[:template]) - phase.save! - end - end - - versions = { - "RCC" => { - title: "Default Template v1", - number: 1, - phase: "Regional CurationCenter Data Management Plan" - }, - "EGRC" => { - title: "Annual Award v1", - number: 1, - phase: "Global Research Center Annual Award" - }, - "RegSciFed_1" => { - title: "Grant Summary v1", - number: 1, - phase: "Regional Science Federation - Preliminary" - }, - "RegSciFed_2" => { - title: "Grant Finalized Award v1", - number: 1, - phase: "Regional Science Federation - Final" - }, - "RegSciFed_2.1" => { - title: "Grant Finalized v2", - number: 1, - phase: "Regional Science Federation - Final" - }, - } - - versions.each do |v, details| - if Version.where(title: details[:title]).empty? - version = Version.new - version.title = details[:title] - version.number = details[:number] - version.phase = Phase.find_by_title(details[:phase]) - version.save! - end - end - - sections = { - "Section 1" => { - title: "Data Collection", - number: 1, - description: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", - version: "Default Template v1", - organisation: "RCC" - }, - "Section 2" => { - title: "Documentation and Metadata", - number: 2, - description: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", - version: "Default Template v1", - organisation: "RCC" - }, - "Section A" => { - title: "Data Overview", - number: 1, - version: "Annual Award v1", - organisation: "EGRC" - }, - "Section B" => { - title: "Ethics and Legal Compliance", - number: 2, - version: "Annual Award v1", - organisation: "EGRC" - }, - "Section C" => { - title: "Storage and Backup", - number: 3, - version: "Annual Award v1", - organisation: "EGRC" - }, - "Section D" => { - title: "Preservation, Sustainability and Use", - number: 4, - version: "Annual Award v1", - organisation: "EGRC" - }, - "regSciFed Summary" => { - title: "Data Collection Guidelines", - number: 1, - description: "This is what we plan on collecting and how we're going to store it.", - version: "Grant Summary v1", - organisation: "RegSciFed" - }, - "RegSciFed Final 1" => { - title: "Data Collection and Storage", - number: 1, - version: "Grant Finalized Award v1", - organisation: "RegSciFed" - }, - "RegSciFed Final 1_2" => { - title: "Data Preservation", - number: 2, - version: "Grant Finalized v2", - organisation: "RegSciFed" - }, - "RegSciFed Final 2_2" => { - title: "Ongoing Access", - number: 3, - version: "Grant Finalized v2", - organisation: "RegSciFed" - } - } - - sections.each do |s, details| - if Section.where(title: details[:title]).empty? - section = Section.new - section.title = details[:title] - section.number = details[:number] - section.description = details[:description] - section.version = Version.find_by_title(details[:version]) - section.organisation = Org.find_by_abbreviation(details[:organisation]) - section.save! - end - end - - questions = { - "What data will you collect or create?" => { - text: "What data will you collect or create?", - section: "Data Collection", - number: 1, - guidance: "
Questions to consider:
Guidance:
Give a brief description of the data, including any existing data or third-party sources that will be used, in each case noting its content, type and coverage. Outline and justify your choice of format and consider the implications of data format and data volumes in terms of storage, backup and access.
", - themes: ["Theme 2"] - }, - "How will the data be collected or created?" => { - text: "How will the data be collected or created?", - section: "Data Collection", - number: 2, - guidance: "Questions to consider:
Guidance:
Outline how the data will be collected/created and which community data standards (if any) will be used. Consider how the data will be organised during the project, mentioning for example naming conventions, version control and folder structures. Explain how the consistency and quality of data collection will be controlled and documented. This may include processes such as calibration, repeat samples or measurements, standardised data capture or recording, data entry validation, peer review of data or representation with controlled vocabularies.
", - themes: ["Theme 3"] - }, - "What documentation and metadata will accompany the data?" => { - text: "What documentation and metadata will accompany the data?", - section: "Documentation and Metadata", - number: 1, - guidance: "Questions to consider:
Guidance:
Describe the types of documentation that will accompany the data to help secondary users to understand and reuse it. This should at least include basic details that will help people to find the data, including who created or contributed to the data, its title, date of creation and under what conditions it can be accessed.
Documentation may also include details on the methodology used, analytical and procedural information, definitions of variables, vocabularies, units of measurement, any assumptions made, and the format and file type of the data. Consider how you will capture this information and where it will be recorded. Wherever possible you should identify and use existing community standards.
", - themes: ["Theme 1"] - }, - "Data Overview" => { - text: "Overview of the Data", - section: "Data Overview", - number: 1, - guidance: "Things to consider:
Things to consider:
Questions to consider:
Guidance:
Ethical issues affect how you store data, who can see/use it and how long it is kept. Managing ethical concerns may include: anonymisation of data; referral to departmental or institutional ethics committees; and formal consent agreements. You should show that you are aware of any issues and have planned accordingly. If you are carrying out research involving human participants, you must also ensure that consent is requested to allow data to be shared and reused.
", - themes: ["Theme 4"] - }, - "How will you manage copyright and Intellectual Property Rights (IPR) issues?" => { - text: "How will you manage copyright and Intellectual Property Rights (IPR) issues?", - section: "Ethics and Legal Compliance", - number: 2, - guidance: "Questions to consider:
Guidance:
State who will own the copyright and IPR of any data that you will collect or create, along with the licence(s) for its use and reuse. For multi-partner projects, IPR ownership may be worth covering in a consortium agreement. Consider any relevant funder, institutional, departmental or group policies on copyright or IPR. Also consider permissions to reuse third-party data and any restrictions needed on data sharing.
", - themes: ["Theme 1"] - }, - "How will the data be stored and backed up during the research?" => { - text: "How will the data be stored and backed up during the research?", - section: "Storage and Backup", - number: 1, - guidance: "Questions to consider:
Guidance:
State how often the data will be backed up and to which locations. How many copies are being made? Storing data on laptops, computer hard drives or external storage devices alone is very risky. The use of robust, managed storage provided by university IT teams is preferable. Similarly, it is normally better to use automatic backup services provided by IT Services than rely on manual processes. If you choose to use a third-party service, you should ensure that this does not conflict with any funder, institutional, departmental or group policies, for example in terms of the legal jurisdiction in which data are held or the protection of sensitive data.
", - themes: ["Theme 2"] - }, - "4a: Preserving Your Data" => { - text: "4a: Preserving Your Data", - section: "Preservation, Sustainability and Use", - number: 1, - guidance: "Preservation of digital outputs is necessary in order for them to endure changes in the technological environment and remain potentially re-usable in the future. In this section you must state what, if any, digital outputs of your project you intend to preserve beyond the period of funding.
The length and cost of preservation should be proportionate to the value and significance of the digital outputs. If you believe that none of these should be preserved this must be justified, and if the case is a good one the application will not be prejudiced.
You must consider preservation in four ways: what, where, how and for how long. You must also consider any institutional support needed in order to carry out these plans, whether from an individual, facility, organisation or service.
You should think about the possibilities for re-use of your data in other contexts and by other users, and connect this as appropriate with your plans for dissemination and Pathways to Impact.Where there is potential for re-usability, you should use standards and formats that facilitate this.
The Technical Reviewer will be looking for evidence that you understand the reasons for the choice of technical standards and formats described in Section 2.a Technical Methodology: Standards and Formats.
You should describe the types of documentation which will accompany the data. Documentation in this sense means technical documentation as well as user documentation. It includes, for instance, technical description, code commenting, project-build guidelines, the documentation of technical decisions and resource metadata which is additional to the standards which you have described in Section 2.a. Not all types of documentation will be relevant to a project and the quantity of documentation proposed should be proportionate to the envisaged value of the data.
", - themes: ["Theme 2", "Theme 3", "Theme 4"] - }, - "4b: Ensuring Continued Accessibility and Use of Your Digital Outputs" => { - text: "4b: Ensuring Continued Accessibility and Use of Your Digital Outputs", - section: "Preservation, Sustainability and Use", - number: 2, - guidance: "In this section you must provide information about any plans for ensuring that digital outputs remain sustainable in the sense of immediately accessible and usable beyond the period of funding. There are costs to ensuring sustainability in this sense over and above the costs of preservation. The project's sustainability plan should therefore be proportionate to the envisaged longer-term value of the data for the research community and should be closely related to your plans for dissemination and Pathways to Impact.
If you believe that digital outputs should not be sustained beyond the period of funding then this should be justified. It is not mandatory to sustain all digital outputs. While you should consider the long-term value of the digital outputs to the research community, where they are purely ancillary to a project’s research outputs there may not be a case for sustaining them (though there would usually be a case for preservation).
You must consider the sustainability of your digital outputs in five ways: what, where, how, for how long, and how the cost will be covered. You must make appropriate provision for user consultation and user testing in this connection, and plan the development of suitable user documentation.
You should provide justification if you do not envisage open, public access. A case can be made for charging for or otherwise limiting access, but the default expectation is that access will be open. The Technical Reviewer will be looking for realistic commitments to sustaining public access in line with affordability and the longer-term value of the digital output.
You must consider any institutional support needed in order to carry out these plans, if not covered under Section 3, as well as the cost of keeping the digital output publicly available in the future, including issues relating to maintenance, infrastructure and upgrade (such as the need to modify aspects of a web interface or software application in order to account for changes in the technological environment). In order to minimise sustainability costs, it is generally useful that the expertise involved in the development of your project is supported by expertise in your own or a partner institution.
A sustainability plan does not necessarily mean a requirement to generate income or prevent resources from being freely available. Rather it is a requirement to consider the direct costs and expertise of maintaining digital outputs for continued access. Some applicants might be able to demonstrate that there will be no significant sustainability problems with their digital output; in some cases the university’s computing services or library might provide a firm commitment to sustaining the resource for a specified period; others might see the benefit of Open Source community development models. You should provide reassurances of sustainability which are proportionate to the envisaged longer-term value of the digital outputs for the research community.
When completing this section, you should consider the potential impact of the data on research in your field (if research in the discipline will be improved through the creation of the digital output, how will it be affected if the resource then disappears?), and make the necessary connections with your Impact Plan. You must factor in the effects of any IP, copyright and ethical issues during the period in which the digital output will be publicly accessible, connecting what you say with the relevant part of your Case for Support.
You must identify whether or not you envisage the academic content (as distinct from the technology) of the digital output being extended or updated beyond the period of funding, addressing the following issues: how this will be done, by who and at what cost. You will need to show how the cost of this will be sustained after the period of funding ends.
", - themes: ["Theme 2"] - } - } - - questions.each do |q, details| - if Question.where(text: details[:text]).empty? - question = Question.new - question.text = details[:text] - question.number = details[:number] - question.guidance = details[:guidance] - question.section = Section.find_by_title(details[:section]) - details[:themes].each do |theme| - question.themes << Theme.find_by_title(theme) - end - question.save! - end - end - -formatting = { - 'Funder' => { - font_face: "Arial, Helvetica, Sans-Serif", - font_size: 11, - margin: { top: 20, bottom: 20, left: 20, right: 20 } - }, - 'DCC' => { - font_face: "Arial, Helvetica, Sans-Serif", - font_size: 12, - margin: { top: 20, bottom: 20, left: 20, right: 20 } - } -} - -formatting.each do |org, settings| - #template = Dmptemplate.find_by_title("#{org} Template") # this is bugged, there is no Funder Template nor DCC template - #template.settings(:export).formatting = settings - #template.save! -end - -token_permission_types = { - 'guidances' => { - description: "allows a user access to the guidances api endpoint" - }, - 'plans' => { - description: "allows a user access to the plans api endpoint" - }, - 'templates' => { - description: "allows a user access to the templates api endpoint" - }, - 'statistics' => { - description: "allows a user access to the statistics api endpoint" - } -} - -token_permission_types.each do |title,settings| - if TokenPermissionType.where(token_type: title).empty? - token_permission_type = TokenPermissionType.new - token_permission_type.token_type = title - token_permission_type.text_description = settings[:description] - token_permission_type.save! end end + +# Regions (create the super regions first and then create the rest) +# ------------------------------------------------------- +regions = [ + {abbreviation: 'horizon', + description: 'European super region', + name: 'Horizon2020', + sub_regions: [ + {abbreviation: 'uk', + description: 'United Kingdom', + name: 'UK'}, + {abbreviation: 'de', + description: 'Germany', + name: 'DE'}, + {abbreviation: 'fr', + description: 'France', + name: 'FR'}, + {abbreviation: 'es', + description: 'Spain', + name: 'ES'} + ]}, + {abbreviation: 'us', + description: 'United States of America', + name: 'US'} +] + +# Create the region. If it has subregions create them and then connect them +regions.each do |r| + srs = r[:sub_regions] + r.delete(:sub_regions) unless r[:sub_regions].nil? + + if Region.find_by(abbreviation: r[:abbreviation]).nil? + region = Region.create!(r) + + unless srs.nil? + srs.each do |sr| + if Region.find_by(abbreviation: sr[:abbreviation]).nil? + subregion = Region.create!(sr) + RegionGroup.create!({region_id: subregion.id, super_region_id: region.id}) + end + end + end + + end +end + +# Perms +# ------------------------------------------------------- +perms = [ + {name: 'add_organisations'}, + {name: 'change_org_affiliation'}, + {name: 'grant_permissions'}, + {name: 'modify_templates'}, + {name: 'modify_guidance'}, + {name: 'use_api'}, + {name: 'change_org_details'}, + {name: 'grant_api_to_orgs'} +] + +perms.map{ |p| Perm.create!(p) if Perm.find_by(name: p[:name]).nil? } + +# Guidance Themes +# ------------------------------------------------------- +themes = [ + {title: 'Data Description'}, + {title: 'Data Format'}, + {title: 'Data Volume'}, + {title: 'Data Collection'}, + {title: 'Metadata & Documentation'}, + {title: 'Ethics & Privacy'}, + {title: 'Intellectual Property Rights'}, + {title: 'Storage & Security'}, + {title: 'Data Sharing'}, + {title: 'Data Repository'}, + {title: 'Preservation'}, + {title: 'Roles & Responsibilities'}, + {title: 'Budget'}, + {title: 'Related Policies'} +] +themes.map{ |t| Theme.create!(t) if Theme.find_by(title: t[:title]).nil? } + +# Token Permission Types +# ------------------------------------------------------- +token_permission_types = [ + {token_type: 'guidances', text_description: 'allows a user access to the guidances api endpoint'}, + {token_type: 'plans', text_description: 'allows a user access to the plans api endpoint'} +] +token_permission_types.map{ |tpt| TokenPermissionType.create!(tpt) if TokenPermissionType.find_by(token_type: tpt[:token_type]).nil? } + +# Create our generic organisation, a funder and a University +# ------------------------------------------------------- +orgs = [ + {name: 'Curation Centre', + abbreviation: 'CC', + banner_text: 'This is an example organisation', + org_type: 3, + language: Language.find_by(abbreviation: 'en-UK'), + token_permission_types: TokenPermissionType.all}, + {name: 'Government Agency', + abbreviation: 'GA', + org_type: 2, + language: Language.find_by(abbreviation: 'en-UK')}, + {name: 'University of Exampleland', + abbreviation: 'UOS', + org_type: 1, + language: Language.find_by(abbreviation: 'en-UK')} +] +orgs.map{ |o| Org.create!(o) if Org.find_by(abbreviation: o[:abbreviation]).nil? } + +# Create a Super Admin associated with our generic organisation, +# an Org Admin for our funder and an Org Admin and User for our University +# ------------------------------------------------------- +users = [ + {email: "super_admin@example.com", + firstname: "Super", + surname: "Admin", + password: "password123", + password_confirmation: "password123", + organisation: Org.find_by(abbreviation: 'CC'), + language: Language.find_by(abbreviation: 'en-UK'), + perms: Perm.all, + accept_terms: true, + confirmed_at: Time.zone.now}, + {email: "funder_admin@example.com", + firstname: "Funder", + surname: "Admin", + password: "password123", + password_confirmation: "password123", + organisation: Org.find_by(abbreviation: 'GA'), + language: Language.find_by(abbreviation: 'en-UK'), + perms: Perm.where.not(name: ['admin', 'add_organisations', 'change_org_affiliation']), + accept_terms: true, + confirmed_at: Time.zone.now}, + {email: "org_admin@example.com", + firstname: "Organisational", + surname: "Admin", + password: "password123", + password_confirmation: "password123", + organisation: Org.find_by(abbreviation: 'UOS'), + language: Language.find_by(abbreviation: 'en-UK'), + perms: Perm.where.not(name: ['admin', 'add_organisations', 'change_org_affiliation']), + accept_terms: true, + confirmed_at: Time.zone.now}, + {email: "org_user@example.com", + firstname: "Organisational", + surname: "User", + password: "password123", + password_confirmation: "password123", + organisation: Org.find_by(abbreviation: 'UOS'), + language: Language.find_by(abbreviation: 'en-UK'), + accept_terms: true, + confirmed_at: Time.zone.now} +] +users.map{ |u| User.create!(u) if User.find_by(email: u[:email]).nil? } + +# Create a Guidance Group for our organisation and the funder +# ------------------------------------------------------- +guidance_groups = [ + {name: "Generic Guidance (provided by the example curation centre)", + org: Org.find_by(abbreviation: 'CC'), + optional_subset: true, + published: true}, + {name: "Government Agency Advice (Funder specific guidance)", + org: Org.find_by(abbreviation: 'GA'), + optional_subset: false, + published: true} +] +guidance_groups.map{ |gg| GuidanceGroup.create!(gg) if GuidanceGroup.find_by(name: gg[:name]).nil? } + +# Initialize with the generic Roadmap guidance and a sample funder guidance +# ------------------------------------------------------- +guidances = [ + {text: "● Give a summary of the data you will collect or create, noting the content, coverage and data type, e.g., tabular data, survey data, experimental measurements, models, software, audiovisual data, physical samples, etc. +● Consider how your data could complement and integrate with existing data, or whether there are any existing data or methods that you could reuse. +● If purchasing or reusing existing data, explain how issues such as copyright and IPR have been addressed. You should aim to m +inimise any restrictions on the reuse (and subsequent sharing) of third-party data.", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Data Description')]}, + {text: "● Clearly note what format(s) your data will be in, e.g., plain text (.txt), comma-separated values (.csv), geo-referenced TIFF (.tif, .tfw). +● Explain why you have chosen certain formats. Decisions may be based on staff expertise, a preference for open formats, the standards accepted by data centres or widespread usage within a given community. +● Using standardised, interchangeable or open formats ensures the long-term usability of data; these are recommended for sharing and archiving. +● See UK Data Service guidance on recommended formats or DataONE Best Practices for file formats", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Data Format')]}, + {text: "● Note what volume of data you will create in MB/GB/TB +● Consider the implications of data volumes in terms of storage, access and preservation. Do you need to include additional costs? +● Consider whether the scale of the data will pose challenges when sharing or transferring data between sites; if so, how will you address these challenges?", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Data Volume')]}, + {text: "● Outline how the data will be collected and processed. This should cover relevant standards or methods, quality assurance and data organisation. +● Indicate how the data will be organised during the project, mentioning, e.g., naming conventions, version control and folder structures. Consistent, well-ordered research data will be easier to find, understand and reuse +● Explain how the consistency and quality of data collection will be controlled and documented. This may include processes such as calibration, repeat samples or measurements, standardised data capture, data entry validation, peer review of data or representation with controlled vocabularies. +● See the DataOne Best Practices for data quality", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Data Collection')]}, + {text: "● What metadata will be provided to help others identify and discover the data? +● Researchers are strongly encouraged to use community metadata standards where these are in place. The Research Data Alliance offers a Directory of Metadata Standards. +● Consider what other documentation is needed to enable reuse. This may include information on the methodology used to collect the data, analytical and procedural information, definitions of variables, units of measurement, any assumptions made, the format and file type of the data and software used to collect and/or process the data. +● Consider how you will capture this information and where it will be recorded, e.g., in a database with links to each item, in a ‘readme’ text file, in file headers, etc. ", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Metadata & Documentation')]}, + {text: "● Investigators carrying out research involving human participants should request consent to preserve and share the data. Do not just ask for permission to use the data in your study or make unnecessary promises to delete it at the end. +● Consider how you will protect the identity of participants, e.g., via anonymisation or using managed access procedures. +● Ethical issues may affect how you store and transfer data, who can see/use it and how long it is kept. You should demonstrate that you are aware of this and have planned accordingly. +● See UK Data Service guidance on consent for data sharing +● See ICPSR approach to confidentiality and Health Insurance Portability and Accountability Act (HIPAA) regulations for health research", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Ethics & Privacy')]}, + {text: "● State who will own the copyright and IPR of any new data that you will generate. For multi-partner projects, IPR ownership should be covered in the consortium agreement. +● Outline any restrictions needed on data sharing, e.g., to protect proprietary or patentable data. +● Explain how the data will be licensed for reuse. See the DCC guide on How to license research data and EUDAT’s data and software licensing wizard.", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Intellectual Property Rights')]}, + {text: "● Describe where the data will be stored and backed up during the course of research activities. This may vary if you are doing fieldwork or working across multiple sites so explain each procedure. +● Identify who will be responsible for backup and how often this will be performed. The use of robust, managed storage with automatic backup, for example, that provided by university IT teams, is preferable. Storing data on laptops, computer hard drives or external storage devices alone is very risky. +● See UK Data Service Guidance on data storage or DataONE Best Practices for storage +● Also consider data security, particularly if your data is sensitive e.g., detailed personal data, politically sensitive information or trade secrets. Note the main risks and how these will be managed. +● Identify any formal standards that you will comply with, e.g., ISO 27001. See the DCC Briefing Paper on Information Security Management -ISO 27000 and UK Data Service guidance on data security", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Storage & Security')]}, + {text: "● How will you share the data e.g. deposit in a data repository, use a secure data service, handle data requests directly or use another mechanism? The methods used will depend on a number of factors such as the type, size, complexity and sensitivity of the data. +● When will you make the data available? Research funders expect timely release. They typically allow embargoes but not prolonged exclusive use. +● Who will be able to use your data? If you need to restricted access to certain communities or apply data sharing agreements, explain why. +● Consider strategies to minimise restrictions on sharing. These may include anonymising or aggregating data, gaining participant consent for data sharing, gaining copyright permissions, and agreeing a limited embargo period. +● How might your data be reused in other contexts? Where there is potential for reuse, you should use standards and formats that facilitate this, and ensure that appropriate metadata is available online so your data can be discovered. Persistent identifiers should be applied so people can reliably and efficiently find your data. They also help you to track citations and reuse.", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Data Sharing')]}, + {text: "● Where will the data be deposited? If you do not propose to use an established repository, the data management plan should demonstrate that the data can be curated effectively beyond the lifetime of the grant. +● It helps to show that you have consulted with the repository to understand their policies and procedures, including any metadata standards. +● An international list of data repositories is available via Re3data and some universities or publishers provide lists of recommendations e.g. PLOS ONE recommended repositories", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Data Repository')]}, + {text: "● Indicate which data are of long-term value and should be shared and/or preserved. +● Outline the plans for data sharing and preservation - how long will the data be retained and where will it be archived? +● Will additional resources be needed to prepare data for deposit or meet any charges from data repositories? See the DCC guide: How to appraise and select research data for curation or DataONE Best Practices: Identifying data with long-term value", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Preservation')]}, + {text: "● Outline the roles and responsibilities for all activities, e.g., data capture, metadata production, data quality, storage and backup, data archiving & data sharing. Individuals should be named where possible. +● For collaborative projects you should explain the coordination of data management responsibilities across partners. +● See UK Data Service guidance on data management roles and responsibilities or DataONE Best Practices: Define roles and assign responsibilities for data management", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Roles & Responsibilities')]}, + {text: "● Carefully consider and justify any resources needed to deliver the plan. These may include storage costs, hardware, staff time, costs of preparing data for deposit and repository charges. +● Outline any relevant technical expertise, support and training that is likely to be required and how it will be acquired. +● If you are not depositing in a data repository, ensure you have appropriate resources and systems in place to share and preserve the data. See UK Data Service guidance on costing data management", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Budget')]}, + {text: "● Consider whether there are any existing procedures that you can base your approach on. If your group/department has local guidelines that you work to, point to them here. +● List any other relevant funder, institutional, departmental or group policies on data management, data sharing and data security. ", + guidance_group: GuidanceGroup.first, + published: true, + themes: [Theme.find_by(title: 'Related Policies')]}, + {text: "Please tell us how much data you plan to collect and what format it will be in once its deposited.", + guidance_group: GuidanceGroup.last, + published: true, + themes: [Theme.find_by(title: 'Data Description')]} +] +guidances.map{ |g| Guidance.create!(g) if Guidance.find_by(text: g[:text]).nil? } + +# Create a default template for the curation centre and one for the example funder +# ------------------------------------------------------- +templates = [ + {title: "My Curation Center's Default Template", + description: "The default template", + published: true, + org: Org.find_by(abbreviation: 'CC'), + is_default: true, + version: 1}, + + {title: "OLD - Department of Testing Award", + published: false, + org: Org.find_by(abbreviation: 'GA'), + is_default: false, + version: 1}, + + {title: "Department of Testing Award", + published: true, + org: Org.find_by(abbreviation: 'GA'), + is_default: false, + version: 2} +] +templates.map{ |t| Template.create!(t) if Template.find_by(title: t[:title]).nil? } + +# Create 2 phases for the funder's template and one for our generic template +# ------------------------------------------------------- +phases = [ + {title: "Generic Data Management Planning Template", + number: 1, + modifiable: false, + template: Template.find_by(title: "My Curation Center's Default Template")}, + + {title: "Detailed Overview", + number: 1, + modifiable: false, + template: Template.find_by(title: "OLD - Department of Testing Award")}, + + {title: "Preliminary Statement of Work", + number: 1, + modifiable: true, + template: Template.find_by(title: "Department of Testing Award")}, + {title: "Detailed Overview", + number: 2, + modifiable: false, + template: Template.find_by(title: "Department of Testing Award")} +] +phases.map{ |p| Phase.create!(p) if Phase.find_by(title: p[:title]).nil? } + +generic_template_phase_1 = Phase.find_by(title: "Generic Data Management Planning Template") +funder_template_phase_1 = Phase.find_by(title: "Preliminary Statement of Work") +funder_template_phase_2 = Phase.find_by(title: "Detailed Overview") + +# Create sections for the 2 templates and their phases +# ------------------------------------------------------- +sections = [ + # Sections for the Generic Template + {title: "Data Collection", + number: 1, + published: true, + modifiable: false, + phase: generic_template_phase_1}, + {title: "Documentation and Metadata", + number: 2, + published: true, + modifiable: false, + phase: generic_template_phase_1}, + {title: "Ethics and Legal Compliance", + number: 3, + published: true, + modifiable: false, + phase: generic_template_phase_1}, + {title: "Storage and Backup", + number: 4, + published: true, + modifiable: false, + phase: generic_template_phase_1}, + {title: "Selection and Preservation", + number: 5, + published: true, + modifiable: false, + phase: generic_template_phase_1}, + {title: "Data Sharing", + number: 6, + published: true, + modifiable: false, + phase: generic_template_phase_1}, + {title: "Responsibilities and Resources", + number: 7, + published: true, + modifiable: false, + phase: generic_template_phase_1}, + + # Section of old version of Funder Template + {title: "Data Collection and Preservation", + number: 1, + published: false, + modifiable: true, + phase: Phase.find_by(title: "Detailed Overview")}, + + # Sections for the Funder Template's Preliminary Phase + {title: "Data Overview", + number: 1, + published: false, + modifiable: true, + phase: funder_template_phase_1}, + {title: "Data Description", + number: 1, + published: false, + modifiable: true, + phase: funder_template_phase_1}, + + # Sections for the Funder Template's Detailed Phase + {title: "Preservation Policy", + number: 1, + published: true, + modifiable: false, + phase: funder_template_phase_2}, + {title: "Data Format and Storage", + number: 1, + published: true, + modifiable: false, + phase: funder_template_phase_2}, + {title: "Collection Process", + number: 1, + published: true, + modifiable: false, + phase: funder_template_phase_2}, + {title: "Ethical Standards", + number: 1, + published: true, + modifiable: false, + phase: funder_template_phase_2}, + {title: "Preservation and Reuse Policies", + number: 1, + published: true, + modifiable: false, + phase: funder_template_phase_2} +] +sections.map{ |s| Section.create!(s) if Section.find_by(title: s[:title]).nil? } + +text_area = QuestionFormat.find_by(title: "Text area") + +# Create questions for the 2 templates and their phases +# ------------------------------------------------------- +questions = [ + # Questions for the Generic Template + {text: "What data will you collect or create?", + number: 1, + section: Section.find_by(title: "Data Collection"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Data Description")]}, + {text: "How will the data be collected or created?", + number: 2, + section: Section.find_by(title: "Data Collection"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Data Collection")]}, + {text: "What documentation and metadata will accompany the data?", + number: 1, + section: Section.find_by(title: "Documentation and Metadata"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Metadata & Documentation")]}, + {text: "How will you manage any ethical issues?", + number: 1, + section: Section.find_by(title: "Ethics and Legal Compliance"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Ethics & Privacy")]}, + {text: "How will you manage copyright and Intellectual Property Rights (IPR) issues?", + number: 2, + section: Section.find_by(title: "Ethics and Legal Compliance"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Intellectual Property Rights")]}, + {text: "How will the data be stored and backed up during the research?", + number: 1, + section: Section.find_by(title: "Storage and Backup"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Storage & Security")]}, + {text: "How will you manage access and security?", + number: 2, + section: Section.find_by(title: "Storage and Backup"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Storage & Security")]}, + {text: "Which data are of long-term value and should be retained, shared, and/or preserved?", + number: 1, + section: Section.find_by(title: "Selection and Preservation"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Preservation")]}, + {text: "What is the long-term preservation plan for the dataset?", + number: 2, + section: Section.find_by(title: "Selection and Preservation"), + question_format: text_area, + modifiable: false}, + {text: "How will you share the data?", + number: 1, + section: Section.find_by(title: "Data Sharing"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Data Sharing")]}, + {text: "Are any restrictions on data sharing required?", + number: 2, + section: Section.find_by(title: "Data Sharing"), + question_format: text_area, + modifiable: false}, + {text: "Who will be responsible for data management?", + number: 1, + section: Section.find_by(title: "Responsibilities and Resources"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Roles & Responsibilities")]}, + {text: "What resources will you require to deliver your plan?", + number: 2, + modifiable: false, + section: Section.find_by(title: "Responsibilities and Resources"), + question_format: text_area}, + + # Questions for old version of Funder Template + {text: "What data will you collect and how will it be obtained?", + number: 1, + modifiable: false, + section: Section.find_by(title: "Data Collection and Preservation"), + question_format: text_area}, + {text: "How will you preserve your data during the project and long-term?", + number: 2, + modifiable: false, + section: Section.find_by(title: "Data Collection and Preservation"), + question_format: text_area}, + + # Questions for the Funder Template's Preliminary Phase + {text: "Provide an overview of the dataset.", + number: 1, + section: Section.find_by(title: "Data Overview"), + question_format: text_area, + modifiable: true, + themes: [Theme.find_by(title: "Data Description")]}, + {text: "What types/formats of data will you collect?", + number: 1, + modifiable: true, + section: Section.find_by(title: "Data Description"), + question_format: text_area, + themes: [Theme.find_by(title: "Data Format")]}, + {text: "How will you store the data and how will it be preserved?", + number: 2, + modifiable: true, + section: Section.find_by(title: "Data Description"), + question_format: text_area, + themes: [Theme.find_by(title: "Data Collection")]}, + + # Questions for the Funder Template's Detailed Phase + {text: "What is your policy for long term access to your dataset?", + number: 1, + section: Section.find_by(title: "Preservation Policy"), + question_format: text_area, + modifiable: false, + default_value: "Please enter your answer here ..." , + themes: [Theme.find_by(title: "Preservation")]}, + {text: "Where will your data be preserved?", + number: 2, + section: Section.find_by(title: "Preservation Policy"), + question_format: QuestionFormat.find_by(title: "Text field"), + modifiable: false, + default_value: "on a server at my institution", + guidance: "Consider where your data will be stored after your research is complete.", + themes: [Theme.find_by(title: "Preservation")]}, + {text: "What types of data will you collect and how will it be stored?", + number: 1, + section: Section.find_by(title: "Data Format and Storage"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Storage & Security"), Theme.find_by(title: 'Data Format')]}, + {text: "Please select the appropriate formats.", + number: 2, + section: Section.find_by(title: "Data Format and Storage"), + question_format: QuestionFormat.find_by(title: "Radio buttons"), + modifiable: false, + themes: [Theme.find_by(title: "Storage & Security"), Theme.find_by(title: 'Data Format')]}, + {text: "Will software accompany your dataset?", + number: 1, + section: Section.find_by(title: "Collection Process"), + question_format: QuestionFormat.find_by(title: "Check box"), + modifiable: false, + themes: [Theme.find_by(title: "Data Collection")]}, + {text: "Where will you store your data during the research period?", + number: 2, + section: Section.find_by(title: "Collection Process"), + question_format: QuestionFormat.find_by(title: "Dropdown"), + modifiable: false, + themes: [Theme.find_by(title: "Data Collection")]}, + {text: "What type(s) of data will you collect?", + number: 3, + section: Section.find_by(title: "Collection Process"), + question_format: QuestionFormat.find_by(title: "Multi select box"), + option_comment_display: true, + modifiable: false, + themes: [Theme.find_by(title: "Data Collection")]}, + {text: "What are your institution's ethical policies?", + number: 1, + section: Section.find_by(title: "Ethical Standards"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Ethics & Privacy")]}, + {text: "When will your data be available for public consumption?", + number: 2, + section: Section.find_by(title: "Ethical Standards"), + question_format: QuestionFormat.find_by(title: "Date"), + modifiable: false, + themes: [Theme.find_by(title: "Ethics & Privacy")]}, + {text: "Tell us about your departmental and institutional policies on reuse and preservation.", + number: 1, + section: Section.find_by(title: "Preservation and Reuse Policies"), + question_format: text_area, + modifiable: false, + themes: [Theme.find_by(title: "Preservation"), Theme.find_by(title: "Data Sharing")]} +] +questions.map{ |q| Question.create!(q) if Question.find_by(text: q[:text]).nil? } + +drop_down_question = Question.find_by(text: "Where will you store your data during the research period?") +multi_select_question = Question.find_by(text: "What type(s) of data will you collect?") +radio_button_question = Question.find_by(text: "Please select the appropriate formats.") + +# Create suggested answers for a few questions +# ------------------------------------------------------- +suggested_answers = [ + {text: "We will preserve it in Dryad or a similar data repository service.", + is_example: true, + org: Org.find_by(abbreviation: 'GA'), + question: Question.find_by(text: "What is your policy for long term access to your dataset?")}, + {text: "We recommend that you identify the type(s) of content as well as the type of file(s) involved", + is_example: false, + org: Org.find_by(abbreviation: 'GA'), + question: Question.find_by(text: "What types of data will you collect and how will it be stored?")}, +] +suggested_answers.map{ |s| SuggestedAnswer.create!(s) if SuggestedAnswer.find_by(text: s[:text]).nil? } + +# Create options for the dropdown, multi-select and radio buttons +# ------------------------------------------------------- +question_options = [ + {text: "csv files", + number: 1, + question: radio_button_question, + is_default: false}, + {text: "database (e.g. mysql, redis)", + number: 2, + question: radio_button_question, + is_default: false}, + {text: "archive files (e.g. tar, zip)", + number: 3, + question: radio_button_question, + is_default: false}, + + {text: "local hard drive", + number: 1, + question: drop_down_question, + is_default: true}, + {text: "personal cloud storage", + number: 2, + question: drop_down_question, + is_default: false}, + {text: "institutional servers", + number: 3, + question: drop_down_question, + is_default: false}, + + {text: "statistical", + number: 1, + question: multi_select_question, + is_default: false}, + {text: "image/video", + number: 2, + question: multi_select_question, + is_default: false}, + {text: "geographical", + number: 3, + question: multi_select_question, + is_default: false}, + {text: "other", + number: 4, + question: multi_select_question, + is_default: false} +] +question_options.map{ |q| QuestionOption.create!(q) if QuestionOption.find_by(text: q[:text]).nil? } + +# Create plans +# ------------------------------------------------------- +=begin +plans = [ + {title: "Sample plan", + template: Template.find_by(title: "Department of Testing Award"), + grant_number: "FUNDER-GRANT-123", + identifier: "987654321", + description: "This is a sample plan based on a funder template", + principal_investigator: "John Doe", + principal_investigator_identifier: "ORCID: 12346-000-1234", + data_contact: "john.doe@example.com", + funder_name: "Example Government Agency", + visibility: 0} +] +plans.map{ |p| Plan.create!(p) if Plan.find_by(title: "Sample plan").nil? } + +plan = Plan.find_by(title: "Sample plan") +user = User.find_by(email: "org_user@example.com") + +answers = [ + {text: "We will collect data from various sources and create our own analysis.", + plan: plan, + user: user, + question: Question.find_by(text: "Provide an overview of the dataset.")}, + {text: "We will primarily collect images and video from our telescope and other instruments", + plan: plan, + user: user, + question: Question.find_by(text: "What types/formats of data will you collect?")}, + {text: "We will store the data on our departmental server and then move it to a commercial data repository afterward.", + plan: plan, + user: user, + question: Question.find_by(text: "How will you store the data and how will it be preserved?")}, + + {text: "We want people to be able to access it. ", + plan: plan, + user: user, + question: Question.find_by(text: "What is your policy for long term access to your dataset?")}, + {plan: plan, + user: user, + question: drop_down_question, + question_options: [QuestionOption.find_by(text: "institutional servers")]}, + {plan: plan, + user: user, + question: multi_select_question, + question_options: [QuestionOption.find_by(text: "image/video"), + QuestionOption.find_by(text: "other")]}, + {plan: plan, + user: user, + question: radio_button_question, + question_options: [QuestionOption.find_by(text: "archive files (e.g. tar, zip)"), + QuestionOption.find_by(text: "csv files")]}, + {text: "Yes", + plan: plan, + user: user, + question: Question.find_by(text: "Will software accompany your dataset?")}, + {text: "On a local server", + plan: plan, + user: user, + question: Question.find_by(text: "Where will you store your data during the research period?")}, + {text: "2018-05-01 00:00:01", + plan: plan, + user: user, + question: Question.find_by(text: "When will your data be available for public consumption?")} +] +answers.map{ |a| Answer.create!(a) if Answer.where(plan: a[:plan], user: a[:user], question: a[:question]).empty? } +=end \ No newline at end of file diff --git a/test/unit/dmptemplate_test.rb b/test/unit/dmptemplate_test.rb deleted file mode 100644 index c17a2ba..0000000 --- a/test/unit/dmptemplate_test.rb +++ /dev/null @@ -1,347 +0,0 @@ -require 'test_helper' - -class DmptemplateTest < ActiveSupport::TestCase - - setup do - @template = Dmptemplate.first - - @organisation = Organisation.first - end - - def settings(extras = {}) - {margin: (@margin || { top: 10, bottom: 10, left: 10, right: 10 }), - font_face: (@font_face || Settings::Dmptemplate::VALID_FONT_FACES.first), - font_size: (@font_size || 11) - }.merge(extras) - end - - def default_formatting - Settings::Dmptemplate::DEFAULT_SETTINGS[:formatting] - end - - # --------------------------------------------------- - test "required fields are required" do - assert_not Dmptemplate.new.valid? - assert_not Dmptemplate.new(title: 'Testing tmeplate').valid?, "expected the 'organisation' field to be required" - assert_not Dmptemplate.new(organisation: @organisation).valid?, "expected the 'title' field to be required" - - # Ensure the bar minimum and complete versions are valid - a = Dmptemplate.new(organisation: @organisation, title: 'Testing tmeplate') - assert a.valid?, "expected the 'title' and 'organisation' fields to be enough to create an Dmptemplate! - #{a.errors.map{|f, m| f.to_s + ' ' + m}.join(', ')}" - end - - # --------------------------------------------------- - test "to_s method returns the title" do - assert_equal @template.title, @template.to_s - end - - - # ---------- settings ---------- - # --------------------------------------------------- - test "settings should use defaults if none are defined" do - assert(!@template.settings(:export).value?) - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "settings should use defined valid settings" do - @template.settings(:export).formatting = settings - @template.save! - - assert(@template.settings(:export).value?) - assert_equal(settings, @template.settings(:export).formatting) - assert_not_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "setting negative margin should not be valid" do - @margin = { top: -10, bottom: 10, left: 10, right: 10 } - - @template.settings(:export).formatting = settings - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.negative_margin'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "setting unknown margin should not be valid" do - @margin = { top: 10, bottom: 10, left: 10, right: 10, top_left: 10 } - - @template.settings(:export).formatting = settings - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.unknown_margin'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "setting negative font-size should not be valid" do - @font_size = -11 - - @template.settings(:export).formatting = settings - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.invalid_font_size'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "setting unknown key should not be valid" do - @template.settings(:export).formatting = settings(foo: :bar) - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.unknown_key'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "not setting font_face should not be valid" do - @template.settings(:export).formatting = settings.reject {|k,v| k == :font_face } - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.missing_key'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "not setting font_size should not be valid" do - @template.settings(:export).formatting = settings.reject {|k,v| k == :font_size } - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.missing_key'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "not setting margin should not be valid" do - @template.settings(:export).formatting = settings.reject {|k,v| k == :margin } - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.missing_key'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "setting non-hash as margin should not be valid" do - @margin = :foo - - @template.settings(:export).formatting = settings - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.invalid_margin'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "setting non-integer as font_size should not be valid" do - @font_size = "foo" - - @template.settings(:export).formatting = settings - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.invalid_font_size'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "setting non-string as font_face should not be valid" do - @font_face = 1 - - @template.settings(:export).formatting = settings - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.invalid_font_face'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - - assert_equal(default_formatting, @template.settings(:export).formatting) - end - - # --------------------------------------------------- - test "setting unknown string as font_face should not be valid" do - @font_face = 'Monaco, Monospace, Sans-Serif' - - @template.settings(:export).formatting = settings - - assert(!@template.valid?) - assert(!@template.save) - - assert_equal(I18n.t('helpers.settings.plans.errors.invalid_font_face'), - @template.errors.messages[:'setting_objects.formatting'].first) - - @template.reload - - assert_equal(default_formatting, @template.settings(:export).formatting) - end - -<<<<<<< HEAD -======= - # ---------- templates_org_type ---------- - test "templates_org_type returns all published" do - OrganisationType.find_each do |org_type| - result_templates = Dmptemplate.templates_org_type(org_type.name) - my_list = Array.new - org_type.organisations.each do |org| - my_list += org.dmptemplates - end - my_list.each do |template| - if template.published - assert_includes(result_templates, template, "Template: #{template.title}} of type #{org_type.name}, not returned by templates_org_type") - end - end - end - end - - # ---------- funders_templates ---------- - test "funders_templates returns all funder organisation templates" do - result_templates = Dmptemplate.funders_templates - funder_templates = OrganisationType.first.organisations do |org| - org.dmptemplates.each do |template| - assert_includes( result_templates, template, "Funder Template: #{template.title} not included in result of funders_templates") - end - end - end - - # ---------- own_institutional_templates ---------- - test "own_institutional_templates returns all templates belonging to given org_id" do - Org.find_each do |org| - result_templates = Dmptemplate.own_institutional_templates(org.id) - org.dmptemplates.each do |template| - assert_includes(result_templates, template, "Template: #{template.title} not returned by own_institutional_templates") - end - end - end - - # ---------- funders_and_own_templates ---------- - test "funders_and_own_templates returns all funder and own given org_id templates" do - Org.find_each do |org| - result_templates = Dmptemplate.funders_and_own_templates(org.id) - org.dmptemplates.each do |template| - assert_includes(result_templates, template, "Template #{template.title} not returned by funders and own templates") - end - end - funder_templates = OrganisationType.first.organisations do |org| - org.dmptemplates.each do |template| - assert_includes( result_templates, template, "Funder Template: #{template.title} not included in result of funders_and_own_templates") - end - end - end - - # ---------- org_type ---------- - test "org_type properly returns the name of the template's organisation's type" do - Dmptemplate.find_each do |template| - assert_equal( template.org_type, template.organisation.organisation_type.name, "Template: #{template.title} returned #{template.org_type}, instead of #{template.organisation.organisation_type.name}") - end - end - ->>>>>>> final_schema - # ---------- has_customisations? ---------- - test "has_customisations? correctly identifies if a given org has customised the template" do - # TODO: Impliment after understanding has_customisations - - end - - # ---------- has_published_versions? ---------- - test "has_published_versions? correctly identifies published versions" do - Dmptemplate.find_each do |template| - template.phases.each do |phase| - unless phase.latest_published_version.nil? - assert(template.has_published_versions? , "there was a published version of phase: #{phase.title}") - end - end - end - end - - # --------------------------------------------------- - test "can CRUD Template" do - tmplt = Dmptemplate.create(organisation: @organisation, title: 'Testing tmeplate') - assert_not tmplt.id.nil?, "was expecting to be able to create a new Dmptemplate!" - - tmplt.description = 'Testing an update' - tmplt.save! - tmplt.reload - assert_equal 'Testing an update', tmplt.description, "Was expecting to be able to update the description of the Dmptemplate!" - - assert tmplt.destroy!, "Was unable to delete the Dmptemplate!" - end - - # --------------------------------------------------- - test "can manage has_many relationship with Phase" do - phase = Phase.new(title: 'Test Phase', number: 2) - verify_has_many_relationship(@template, phase, @template.phases.count) - end - - # --------------------------------------------------- - test "can manage has_many relationship with Project" do - project = Project.new(title: 'Test Project', organisation: @organisation) - verify_has_many_relationship(@template, project, @template.projects.count) - end - - # --------------------------------------------------- - test "can manage has_many relationship with GuidanceGroup" do - grp = GuidanceGroup.new(name: 'Test Group', organisation: @organisation) - verify_has_many_relationship(@template, grp, @template.guidance_groups.count) - end - - # --------------------------------------------------- - test "can manage belongs_to relationship with Organisation" do - verify_belongs_to_relationship(@template, @organisation) - end - -end diff --git a/test/unit/template_test.rb b/test/unit/template_test.rb new file mode 100644 index 0000000..0db44c4 --- /dev/null +++ b/test/unit/template_test.rb @@ -0,0 +1,347 @@ +require 'test_helper' + +class TemplateTest < ActiveSupport::TestCase + + setup do + @template = Dmptemplate.first + + @organisation = Organisation.first + end + + def settings(extras = {}) + {margin: (@margin || { top: 10, bottom: 10, left: 10, right: 10 }), + font_face: (@font_face || Settings::Dmptemplate::VALID_FONT_FACES.first), + font_size: (@font_size || 11) + }.merge(extras) + end + + def default_formatting + Settings::Dmptemplate::DEFAULT_SETTINGS[:formatting] + end + + # --------------------------------------------------- + test "required fields are required" do + assert_not Dmptemplate.new.valid? + assert_not Dmptemplate.new(title: 'Testing tmeplate').valid?, "expected the 'organisation' field to be required" + assert_not Dmptemplate.new(organisation: @organisation).valid?, "expected the 'title' field to be required" + + # Ensure the bar minimum and complete versions are valid + a = Dmptemplate.new(organisation: @organisation, title: 'Testing tmeplate') + assert a.valid?, "expected the 'title' and 'organisation' fields to be enough to create an Dmptemplate! - #{a.errors.map{|f, m| f.to_s + ' ' + m}.join(', ')}" + end + + # --------------------------------------------------- + test "to_s method returns the title" do + assert_equal @template.title, @template.to_s + end + + + # ---------- settings ---------- + # --------------------------------------------------- + test "settings should use defaults if none are defined" do + assert(!@template.settings(:export).value?) + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "settings should use defined valid settings" do + @template.settings(:export).formatting = settings + @template.save! + + assert(@template.settings(:export).value?) + assert_equal(settings, @template.settings(:export).formatting) + assert_not_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "setting negative margin should not be valid" do + @margin = { top: -10, bottom: 10, left: 10, right: 10 } + + @template.settings(:export).formatting = settings + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.negative_margin'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "setting unknown margin should not be valid" do + @margin = { top: 10, bottom: 10, left: 10, right: 10, top_left: 10 } + + @template.settings(:export).formatting = settings + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.unknown_margin'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "setting negative font-size should not be valid" do + @font_size = -11 + + @template.settings(:export).formatting = settings + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.invalid_font_size'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "setting unknown key should not be valid" do + @template.settings(:export).formatting = settings(foo: :bar) + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.unknown_key'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "not setting font_face should not be valid" do + @template.settings(:export).formatting = settings.reject {|k,v| k == :font_face } + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.missing_key'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "not setting font_size should not be valid" do + @template.settings(:export).formatting = settings.reject {|k,v| k == :font_size } + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.missing_key'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "not setting margin should not be valid" do + @template.settings(:export).formatting = settings.reject {|k,v| k == :margin } + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.missing_key'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "setting non-hash as margin should not be valid" do + @margin = :foo + + @template.settings(:export).formatting = settings + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.invalid_margin'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "setting non-integer as font_size should not be valid" do + @font_size = "foo" + + @template.settings(:export).formatting = settings + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.invalid_font_size'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "setting non-string as font_face should not be valid" do + @font_face = 1 + + @template.settings(:export).formatting = settings + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.invalid_font_face'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + + assert_equal(default_formatting, @template.settings(:export).formatting) + end + + # --------------------------------------------------- + test "setting unknown string as font_face should not be valid" do + @font_face = 'Monaco, Monospace, Sans-Serif' + + @template.settings(:export).formatting = settings + + assert(!@template.valid?) + assert(!@template.save) + + assert_equal(I18n.t('helpers.settings.plans.errors.invalid_font_face'), + @template.errors.messages[:'setting_objects.formatting'].first) + + @template.reload + + assert_equal(default_formatting, @template.settings(:export).formatting) + end + +<<<<<<< HEAD +======= + # ---------- templates_org_type ---------- + test "templates_org_type returns all published" do + OrganisationType.find_each do |org_type| + result_templates = Dmptemplate.templates_org_type(org_type.name) + my_list = Array.new + org_type.organisations.each do |org| + my_list += org.dmptemplates + end + my_list.each do |template| + if template.published + assert_includes(result_templates, template, "Template: #{template.title}} of type #{org_type.name}, not returned by templates_org_type") + end + end + end + end + + # ---------- funders_templates ---------- + test "funders_templates returns all funder organisation templates" do + result_templates = Dmptemplate.funders_templates + funder_templates = OrganisationType.first.organisations do |org| + org.dmptemplates.each do |template| + assert_includes( result_templates, template, "Funder Template: #{template.title} not included in result of funders_templates") + end + end + end + + # ---------- own_institutional_templates ---------- + test "own_institutional_templates returns all templates belonging to given org_id" do + Org.find_each do |org| + result_templates = Dmptemplate.own_institutional_templates(org.id) + org.dmptemplates.each do |template| + assert_includes(result_templates, template, "Template: #{template.title} not returned by own_institutional_templates") + end + end + end + + # ---------- funders_and_own_templates ---------- + test "funders_and_own_templates returns all funder and own given org_id templates" do + Org.find_each do |org| + result_templates = Dmptemplate.funders_and_own_templates(org.id) + org.dmptemplates.each do |template| + assert_includes(result_templates, template, "Template #{template.title} not returned by funders and own templates") + end + end + funder_templates = OrganisationType.first.organisations do |org| + org.dmptemplates.each do |template| + assert_includes( result_templates, template, "Funder Template: #{template.title} not included in result of funders_and_own_templates") + end + end + end + + # ---------- org_type ---------- + test "org_type properly returns the name of the template's organisation's type" do + Dmptemplate.find_each do |template| + assert_equal( template.org_type, template.organisation.organisation_type.name, "Template: #{template.title} returned #{template.org_type}, instead of #{template.organisation.organisation_type.name}") + end + end + +>>>>>>> final_schema + # ---------- has_customisations? ---------- + test "has_customisations? correctly identifies if a given org has customised the template" do + # TODO: Impliment after understanding has_customisations + + end + + # ---------- has_published_versions? ---------- + test "has_published_versions? correctly identifies published versions" do + Dmptemplate.find_each do |template| + template.phases.each do |phase| + unless phase.latest_published_version.nil? + assert(template.has_published_versions? , "there was a published version of phase: #{phase.title}") + end + end + end + end + + # --------------------------------------------------- + test "can CRUD Template" do + tmplt = Dmptemplate.create(organisation: @organisation, title: 'Testing tmeplate') + assert_not tmplt.id.nil?, "was expecting to be able to create a new Dmptemplate!" + + tmplt.description = 'Testing an update' + tmplt.save! + tmplt.reload + assert_equal 'Testing an update', tmplt.description, "Was expecting to be able to update the description of the Dmptemplate!" + + assert tmplt.destroy!, "Was unable to delete the Dmptemplate!" + end + + # --------------------------------------------------- + test "can manage has_many relationship with Phase" do + phase = Phase.new(title: 'Test Phase', number: 2) + verify_has_many_relationship(@template, phase, @template.phases.count) + end + + # --------------------------------------------------- + test "can manage has_many relationship with Project" do + project = Project.new(title: 'Test Project', organisation: @organisation) + verify_has_many_relationship(@template, project, @template.projects.count) + end + + # --------------------------------------------------- + test "can manage has_many relationship with GuidanceGroup" do + grp = GuidanceGroup.new(name: 'Test Group', organisation: @organisation) + verify_has_many_relationship(@template, grp, @template.guidance_groups.count) + end + + # --------------------------------------------------- + test "can manage belongs_to relationship with Organisation" do + verify_belongs_to_relationship(@template, @organisation) + end + +end