answers-core 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Rakefile +6 -0
- data/answers-core.gemspec +30 -0
- data/app/assets/fonts/answers/League_Gothic-webfont.eot +0 -0
- data/app/assets/fonts/answers/League_Gothic-webfont.svg +230 -0
- data/app/assets/fonts/answers/League_Gothic-webfont.ttf +0 -0
- data/app/assets/fonts/answers/League_Gothic-webfont.woff +0 -0
- data/app/assets/images/OaklandCityTree.png +0 -0
- data/app/assets/images/background_image.jpg +0 -0
- data/app/assets/images/background_pattern.png +0 -0
- data/app/assets/images/beta.png +0 -0
- data/app/assets/images/bg_transparent.png +0 -0
- data/app/assets/images/border.png +0 -0
- data/app/assets/images/brigade.png +0 -0
- data/app/assets/images/cfa.png +0 -0
- data/app/assets/images/cfa_logo.png +0 -0
- data/app/assets/images/cfa_logo_footer.png +0 -0
- data/app/assets/images/favicon.ico +0 -0
- data/app/assets/images/forest.jpeg +0 -0
- data/app/assets/images/getting_started_btn.png +0 -0
- data/app/assets/images/govuk.png +0 -0
- data/app/assets/images/openoaklandlogo.png +0 -0
- data/app/assets/images/quick_answers_icon.png +0 -0
- data/app/assets/images/quick_answers_icon_small.png +0 -0
- data/app/assets/images/searchIcon.png +0 -0
- data/app/assets/images/wmd-buttons.png +0 -0
- data/app/assets/images/yellow_bg.png +0 -0
- data/app/assets/javascripts/answers.js +19 -0
- data/app/assets/javascripts/answers/Markdown.Extra.js +304 -0
- data/app/assets/javascripts/answers/active_admin.js +62 -0
- data/app/assets/javascripts/answers/pagedown/LICENSE.txt +32 -0
- data/app/assets/javascripts/answers/pagedown/Markdown.Converter.js +1332 -0
- data/app/assets/javascripts/answers/pagedown/Markdown.Editor.js +2212 -0
- data/app/assets/javascripts/answers/pagedown/Markdown.Sanitizer.js +108 -0
- data/app/assets/javascripts/answers/pagedown/README.txt +0 -0
- data/app/assets/javascripts/answers/pagedown/demo/browser/demo.css +120 -0
- data/app/assets/javascripts/answers/pagedown/demo/browser/demo.html +83 -0
- data/app/assets/javascripts/answers/pagedown/demo/node/demo.js +44 -0
- data/app/assets/javascripts/answers/pagedown/local/Markdown.local.fr.js +43 -0
- data/app/assets/javascripts/answers/pagedown/node-pagedown.js +2 -0
- data/app/assets/javascripts/answers/pagedown/package.json +12 -0
- data/app/assets/javascripts/answers/pagedown/resources/wmd-buttons.psd +0 -0
- data/app/assets/javascripts/answers/pagedown/wmd-buttons.png +0 -0
- data/app/assets/javascripts/answers/skip_nav.js +8 -0
- data/app/assets/stylesheets/answers/active_admin.css.scss +17 -0
- data/app/assets/stylesheets/answers/active_admin_custom.css.scss +35 -0
- data/app/assets/stylesheets/answers/formatting.css +82 -0
- data/app/assets/stylesheets/answers/mobile.css +149 -0
- data/app/assets/stylesheets/answers/tags.css.scss +3 -0
- data/app/assets/stylesheets/answers/theme.css +916 -0
- data/app/controllers/answers/answers_controller.rb +26 -0
- data/app/controllers/answers/api/v1/answers_controller.rb +38 -0
- data/app/controllers/answers/api/v1/api_controller.rb +13 -0
- data/app/controllers/answers/api/v1/questions_controller.rb +39 -0
- data/app/controllers/answers/api/v1/taggings_controller.rb +46 -0
- data/app/controllers/answers/api/v1/tags_controller.rb +38 -0
- data/app/controllers/answers/application_controller.rb +27 -0
- data/app/controllers/answers/home_controller.rb +17 -0
- data/app/controllers/answers/questions_controller.rb +33 -0
- data/app/controllers/answers/search_controller.rb +22 -0
- data/app/controllers/answers/tags_controller.rb +36 -0
- data/app/helpers/answers/tags_helper.rb +7 -0
- data/app/models/.gitkeep +0 -0
- data/app/models/answers/ability.rb +28 -0
- data/app/models/answers/administrator.rb +5 -0
- data/app/models/answers/answer.rb +6 -0
- data/app/models/answers/api/v1/api_user.rb +5 -0
- data/app/models/answers/question.rb +31 -0
- data/app/models/answers/user.rb +30 -0
- data/app/views/answers/admin/contacts/_article.html.erb +0 -0
- data/app/views/answers/admin/dashboard/_dashboard.html.erb +5 -0
- data/app/views/answers/admin/guide_steps/_form.html.erb +17 -0
- data/app/views/answers/api/v1/answers/_answer.json.jbuilder +2 -0
- data/app/views/answers/api/v1/answers/index.json.jbuilder +1 -0
- data/app/views/answers/api/v1/answers/show.json.jbuilder +1 -0
- data/app/views/answers/api/v1/questions/_question.json.jbuilder +2 -0
- data/app/views/answers/api/v1/questions/index.json.jbuilder +1 -0
- data/app/views/answers/api/v1/questions/show.json.jbuilder +1 -0
- data/app/views/answers/api/v1/taggings/_tagging.json.jbuilder +3 -0
- data/app/views/answers/api/v1/taggings/index.json.jbuilder +1 -0
- data/app/views/answers/api/v1/taggings/show.json.jbuilder +1 -0
- data/app/views/answers/api/v1/tags/_tag.json.jbuilder +2 -0
- data/app/views/answers/api/v1/tags/index.json.jbuilder +1 -0
- data/app/views/answers/api/v1/tags/show.json.jbuilder +1 -0
- data/app/views/answers/devise/confirmations/new.html.erb +12 -0
- data/app/views/answers/devise/mailer/confirmation_instructions.html.erb +5 -0
- data/app/views/answers/devise/mailer/reset_password_instructions.html.erb +8 -0
- data/app/views/answers/devise/mailer/unlock_instructions.html.erb +7 -0
- data/app/views/answers/devise/passwords/edit.html.erb +24 -0
- data/app/views/answers/devise/passwords/new.html.erb +20 -0
- data/app/views/answers/devise/registrations/edit.html.erb +25 -0
- data/app/views/answers/devise/registrations/new.html.erb +18 -0
- data/app/views/answers/devise/sessions/new.html.erb +25 -0
- data/app/views/answers/devise/shared/_links.erb +25 -0
- data/app/views/answers/devise/unlocks/new.html.erb +12 -0
- data/app/views/answers/home/_article.html.erb +3 -0
- data/app/views/answers/home/_category.html.erb +8 -0
- data/app/views/answers/home/about.html.erb +72 -0
- data/app/views/answers/home/index.html.erb +44 -0
- data/app/views/answers/questions/index.html.erb +21 -0
- data/app/views/answers/questions/show.html.erb +31 -0
- data/app/views/answers/search/index.html.erb +32 -0
- data/app/views/answers/shared/_articles_sidebar.html.erb +22 -0
- data/app/views/answers/shared/_autocomplete.html.erb +8 -0
- data/app/views/answers/shared/_categories_sidebar.html.erb +12 -0
- data/app/views/answers/shared/_search_form.html.erb +4 -0
- data/app/views/answers/shared/admin/_administration.html.erb +38 -0
- data/app/views/answers/shared/admin/_article_actions.html.erb +86 -0
- data/app/views/answers/shared/admin/_article_content.html.erb +27 -0
- data/app/views/answers/shared/admin/_article_details.html.erb +11 -0
- data/app/views/answers/shared/admin/_article_form.html.erb +20 -0
- data/app/views/answers/shared/admin/_author_pic.html.erb +0 -0
- data/app/views/answers/tags/index.html.erb +34 -0
- data/app/views/answers/tags/show.html.erb +31 -0
- data/app/views/layouts/answers/application.html.erb +97 -0
- data/config.ru +5 -0
- data/config/initializers/active_admin.rb +245 -0
- data/config/initializers/devise.rb +228 -0
- data/config/locales/devise.en.yml +57 -0
- data/config/locales/en.yml +129 -0
- data/config/routes.rb +22 -0
- data/config/secrets.yml +68 -0
- data/db/migrate/20140911060606_answers_up.rb +79 -0
- data/lib/answers-core.rb +1 -0
- data/lib/answers.rb +175 -0
- data/lib/answers/admin/answer.rb +29 -0
- data/lib/answers/admin/dashboard.rb +75 -0
- data/lib/answers/admin/question.rb +57 -0
- data/lib/answers/admin/tag.rb +12 -0
- data/lib/answers/admin/users.rb +65 -0
- data/lib/answers/core.rb +25 -0
- data/lib/answers/core/configuration.rb +90 -0
- data/lib/answers/core/engine.rb +116 -0
- data/lib/answers/engine.rb +62 -0
- data/lib/answers/errors.rb +13 -0
- data/lib/answers/plugin.rb +75 -0
- data/lib/answers/plugins.rb +73 -0
- data/lib/answers/version.rb +16 -0
- data/lib/api_client.rb +20 -0
- data/lib/assets/.gitkeep +0 -0
- data/lib/assets/eng_stop.csv +1 -0
- data/lib/generators/answers/clash_keywords.yml +3 -0
- data/lib/generators/answers/cms/cms_generator.rb +314 -0
- data/lib/generators/answers/cms/templates/.gitignore +91 -0
- data/lib/generators/answers/cms/templates/app/decorators/controllers/answers/.keep +0 -0
- data/lib/generators/answers/cms/templates/app/decorators/models/answers/.keep +0 -0
- data/lib/generators/answers/cms/templates/app/views/sitemap/index.xml.builder +15 -0
- data/lib/generators/answers/cms/templates/config/database.yml.mysql +20 -0
- data/lib/generators/answers/cms/templates/config/database.yml.postgresql +58 -0
- data/lib/generators/answers/cms/templates/config/database.yml.sqlite3 +18 -0
- data/lib/generators/answers/core/core_generator.rb +10 -0
- data/lib/generators/answers/core/templates/config/initializers/answers/core.rb.erb +35 -0
- data/lib/generators/answers/dummy/dummy_generator.rb +86 -0
- data/lib/generators/answers/dummy/templates/rails/Rakefile +7 -0
- data/lib/generators/answers/dummy/templates/rails/application.js +3 -0
- data/lib/generators/answers/dummy/templates/rails/application.rb.erb +12 -0
- data/lib/generators/answers/dummy/templates/rails/boot.rb.erb +6 -0
- data/lib/generators/answers/dummy/templates/rails/database.yml +34 -0
- data/lib/generators/answers/dummy/templates/rails/routes.rb +3 -0
- data/lib/generators/answers/engine/USAGE +24 -0
- data/lib/generators/answers/engine/engine_generator.rb +44 -0
- data/lib/generators/answers/engine/templates/.gitignore +2 -0
- data/lib/generators/answers/engine/templates/Gemfile +42 -0
- data/lib/generators/answers/engine/templates/Rakefile +19 -0
- data/lib/generators/answers/engine/templates/answers-extension_plural_name.gemspec +19 -0
- data/lib/generators/answers/engine/templates/app/controllers/answers/namespace/admin/plural_name_controller.rb.erb +14 -0
- data/lib/generators/answers/engine/templates/app/controllers/answers/namespace/plural_name_controller.rb.erb +34 -0
- data/lib/generators/answers/engine/templates/app/models/answers/namespace/singular_name.rb.erb +37 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/admin/plural_name/_actions.html.erb +25 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/admin/plural_name/_form.html.erb +65 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/admin/plural_name/_plural_name.html.erb +2 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/admin/plural_name/_records.html.erb +16 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/admin/plural_name/_singular_name.html.erb +33 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/admin/plural_name/_sortable_list.html.erb +5 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/admin/plural_name/edit.html.erb +1 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/admin/plural_name/index.html.erb +7 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/admin/plural_name/new.html.erb +1 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/plural_name/index.html.erb +11 -0
- data/lib/generators/answers/engine/templates/app/views/answers/namespace/plural_name/show.html.erb +39 -0
- data/lib/generators/answers/engine/templates/config/locales/cs.yml +28 -0
- data/lib/generators/answers/engine/templates/config/locales/en.yml +28 -0
- data/lib/generators/answers/engine/templates/config/locales/es.yml +29 -0
- data/lib/generators/answers/engine/templates/config/locales/fr.yml +28 -0
- data/lib/generators/answers/engine/templates/config/locales/it.yml +28 -0
- data/lib/generators/answers/engine/templates/config/locales/nb.yml +28 -0
- data/lib/generators/answers/engine/templates/config/locales/nl.yml +28 -0
- data/lib/generators/answers/engine/templates/config/locales/sk.yml +28 -0
- data/lib/generators/answers/engine/templates/config/locales/tr.yml +28 -0
- data/lib/generators/answers/engine/templates/config/locales/zh-CN.yml +30 -0
- data/lib/generators/answers/engine/templates/config/routes.rb.erb +19 -0
- data/lib/generators/answers/engine/templates/db/migrate/1_create_namespace_plural_name.rb.erb +39 -0
- data/lib/generators/answers/engine/templates/db/seeds.rb.erb +21 -0
- data/lib/generators/answers/engine/templates/lib/answers-extension_plural_name.rb.erb +1 -0
- data/lib/generators/answers/engine/templates/lib/answers/plural_name.rb.erb +21 -0
- data/lib/generators/answers/engine/templates/lib/answers/plural_name/engine.rb.erb +23 -0
- data/lib/generators/answers/engine/templates/lib/generators/answers/extension_plural_name_generator.rb.erb +19 -0
- data/lib/generators/answers/engine/templates/lib/tasks/answers/extension_plural_name.rake +13 -0
- data/lib/generators/answers/engine/templates/readme.md +10 -0
- data/lib/generators/answers/engine/templates/script/rails +10 -0
- data/lib/generators/answers/engine/templates/spec/features/answers/namespace/admin/plural_name_spec.rb.erb +200 -0
- data/lib/generators/answers/engine/templates/spec/models/answers/namespace/singular_name_spec.rb.erb +20 -0
- data/lib/generators/answers/engine/templates/spec/spec_helper.rb +31 -0
- data/lib/generators/answers/engine/templates/spec/support/factories/answers/plural_name.rb.erb +7 -0
- data/lib/generators/answers/engine/templates/tasks/rspec.rake +6 -0
- data/lib/generators/answers/engine/templates/tasks/testing.rake +8 -0
- data/lib/generators/answers/generator.rb +292 -0
- data/lib/markdownifier.rb +11 -0
- data/log/.gitkeep +0 -0
- data/log/development.log +12870 -0
- data/log/newrelic_agent.log +1339 -0
- data/log/test.log +233181 -0
- data/public/404.html +25 -0
- data/public/422.html +25 -0
- data/public/500.html +24 -0
- data/public/favicon.ico +0 -0
- data/public/robots.txt +5 -0
- data/script/delayed_job +5 -0
- data/spec/controllers/answers_controller_spec.rb +55 -0
- data/spec/controllers/api/v1/answers_controller_spec.rb +144 -0
- data/spec/controllers/api/v1/questions_controller_spec.rb +144 -0
- data/spec/controllers/api/v1/taggings_controller_spec.rb +126 -0
- data/spec/controllers/api/v1/tags_controller_spec.rb +126 -0
- data/spec/controllers/home_controller_spec.rb +60 -0
- data/spec/controllers/questions_controller_spec.rb +55 -0
- data/spec/controllers/tags_controller_spec.rb +42 -0
- data/spec/factories/answers.rb +10 -0
- data/spec/factories/questions.rb +8 -0
- data/spec/factories/tags.rb +8 -0
- data/spec/factories/user.rb +32 -0
- data/spec/features/admin_dashboard_spec.rb +53 -0
- data/spec/features/admin_user_spec.rb +61 -0
- data/spec/features/searches_spec.rb +101 -0
- data/spec/fixtures/Article/_before_validation/sets_access_count_if_nil.yml +223 -0
- data/spec/fixtures/Article/_delete_orphaned_keywords/updating_an_article/destroys_orphaned_keywords_associated.yml +223 -0
- data/spec/fixtures/Article/_delete_orphaned_keywords/when_deleting_an_article/destroys_all_keywords_associated.yml +223 -0
- data/spec/fixtures/Article/_find_by_friendly_id/when_an_article_does_not_exist/does_not_raise_an_exception.yml +223 -0
- data/spec/fixtures/Article/_find_by_friendly_id/when_an_article_exists/returns_the_corresponding_article.yml +223 -0
- data/spec/fixtures/Article/_find_by_type/excludes_articles_not_matching_specified_type.yml +223 -0
- data/spec/fixtures/Article/_find_by_type/returns_articles_matching_type.yml +223 -0
- data/spec/fixtures/Article/_hits/before_an_article_has_been_viewed/has_zero_hits.yml +223 -0
- data/spec/fixtures/Article/_hits/returns_number_of_views/has_seven_views.yml +223 -0
- data/spec/fixtures/Article/_indexable_/returns_false_if_article_is_not_published.yml +223 -0
- data/spec/fixtures/Article/_indexable_/returns_true_if_article_is_published.yml +223 -0
- data/spec/fixtures/Article/_legacy_/returns_true_if_render_markdown_is_false.yml +223 -0
- data/spec/fixtures/Article/_qm_after_create/creates_wordcounts_for_relevant_keywords.yml +223 -0
- data/spec/fixtures/Article/_record_hit/viewing_an_article/increases_hit_by_one.yml +223 -0
- data/spec/fixtures/Article/_related/has_no_related_articles/.yml +223 -0
- data/spec/fixtures/Article/_related/has_related_articles/.yml +223 -0
- data/spec/fixtures/Article/_remove_stop_words/removes_common_english_words_from_the_string.yml +223 -0
- data/spec/fixtures/Article/_search/_search_titles/query_is_present_in_the_title/.yml +223 -0
- data/spec/fixtures/Article/_search/_search_titles/returns_an_empty_array_when_the_search_term_is_present_in_an_article_but_not_the_title.yml +223 -0
- data/spec/fixtures/Article/_search/matches_articles_in_the_database.yml +223 -0
- data/spec/fixtures/Article/_search/query_does_not_match_anything_in_the_database/returns_an_empty_array.yml +223 -0
- data/spec/fixtures/Article/_search/query_is_a_single_space/.yml +223 -0
- data/spec/fixtures/Article/_search/query_is_an_empty_string/.yml +223 -0
- data/spec/fixtures/Article/_to_s/when_an_article_has_a_category/returns_a_string_containing_title_id_and_category.yml +223 -0
- data/spec/fixtures/Article/can_be_published/an_unpublished_article/is_published.yml +223 -0
- data/spec/fixtures/Article/can_be_published/an_unpublished_article/returns_status_Published.yml +223 -0
- data/spec/fixtures/Article/has_a_friendly_url.yml +223 -0
- data/spec/fixtures/Article/is_valid_with_a_title.yml +223 -0
- data/spec/fixtures/Searches/search_results/1_result_found/.yml +22047 -0
- data/spec/fixtures/Searches/search_results/no_results_found/.yml +393 -0
- data/spec/fixtures/Searches/search_results/several_results_found/should_contain_the_title_and_preview_of_both_articles.yml +223 -0
- data/spec/fixtures/Searches/search_results/several_results_found/show_the_query.yml +277 -0
- data/spec/fixtures/articles.yml +428 -0
- data/spec/fixtures/categories.yml +17 -0
- data/spec/fixtures/contacts.yml +11 -0
- data/spec/fixtures/dragon_keyword_cassette.yml +77 -0
- data/spec/fixtures/oakland_answers.yml +2379 -0
- data/spec/helpers/tags_helper_spec.rb +15 -0
- data/spec/lib/markdownifier_spec.rb +12 -0
- data/spec/models/ability_spec.rb +36 -0
- data/spec/models/answer_spec.rb +5 -0
- data/spec/models/question_spec.rb +70 -0
- data/spec/models/user_spec.rb +55 -0
- data/spec/routing/answers_routing_spec.rb +19 -0
- data/spec/routing/questions_routing_spec.rb +19 -0
- data/spec/routing/routes_spec.rb +13 -0
- data/spec/security/brakeman_spec.rb +37 -0
- data/spec/spec_helper.rb +61 -0
- data/spec/support/login_helpers.rb +10 -0
- data/spec/support/wait_for_ajax_helper.rb +7 -0
- data/spec/support/wait_for_dom_helper.rb +12 -0
- data/spec/views/questions/index.html.erb_spec.rb +16 -0
- data/spec/views/questions/show.html.erb_spec.rb +14 -0
- data/spec/views/tags/index.html.erb_spec.rb +5 -0
- data/spec/views/tags/show.html.erb_spec.rb +5 -0
- data/vendor/assets/javascripts/.gitkeep +0 -0
- data/vendor/assets/stylesheets/.gitkeep +0 -0
- data/vendor/assets/stylesheets/bootstrap.css +3990 -0
- data/vendor/crudgen/lib/generators/crudgen/install_generator.rb +23 -0
- data/vendor/plugins/.gitkeep +0 -0
- metadata +484 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
|
2
|
+
|
3
|
+
en:
|
4
|
+
errors:
|
5
|
+
messages:
|
6
|
+
expired: "has expired, please request a new one"
|
7
|
+
not_found: "not found"
|
8
|
+
already_confirmed: "was already confirmed, please try signing in"
|
9
|
+
not_locked: "was not locked"
|
10
|
+
not_saved:
|
11
|
+
one: "1 error prohibited this %{resource} from being saved:"
|
12
|
+
other: "%{count} errors prohibited this %{resource} from being saved:"
|
13
|
+
|
14
|
+
devise:
|
15
|
+
failure:
|
16
|
+
already_authenticated: 'You are already signed in.'
|
17
|
+
unauthenticated: 'You need to sign in or sign up before continuing.'
|
18
|
+
unconfirmed: 'You have to confirm your account before continuing.'
|
19
|
+
locked: 'Your account is locked.'
|
20
|
+
invalid: 'Invalid email or password.'
|
21
|
+
invalid_token: 'Invalid authentication token.'
|
22
|
+
timeout: 'Your session expired, please sign in again to continue.'
|
23
|
+
inactive: 'Your account was not activated yet.'
|
24
|
+
sessions:
|
25
|
+
signed_in: 'Signed in successfully.'
|
26
|
+
signed_out: 'Signed out successfully.'
|
27
|
+
passwords:
|
28
|
+
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
29
|
+
updated: 'Your password was changed successfully. You are now signed in.'
|
30
|
+
updated_not_active: 'Your password was changed successfully.'
|
31
|
+
send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
32
|
+
confirmations:
|
33
|
+
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
|
34
|
+
send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
|
35
|
+
confirmed: 'Your account was successfully confirmed. You are now signed in.'
|
36
|
+
registrations:
|
37
|
+
signed_up: 'Welcome! You have signed up successfully.'
|
38
|
+
signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
|
39
|
+
signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
|
40
|
+
signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
|
41
|
+
updated: 'You updated your account successfully.'
|
42
|
+
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
|
43
|
+
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
|
44
|
+
unlocks:
|
45
|
+
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
|
46
|
+
unlocked: 'Your account has been unlocked successfully. Please sign in to continue.'
|
47
|
+
send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
|
48
|
+
omniauth_callbacks:
|
49
|
+
success: 'Successfully authorized from %{kind} account.'
|
50
|
+
failure: 'Could not authorize you from %{kind} because "%{reason}".'
|
51
|
+
mailer:
|
52
|
+
confirmation_instructions:
|
53
|
+
subject: 'Confirmation instructions'
|
54
|
+
reset_password_instructions:
|
55
|
+
subject: 'Reset password instructions'
|
56
|
+
unlock_instructions:
|
57
|
+
subject: 'Unlock Instructions'
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# Sample localization file for English. Add more files in this directory for other locales.
|
2
|
+
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
|
3
|
+
|
4
|
+
#en:
|
5
|
+
# hello: "Hello world"
|
6
|
+
|
7
|
+
#############################################################
|
8
|
+
|
9
|
+
# from: http://stackoverflow.com/a/12430597/94154
|
10
|
+
|
11
|
+
en:
|
12
|
+
active_admin:
|
13
|
+
dashboard: Dashboard
|
14
|
+
dashboard_welcome:
|
15
|
+
welcome: "Welcome to Active Admin. This is the default dashboard page."
|
16
|
+
call_to_action: "To add dashboard sections, checkout 'app/admin/dashboard.rb'"
|
17
|
+
view: "View"
|
18
|
+
edit: "Edit"
|
19
|
+
delete: "Delete"
|
20
|
+
delete_confirmation: "Are you sure you want to delete this?"
|
21
|
+
new_model: "New %{model}"
|
22
|
+
create_model: "New %{model}"
|
23
|
+
edit_model: "Edit %{model}"
|
24
|
+
update_model: "Edit %{model}"
|
25
|
+
delete_model: "Delete %{model}"
|
26
|
+
details: "%{model} Details"
|
27
|
+
cancel: "Cancel"
|
28
|
+
empty: "Empty"
|
29
|
+
previous: "Previous"
|
30
|
+
next: "Next"
|
31
|
+
download: "Download:"
|
32
|
+
has_many_new: "Add New %{model}"
|
33
|
+
has_many_delete: "Delete"
|
34
|
+
has_many_remove: "Remove"
|
35
|
+
filters:
|
36
|
+
buttons:
|
37
|
+
filter: "Filter"
|
38
|
+
clear: "Clear Filters"
|
39
|
+
predicates:
|
40
|
+
contains: "Contains"
|
41
|
+
equals: "Equals"
|
42
|
+
starts_with: "Starts with"
|
43
|
+
ends_with: "Ends with"
|
44
|
+
greater_than: "Greater than"
|
45
|
+
less_than: "Less than"
|
46
|
+
main_content: "Please implement %{model}#main_content to display content."
|
47
|
+
logout: "Logout"
|
48
|
+
powered_by: "Powered by %{active_admin} %{version}"
|
49
|
+
sidebars:
|
50
|
+
filters: "Filters"
|
51
|
+
pagination:
|
52
|
+
empty: "No %{model} found"
|
53
|
+
one: "Displaying <b>1</b> %{model}"
|
54
|
+
one_page: "Displaying <b>all %{n}</b> %{model}"
|
55
|
+
multiple: "Displaying %{model} <b>%{from} - %{to}</b> of <b>%{total}</b> in total"
|
56
|
+
multiple_without_total: "Displaying %{model} <b>%{from} - %{to}</b>"
|
57
|
+
entry:
|
58
|
+
one: "entry"
|
59
|
+
other: "entries"
|
60
|
+
any: "Any"
|
61
|
+
blank_slate:
|
62
|
+
content: "There are no %{resource_name} yet."
|
63
|
+
link: "Create one"
|
64
|
+
dropdown_actions:
|
65
|
+
button_label: "Actions"
|
66
|
+
batch_actions:
|
67
|
+
button_label: "Batch Actions"
|
68
|
+
default_confirmation: "Are you sure you want to do this?"
|
69
|
+
delete_confirmation: "Are you sure you want to delete these %{plural_model}?"
|
70
|
+
succesfully_destroyed:
|
71
|
+
one: "Successfully destroyed 1 %{model}"
|
72
|
+
other: "Successfully destroyed %{count} %{plural_model}"
|
73
|
+
selection_toggle_explanation: "(Toggle Selection)"
|
74
|
+
link: "Create one"
|
75
|
+
action_label: "%{title} Selected"
|
76
|
+
labels:
|
77
|
+
destroy: "Delete"
|
78
|
+
comments:
|
79
|
+
resource_type: "Resource Type"
|
80
|
+
author_type: "Author Type"
|
81
|
+
body: "Body"
|
82
|
+
author: "Author"
|
83
|
+
title: "Comment"
|
84
|
+
add: "Add Comment"
|
85
|
+
resource: "Resource"
|
86
|
+
no_comments_yet: "No comments yet."
|
87
|
+
author_missing: "Anonymous"
|
88
|
+
title_content: "Comments (%{count})"
|
89
|
+
errors:
|
90
|
+
empty_text: "Comment wasn't saved, text was empty."
|
91
|
+
devise:
|
92
|
+
username:
|
93
|
+
title: "Username"
|
94
|
+
email:
|
95
|
+
title: "Email"
|
96
|
+
subdomain:
|
97
|
+
title: "Subdomain"
|
98
|
+
password:
|
99
|
+
title: "Password"
|
100
|
+
sign_up:
|
101
|
+
title: "Sign up"
|
102
|
+
submit: "Sign up"
|
103
|
+
login:
|
104
|
+
title: "Login"
|
105
|
+
remember_me: "Remember me"
|
106
|
+
submit: "Login"
|
107
|
+
reset_password:
|
108
|
+
title: "Forgot your password?"
|
109
|
+
submit: "Reset My Password"
|
110
|
+
change_password:
|
111
|
+
title: "Change your password"
|
112
|
+
submit: "Change my password"
|
113
|
+
unlock:
|
114
|
+
title: "Resend unlock instructions"
|
115
|
+
submit: "Resend unlock instructions"
|
116
|
+
resend_confirmation_instructions:
|
117
|
+
title: "Resend confirmation instructions"
|
118
|
+
submit: "Resend confirmation instructions"
|
119
|
+
links:
|
120
|
+
sign_in: "Sign in"
|
121
|
+
forgot_your_password: "Forgot your password?"
|
122
|
+
sign_in_with_omniauth_provider: "Sign in with %{provider}"
|
123
|
+
access_denied:
|
124
|
+
message: "You are not authorized to perform this action."
|
125
|
+
index_list:
|
126
|
+
table: "Table"
|
127
|
+
block: "List"
|
128
|
+
grid: "Grid"
|
129
|
+
blog: "Blog"
|
data/config/routes.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Answers::Core::Engine.routes.draw do
|
2
|
+
|
3
|
+
namespace :api, defaults: {format: 'json'} do
|
4
|
+
namespace :v1 do
|
5
|
+
resources :questions
|
6
|
+
resources :answers
|
7
|
+
resources :tags
|
8
|
+
resources :taggings
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
match '/about' => "home#about" , :as => :about, :via => :get
|
13
|
+
match '/search/' => "search#index" , :as => :search, :via => [:get, :post]
|
14
|
+
match '/search/tag/' => "search#tag_search" , :as => :tag_search, :via => [:get, :post]
|
15
|
+
match 'autocomplete' => "search#autocomplete", :via => :get
|
16
|
+
|
17
|
+
resources :questions, only: [:index, :show], :path => 'answers', :as => 'answers'
|
18
|
+
resources :tags, only: [:index, :show]
|
19
|
+
# root :to => "home#index"
|
20
|
+
match '/' => 'home#index', :via => :get, as: 'home'
|
21
|
+
devise_for :users, class_name: "Answers::User", module: :devise
|
22
|
+
end
|
data/config/secrets.yml
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Your secret key is used for verifying the integrity of signed cookies.
|
4
|
+
# If you change this key, all old signed cookies will become invalid!
|
5
|
+
|
6
|
+
# Make sure the secret is at least 30 characters and all random,
|
7
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
8
|
+
# You can use `rake secret` to generate a secure secret key.
|
9
|
+
|
10
|
+
# Make sure the secrets in this file are kept private
|
11
|
+
# if you're sharing your code publicly.
|
12
|
+
|
13
|
+
development:
|
14
|
+
background_image: /assets/background_image.jpg
|
15
|
+
coveralls_run_locally: /assets/background_image.jpg
|
16
|
+
coveralls_token: /assets/background_image.jpg
|
17
|
+
google_analytics_key: /assets/background_image.jpg
|
18
|
+
kissmetrics_api_key: /assets/background_image.jpg
|
19
|
+
|
20
|
+
official_city_name: answers
|
21
|
+
official_site_title: answers platform
|
22
|
+
official_government_url: https://18f.gsa.gov
|
23
|
+
official_contact_mail: contact@example.gov
|
24
|
+
official_style_guide: https://18f.gsa.gov
|
25
|
+
|
26
|
+
s3_bucket:
|
27
|
+
s3_key:
|
28
|
+
s3_secret:
|
29
|
+
secret_key_base: 629530da3e01ab7094b2d37ab76da69c96e14eb49bd60d769897dc556e7eb0e0cab7ec0f811c1f61f6512ddf074b7c1caa4cf7f26678ffeaac7ccf7e30288e18a
|
30
|
+
|
31
|
+
|
32
|
+
test:
|
33
|
+
background_image: /assets/background_image.jpg
|
34
|
+
coveralls_run_locally: /assets/background_image.jpg
|
35
|
+
coveralls_token: /assets/background_image.jpg
|
36
|
+
google_analytics_key: /assets/background_image.jpg
|
37
|
+
kissmetrics_api_key: /assets/background_image.jpg
|
38
|
+
|
39
|
+
official_city_name: answers
|
40
|
+
official_site_title: answers platform
|
41
|
+
official_government_url: https://18f.gsa.gov
|
42
|
+
official_contact_mail: contact@example.gov
|
43
|
+
official_style_guide: https://18f.gsa.gov
|
44
|
+
|
45
|
+
s3_bucket:
|
46
|
+
s3_key:
|
47
|
+
s3_secret:
|
48
|
+
secret_key_base: 629530da3e01ab7094b2d37ab76da69c96e14eb49bd60d769897dc556e7eb0e0cab7ec0f811c1f61f6512ddf074b7c1caa4cf7f26678ffeaac7ccf7e30288e18a
|
49
|
+
|
50
|
+
# Do not keep production secrets in the repository,
|
51
|
+
# instead read values from the environment.
|
52
|
+
production:
|
53
|
+
background_image: <%= ENV["BACKGROUND_IMAGE"] %>
|
54
|
+
coveralls_run_locally: <%= ENV["COVERALLS_RUN_LOCALLY"] %>
|
55
|
+
coveralls_token: <%= ENV["COVERALLS_TOKEN"] %>
|
56
|
+
google_analytics_key: <%= ENV["GOOGLE_ANALYTICS_KEY"] %>
|
57
|
+
kissmetrics_api_key: <%= ENV["KISSMETRICS_API_KEY"] %>
|
58
|
+
|
59
|
+
official_city_name: <%= ENV["OFFICIAL_CITY_NAME"] %>
|
60
|
+
official_site_title: <%= ENV["OFFICIAL_SITE_TITLE"] %>
|
61
|
+
official_government_url: <%= ENV["OFFICIAL_GOVERNMENT_URL"] %>
|
62
|
+
official_contact_mail: <%= ENV["OFFICIAL_CONTACT_MAIL"] %>
|
63
|
+
official_style_guide: <%= ENV["OFFICIAL_STYLE_GUIDE"] %>
|
64
|
+
|
65
|
+
s3_bucket: <%= ENV["S3_BUCKET"] %>
|
66
|
+
s3_key: <%= ENV["S3_KEY"] %>
|
67
|
+
s3_secret: <%= ENV["S3_SECRET"] %>
|
68
|
+
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class AnswersUp < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def change
|
4
|
+
|
5
|
+
create_table :answers_answers do |t|
|
6
|
+
t.text :need_to_know
|
7
|
+
t.text :text
|
8
|
+
t.string :url
|
9
|
+
t.string :in_language
|
10
|
+
t.references :question, index: true
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
|
15
|
+
add_index :answers_answers, :id
|
16
|
+
|
17
|
+
|
18
|
+
create_table :answers_questions do |t|
|
19
|
+
t.string :text
|
20
|
+
t.string :url
|
21
|
+
t.string :in_language
|
22
|
+
|
23
|
+
t.timestamps
|
24
|
+
end
|
25
|
+
|
26
|
+
add_index :answers_questions, :id
|
27
|
+
|
28
|
+
|
29
|
+
# USERS
|
30
|
+
|
31
|
+
create_table(:answers_users) do |t|
|
32
|
+
## Database authenticatable
|
33
|
+
t.string :email, :null => false, :default => ""
|
34
|
+
t.string :encrypted_password, :null => false, :default => ""
|
35
|
+
|
36
|
+
## Recoverable
|
37
|
+
t.string :reset_password_token
|
38
|
+
t.datetime :reset_password_sent_at
|
39
|
+
|
40
|
+
## Rememberable
|
41
|
+
t.datetime :remember_created_at
|
42
|
+
|
43
|
+
## Trackable
|
44
|
+
t.integer :sign_in_count, :default => 0
|
45
|
+
t.datetime :current_sign_in_at
|
46
|
+
t.datetime :last_sign_in_at
|
47
|
+
t.string :current_sign_in_ip
|
48
|
+
t.string :last_sign_in_ip
|
49
|
+
|
50
|
+
## Encryptable
|
51
|
+
# t.string :password_salt
|
52
|
+
|
53
|
+
## Confirmable
|
54
|
+
# t.string :confirmation_token
|
55
|
+
# t.datetime :confirmed_at
|
56
|
+
# t.datetime :confirmation_sent_at
|
57
|
+
# t.string :unconfirmed_email # Only if using reconfirmable
|
58
|
+
|
59
|
+
## Lockable
|
60
|
+
# t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
|
61
|
+
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
62
|
+
# t.datetime :locked_at
|
63
|
+
|
64
|
+
# Token authenticatable
|
65
|
+
t.string :authentication_token
|
66
|
+
|
67
|
+
## Invitable
|
68
|
+
# t.string :invitation_token
|
69
|
+
|
70
|
+
t.timestamps
|
71
|
+
|
72
|
+
#
|
73
|
+
t.boolean "is_editor"
|
74
|
+
t.boolean "is_admin", default: false
|
75
|
+
t.boolean "is_writer", default: false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/lib/answers-core.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'answers/core'
|
data/lib/answers.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'rails' # from railties
|
2
|
+
require 'active_record'
|
3
|
+
require 'action_controller'
|
4
|
+
require 'rbconfig'
|
5
|
+
|
6
|
+
module Answers
|
7
|
+
require 'answers/errors'
|
8
|
+
|
9
|
+
autoload :Engine, 'answers/engine'
|
10
|
+
autoload :CmsGenerator, 'generators/answers/cms/cms_generator'
|
11
|
+
autoload :DummyGenerator, 'generators/answers/dummy/dummy_generator'
|
12
|
+
autoload :CoreGenerator, 'generators/answers/core/core_generator'
|
13
|
+
autoload :EngineGenerator, 'generators/answers/engine/engine_generator'
|
14
|
+
|
15
|
+
class << self
|
16
|
+
@@extensions = []
|
17
|
+
|
18
|
+
# Returns an array of modules representing currently registered Answers Engines
|
19
|
+
#
|
20
|
+
# Example:
|
21
|
+
# Answers.extensions => [Answers::Core, Answers::Pages]
|
22
|
+
def extensions
|
23
|
+
@@extensions
|
24
|
+
end
|
25
|
+
|
26
|
+
# Register an extension with Answers
|
27
|
+
#
|
28
|
+
# Example:
|
29
|
+
# Answers.register_extension(Answers::Core)
|
30
|
+
def register_extension(const)
|
31
|
+
return if extension_registered?(const)
|
32
|
+
|
33
|
+
validate_extension!(const)
|
34
|
+
|
35
|
+
@@extensions << const
|
36
|
+
end
|
37
|
+
alias_method :register_engine, :register_extension
|
38
|
+
|
39
|
+
# Unregister an extension from Answers
|
40
|
+
#
|
41
|
+
# Example:
|
42
|
+
# Answers.unregister_extension(Answers::Core)
|
43
|
+
def unregister_extension(const)
|
44
|
+
@@extensions.delete(const)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns true if an extension is currently registered with Answers
|
48
|
+
#
|
49
|
+
# Example:
|
50
|
+
# Answers.extension_registered?(Answers::Core)
|
51
|
+
def extension_registered?(const)
|
52
|
+
@@extensions.include?(const)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Constructs a deprecation warning message and warns with Kernel#warn
|
56
|
+
#
|
57
|
+
# Example:
|
58
|
+
# Answers.deprecate('foo') => "The use of 'foo' is deprecated"
|
59
|
+
#
|
60
|
+
# An options parameter can be specified to construct a more detailed deprecation message
|
61
|
+
#
|
62
|
+
# Options:
|
63
|
+
# when - version that this deprecated feature will be removed
|
64
|
+
# replacement - a replacement for what is being deprecated
|
65
|
+
# caller - who called the deprecated feature
|
66
|
+
#
|
67
|
+
# Example:
|
68
|
+
# Answers.deprecate('foo', :when => 'tomorrow', :replacement => 'bar') =>
|
69
|
+
# "The use of 'foo' is deprecated and will be removed at version 2.0. Please use 'bar' instead."
|
70
|
+
def deprecate(what, options = {})
|
71
|
+
# Build a warning.
|
72
|
+
warning = "\n-- DEPRECATION WARNING --\nThe use of '#{what}' is deprecated"
|
73
|
+
warning << " and will be removed at version #{options[:when]}" if options[:when]
|
74
|
+
warning << "."
|
75
|
+
warning << "\nPlease use #{options[:replacement]} instead." if options[:replacement]
|
76
|
+
|
77
|
+
# See if we can trace where this happened
|
78
|
+
if (invoker = detect_invoker(options[:caller])).present?
|
79
|
+
warning << invoker
|
80
|
+
end
|
81
|
+
|
82
|
+
# Give stern talking to.
|
83
|
+
warn warning
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns a Pathname to the root of the Answers project
|
87
|
+
def root
|
88
|
+
@root ||= Pathname.new(File.expand_path('../../../', __FILE__))
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns an array of Pathnames pointing to the root directory of each extension that
|
92
|
+
# has been registered with Answers.
|
93
|
+
#
|
94
|
+
# Example:
|
95
|
+
# Answers.roots => [#<Pathname:/Users/Reset/Code/answerscms/core>, #<Pathname:/Users/Reset/Code/answerscms/pages>]
|
96
|
+
#
|
97
|
+
# An optional extension_name parameter can be specified to return just the Pathname for
|
98
|
+
# the specified extension. This can be represented in Constant, Symbol, or String form.
|
99
|
+
#
|
100
|
+
# Example:
|
101
|
+
# Answers.roots(Answers::Core) => #<Pathname:/Users/Reset/Code/answerscms/core>
|
102
|
+
# Answers.roots(:'answers/core') => #<Pathname:/Users/Reset/Code/answerscms/core>
|
103
|
+
# Answers.roots("answers/core") => #<Pathname:/Users/Reset/Code/answerscms/core>
|
104
|
+
def roots(extension_name = nil)
|
105
|
+
return @roots ||= self.extensions.map(&:root) if extension_name.nil?
|
106
|
+
|
107
|
+
extension_name.to_s.camelize.constantize.root
|
108
|
+
end
|
109
|
+
|
110
|
+
def version
|
111
|
+
Answers::Version.to_s
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns string version of url helper path. We need this to temporarily support namespaces
|
115
|
+
# like Answers::Image and Answers::Blog::Post
|
116
|
+
#
|
117
|
+
# Example:
|
118
|
+
# Answers.route_for_model(Answers::Image) => "admin_image_path"
|
119
|
+
# Answers.route_for_model(Answers::Image, {:plural => true}) => "admin_images_path"
|
120
|
+
# Answers.route_for_model(Answers::Blog::Post) => "blog_admin_post_path"
|
121
|
+
# Answers.route_for_model(Answers::Blog::Post, {:plural => true}) => "blog_admin_posts_path"
|
122
|
+
# Answers.route_for_model(Answers::Blog::Post, {:admin => false}) => "blog_post_path"
|
123
|
+
def route_for_model(klass, options = {})
|
124
|
+
options = {:plural => false, :admin => true}.merge options
|
125
|
+
|
126
|
+
klass = klass.constantize if klass.respond_to?(:constantize)
|
127
|
+
active_name = ::ActiveModel::Name.new(
|
128
|
+
klass, (Answers if klass.parents.include?(Answers))
|
129
|
+
)
|
130
|
+
|
131
|
+
if options[:admin]
|
132
|
+
# Most of the time this gets rid of 'answers'
|
133
|
+
parts = active_name.to_s.underscore.split('/').reject{|name|
|
134
|
+
active_name.singular_route_key.exclude?(name)
|
135
|
+
}
|
136
|
+
|
137
|
+
# Get the singular resource_name from the url parts
|
138
|
+
resource_name = parts.pop
|
139
|
+
resource_name = resource_name.pluralize if options[:plural]
|
140
|
+
|
141
|
+
[parts.join("_"), "admin", resource_name, "path"].reject(&:blank?).join "_"
|
142
|
+
else
|
143
|
+
path = options[:plural] ? active_name.route_key : active_name.singular_route_key
|
144
|
+
|
145
|
+
[path, 'path'].join '_'
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def include_once(base, extension_module)
|
150
|
+
base.send :include, extension_module unless included_extension_module?(base, extension_module)
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
def detect_invoker(the_caller = caller)
|
155
|
+
return '' unless the_caller && the_caller.respond_to?(:detect)
|
156
|
+
the_caller.detect{|c| /#{Rails.root}/ === c }.inspect.to_s.split(':in').first
|
157
|
+
end
|
158
|
+
|
159
|
+
# plain Module#included? or Module#included_modules doesn't cut it here
|
160
|
+
def included_extension_module?(base, extension_module)
|
161
|
+
if base.kind_of?(Class)
|
162
|
+
direct_superclass = base.superclass
|
163
|
+
base.ancestors.take_while {|ancestor| ancestor != direct_superclass}.include?(extension_module)
|
164
|
+
else
|
165
|
+
base < extension_module # can't do better than that for modules
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def validate_extension!(const)
|
170
|
+
unless const.respond_to?(:root) && const.root.is_a?(Pathname)
|
171
|
+
raise InvalidEngineError, "Engine must define a root accessor that returns a pathname to its root"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|