releaf 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +15 -12
  3. data/Rakefile +8 -0
  4. data/app/assets/javascripts/releaf/controllers/base.js +0 -40
  5. data/app/assets/javascripts/releaf/include/field.type_date_or_datetime_or_time.js +43 -0
  6. data/app/assets/javascripts/releaf/include/nested_fields.js +58 -65
  7. data/app/assets/javascripts/releaf/include/sortable.js +19 -17
  8. data/app/assets/stylesheets/releaf/controllers/releaf/content.css.erb +6 -0
  9. data/app/assets/stylesheets/releaf/include/field.css.erb +37 -13
  10. data/app/controllers/releaf/admins_controller.rb +13 -6
  11. data/app/controllers/releaf/base_application_controller.rb +4 -1
  12. data/app/controllers/releaf/base_controller.rb +415 -154
  13. data/app/controllers/releaf/content_controller.rb +62 -45
  14. data/app/controllers/releaf/roles_controller.rb +11 -9
  15. data/app/controllers/releaf/sessions_controller.rb +23 -1
  16. data/app/controllers/releaf/translations_controller.rb +21 -25
  17. data/app/helpers/releaf/admin_helper.rb +0 -20
  18. data/app/models/releaf/admin.rb +9 -0
  19. data/app/models/releaf/blank_node_base.rb +29 -0
  20. data/app/models/releaf/node.rb +6 -5
  21. data/app/models/releaf/node_base.rb +9 -3
  22. data/app/models/releaf/role.rb +9 -2
  23. data/app/views/layouts/releaf/admin.html.haml +12 -6
  24. data/app/views/layouts/releaf/devise.html.haml +32 -0
  25. data/app/views/releaf/aliases/{_edit.body.haml → _edit.body.html.haml} +0 -0
  26. data/app/views/releaf/aliases/{_edit.header.haml → _edit.header.html.haml} +1 -1
  27. data/app/views/releaf/aliases/_index.row.html.haml +5 -0
  28. data/app/views/releaf/aliases/{_secondary_panel.haml → _secondary_panel.html.haml} +0 -0
  29. data/app/views/releaf/base/_edit.body.html.haml +11 -0
  30. data/app/views/releaf/base/_edit.field.html.haml +23 -0
  31. data/app/views/releaf/base/{_edit.field.type_autocomplete.haml → _edit.field_type_autocomplete.html.haml} +1 -1
  32. data/app/views/releaf/base/{_edit.field.type_checkbox.haml → _edit.field_type_boolean.html.haml} +1 -1
  33. data/app/views/releaf/base/{_edit.field.type_date.haml → _edit.field_type_date.html.haml} +0 -0
  34. data/app/views/releaf/base/{_edit.field.type_datetime.haml → _edit.field_type_datetime.html.haml} +0 -0
  35. data/app/views/releaf/base/{_edit.field.type_delete_nested.haml → _edit.field_type_delete_nested.html.haml} +0 -0
  36. data/app/views/releaf/base/{_edit.field.type_file.haml → _edit.field_type_file.html.haml} +0 -0
  37. data/app/views/releaf/base/_edit.field_type_image.html.haml +12 -0
  38. data/app/views/releaf/base/_edit.field_type_item.html.haml +31 -0
  39. data/app/views/releaf/base/{_edit.field.type_link.haml → _edit.field_type_link.html.haml} +0 -0
  40. data/app/views/releaf/base/_edit.field_type_link_i18n.html.haml +26 -0
  41. data/app/views/releaf/base/{_edit.field.type_password.haml → _edit.field_type_password.html.haml} +0 -0
  42. data/app/views/releaf/base/{_edit.field.type_richtext.haml → _edit.field_type_richtext.html.haml} +0 -0
  43. data/app/views/releaf/base/{_edit.field.type_richtext_i18n.haml → _edit.field_type_richtext_i18n.html.haml} +0 -0
  44. data/app/views/releaf/base/{_edit.field.type_text.haml → _edit.field_type_text.html.haml} +0 -0
  45. data/app/views/releaf/base/{_edit.field.type_text_i18n.haml → _edit.field_type_text_i18n.html.haml} +0 -0
  46. data/app/views/releaf/base/{_edit.field.type_textarea.haml → _edit.field_type_textarea.html.haml} +0 -0
  47. data/app/views/releaf/base/{_edit.field.type_textarea_i18n.haml → _edit.field_type_textarea_i18n.html.haml} +0 -0
  48. data/app/views/releaf/base/{_edit.field.type_time.haml → _edit.field_type_time.html.haml} +0 -0
  49. data/app/views/releaf/base/_edit.fields.association.html.haml +48 -0
  50. data/app/views/releaf/base/_edit.fields.has_many_template.html.haml +15 -0
  51. data/app/views/releaf/base/_edit.fields.html.haml +20 -0
  52. data/app/views/releaf/base/{_edit.footer.haml → _edit.footer.html.haml} +2 -2
  53. data/app/views/releaf/base/_edit.form.html.haml +4 -0
  54. data/app/views/releaf/base/_edit.header.html.haml +3 -0
  55. data/app/views/releaf/base/{_index.body.haml → _index.body.html.haml} +2 -2
  56. data/app/views/releaf/base/_index.cell.html.haml +20 -0
  57. data/app/views/releaf/base/_index.footer.html.haml +28 -0
  58. data/app/views/releaf/base/_index.header.html.haml +4 -0
  59. data/app/views/releaf/base/_index.row.html.haml +6 -0
  60. data/app/views/releaf/base/_index.search.html.haml +5 -0
  61. data/app/views/releaf/base/_index.table.html.haml +24 -0
  62. data/app/views/releaf/base/_secondary_panel.html.haml +10 -0
  63. data/app/views/releaf/base/_show.body.html.haml +3 -0
  64. data/app/views/releaf/base/_show.field.html.haml +20 -0
  65. data/app/views/releaf/base/_show.field_type_date.html.haml +9 -0
  66. data/app/views/releaf/base/_show.field_type_date_time.html.haml +9 -0
  67. data/app/views/releaf/base/_show.field_type_email.html.haml +6 -0
  68. data/app/views/releaf/base/_show.field_type_file.html.haml +7 -0
  69. data/app/views/releaf/base/_show.field_type_image.html.haml +10 -0
  70. data/app/views/releaf/base/_show.field_type_item.html.haml +11 -0
  71. data/app/views/releaf/base/_show.field_type_link.html.haml +14 -0
  72. data/app/views/releaf/base/_show.field_type_password.html.haml +6 -0
  73. data/app/views/releaf/base/_show.field_type_richtext.html.haml +6 -0
  74. data/app/views/releaf/base/_show.field_type_text.html.haml +6 -0
  75. data/app/views/releaf/base/_show.field_type_textarea.html.haml +6 -0
  76. data/app/views/releaf/base/_show.field_type_time.html.haml +9 -0
  77. data/app/views/releaf/base/_show.field_type_url.html.haml +7 -0
  78. data/app/views/releaf/base/_show.fields.association.html.haml +36 -0
  79. data/app/views/releaf/base/_show.fields.has_many_template.html.haml +12 -0
  80. data/app/views/releaf/base/_show.fields.html.haml +17 -0
  81. data/app/views/releaf/base/{_show.footer.haml → _show.footer.html.haml} +6 -4
  82. data/app/views/releaf/base/_show.header.html.haml +3 -0
  83. data/app/views/releaf/base/confirm_destroy.html.haml +17 -0
  84. data/app/views/releaf/base/edit.html.haml +1 -0
  85. data/app/views/releaf/base/index.html.haml +3 -0
  86. data/app/views/releaf/base/new.html.haml +1 -0
  87. data/app/views/releaf/base/show.html.haml +3 -0
  88. data/app/views/releaf/content/{_edit.body.haml → _edit.body.html.haml} +7 -6
  89. data/app/views/releaf/content/_edit.content_fields.html.haml +11 -0
  90. data/app/views/releaf/content/_edit.fields.html.haml +17 -0
  91. data/app/views/releaf/content/{_edit.slug.haml → _edit.slug.html.haml} +0 -0
  92. data/app/views/releaf/content/{_get_content_form.haml → _get_content_form.html.haml} +2 -2
  93. data/app/views/releaf/content/{_secondary_panel.haml → _secondary_panel.html.haml} +0 -0
  94. data/app/views/releaf/content/{_tree_level.haml → _tree_level.html.haml} +0 -0
  95. data/app/views/releaf/content/{ajax.new.haml → ajax.new.html.haml} +0 -0
  96. data/app/views/releaf/content/{index.haml → index.html.haml} +0 -0
  97. data/app/views/releaf/roles/_edit.field.permissions.html.haml +5 -0
  98. data/app/views/releaf/roles/{_show.field.default.haml → _show.field.default.html.haml} +1 -1
  99. data/app/views/releaf/roles/{_show.field.permissions.haml → _show.field.permissions.html.haml} +2 -2
  100. data/app/views/releaf/translations/{_edit.body.haml → _edit.body.html.haml} +0 -0
  101. data/app/views/releaf/translations/{_edit.header.haml → _edit.header.html.haml} +1 -1
  102. data/app/views/releaf/translations/_index.row.html.haml +5 -0
  103. data/app/views/releaf/translations/{_secondary_panel.haml → _secondary_panel.html.haml} +0 -0
  104. data/lib/generators/releaf/templates/initializers/releaf.rb +0 -39
  105. data/lib/generators/releaf/templates/initializers/releaf_i18n.rb +17 -0
  106. data/lib/generators/releaf/templates/javascripts/3rd_party/jquery.jcarousel.js +1058 -0
  107. data/lib/generators/releaf/templates/javascripts/lib/init_jcarousel.js +40 -0
  108. data/lib/generators/releaf/templates/migrations/create_releaf_roles.rb +1 -0
  109. data/lib/generators/releaf/templates/migrations/create_releaf_tinymce_assets.rb +1 -0
  110. data/lib/generators/releaf/templates/models/admin_ability.rb +1 -1
  111. data/lib/i18n/backend/releaf.rb +5 -4
  112. data/lib/i18n/backend/releaf/translation.rb +5 -0
  113. data/lib/i18n/backend/releaf/translation_data.rb +7 -0
  114. data/lib/i18n/backend/releaf/translation_group.rb +4 -0
  115. data/lib/releaf.rb +4 -0
  116. data/lib/releaf/boolean_at.rb +77 -0
  117. data/lib/releaf/globalize3/fallbacks.rb +19 -0
  118. data/lib/releaf/resources.rb +101 -0
  119. data/lib/releaf/slug.rb +99 -60
  120. data/lib/releaf/version.rb +1 -1
  121. data/spec/spec_helper.rb +6 -0
  122. data/templates/releaf/installer.rb +15 -4
  123. metadata +275 -329
  124. data/app/views/releaf/aliases/_index.row.haml +0 -5
  125. data/app/views/releaf/base/_edit.body.haml +0 -19
  126. data/app/views/releaf/base/_edit.field.haml +0 -96
  127. data/app/views/releaf/base/_edit.field.type_image.haml +0 -14
  128. data/app/views/releaf/base/_edit.field.type_select.haml +0 -11
  129. data/app/views/releaf/base/_edit.form.haml +0 -4
  130. data/app/views/releaf/base/_edit.has_many_associations.haml +0 -45
  131. data/app/views/releaf/base/_edit.header.haml +0 -3
  132. data/app/views/releaf/base/_index.cell.haml +0 -19
  133. data/app/views/releaf/base/_index.footer.haml +0 -22
  134. data/app/views/releaf/base/_index.header.haml +0 -4
  135. data/app/views/releaf/base/_index.row.haml +0 -6
  136. data/app/views/releaf/base/_index.search.haml +0 -5
  137. data/app/views/releaf/base/_index.table.haml +0 -8
  138. data/app/views/releaf/base/_secondary_panel.haml +0 -9
  139. data/app/views/releaf/base/_show.body.haml +0 -7
  140. data/app/views/releaf/base/_show.field.haml +0 -78
  141. data/app/views/releaf/base/_show.field.type_html.haml +0 -1
  142. data/app/views/releaf/base/_show.header.haml +0 -3
  143. data/app/views/releaf/base/confirm_destroy.haml +0 -10
  144. data/app/views/releaf/base/edit.haml +0 -1
  145. data/app/views/releaf/base/index.haml +0 -3
  146. data/app/views/releaf/base/new.haml +0 -1
  147. data/app/views/releaf/base/show.haml +0 -3
  148. data/app/views/releaf/content/_edit.content_fields.haml +0 -19
  149. data/app/views/releaf/content/_show.field.content.haml +0 -11
  150. data/app/views/releaf/roles/_edit.field.admins.haml +0 -0
  151. data/app/views/releaf/roles/_edit.field.permissions.haml +0 -5
  152. data/app/views/releaf/translations/_index.row.haml +0 -5
  153. data/spec/dummy/README.rdoc +0 -261
  154. data/spec/dummy/Rakefile +0 -7
  155. data/spec/dummy/app/assets/images/rails.png +0 -0
  156. data/spec/dummy/app/assets/javascripts/application.js +0 -15
  157. data/spec/dummy/app/assets/stylesheets/application.css +0 -13
  158. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  159. data/spec/dummy/app/helpers/application_helper.rb +0 -2
  160. data/spec/dummy/app/models/admin_ability.rb +0 -51
  161. data/spec/dummy/app/models/settings.rb +0 -2
  162. data/spec/dummy/app/views/layouts/application.html.haml +0 -10
  163. data/spec/dummy/config.ru +0 -4
  164. data/spec/dummy/config/application.rb +0 -68
  165. data/spec/dummy/config/boot.rb +0 -6
  166. data/spec/dummy/config/common_fields.yml.example +0 -17
  167. data/spec/dummy/config/database.yml +0 -42
  168. data/spec/dummy/config/environment.rb +0 -5
  169. data/spec/dummy/config/environments/development.rb +0 -37
  170. data/spec/dummy/config/environments/production.rb +0 -67
  171. data/spec/dummy/config/environments/test.rb +0 -37
  172. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  173. data/spec/dummy/config/initializers/devise.rb +0 -232
  174. data/spec/dummy/config/initializers/dragonfly.rb +0 -1
  175. data/spec/dummy/config/initializers/inflections.rb +0 -15
  176. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  177. data/spec/dummy/config/initializers/releaf.rb +0 -59
  178. data/spec/dummy/config/initializers/releaf_i18n.rb +0 -8
  179. data/spec/dummy/config/initializers/releaf_store_current_template.rb +0 -25
  180. data/spec/dummy/config/initializers/secret_token.rb +0 -7
  181. data/spec/dummy/config/initializers/session_store.rb +0 -8
  182. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  183. data/spec/dummy/config/locales/devise.en.yml +0 -58
  184. data/spec/dummy/config/locales/en.yml +0 -5
  185. data/spec/dummy/config/routes.rb +0 -11
  186. data/spec/dummy/db/migrate/20130204164516_create_settings.rb +0 -17
  187. data/spec/dummy/db/migrate/20130204164523_create_releaf_nodes.rb +0 -25
  188. data/spec/dummy/db/migrate/20130204164524_create_releaf_roles.rb +0 -11
  189. data/spec/dummy/db/migrate/20130204164525_create_releaf_translations.rb +0 -31
  190. data/spec/dummy/db/migrate/20130204164526_create_releaf_admins.rb +0 -53
  191. data/spec/dummy/db/schema.rb +0 -112
  192. data/spec/dummy/db/seeds.rb +0 -64
  193. data/spec/dummy/doc/README_FOR_APP +0 -2
  194. data/spec/dummy/log/development.log +0 -74
  195. data/spec/dummy/log/test.log +0 -129
  196. data/spec/dummy/public/404.html +0 -26
  197. data/spec/dummy/public/422.html +0 -26
  198. data/spec/dummy/public/500.html +0 -25
  199. data/spec/dummy/public/favicon.ico +0 -0
  200. data/spec/dummy/script/rails +0 -6
  201. data/spec/dummy/tmp/cache/9C5/660/settings%3Ai18n_updated_at +0 -1
@@ -0,0 +1,40 @@
1
+ //= require ../3rd_party/jquery.jcarousel
2
+
3
+ jQuery(document).ready(function() {
4
+
5
+ jQuery(document.body).on('initcarousel', function(e) {
6
+ var target = jQuery(e.target);
7
+
8
+ target.find('.carousel_wrap').each(function() {
9
+ var carousel_wrap = jQuery(this);
10
+ var carousel_controls_wrap = carousel_wrap.find('.carousel_controls');
11
+ var carousel_controls = carousel_controls_wrap.find('a[data-nr], button[data-nr]');
12
+
13
+ carousel_wrap.find('.jcarousel').jcarousel({
14
+ wrap: 'circular',
15
+ vertical: false,
16
+ scroll: 1,
17
+ buttonNextHTML: null,
18
+ buttonPrevHTML: null,
19
+ auto: 5,
20
+ itemVisibleInCallback: {
21
+ onBeforeAnimation: function (carousel, item, idx, state) {
22
+ var jitem = jQuery(item);
23
+ carousel_controls.removeClass('active');
24
+ jQuery(carousel_controls[jitem.attr('data-nr')]).addClass('active');
25
+ }
26
+ },
27
+ initCallback: function(carousel) {
28
+ carousel_controls_wrap.on('click', 'a[data-nr], button[data-nr]', function() {
29
+ var link = jQuery(this);
30
+ carousel.scroll(jQuery.jcarousel.intval(link.attr('data-nr')));
31
+ });
32
+ }
33
+ });
34
+ });
35
+ });
36
+
37
+ jQuery(document.body).trigger('initcarousel');
38
+
39
+ });
40
+
@@ -4,6 +4,7 @@ class CreateReleafRoles < ActiveRecord::Migration
4
4
  t.string :name, :null => false
5
5
  t.text :permissions
6
6
  t.boolean :default, :null => false, :default => false
7
+ t.text :default_controller
7
8
 
8
9
  t.timestamps
9
10
  end
@@ -3,6 +3,7 @@ class CreateReleafTinymceAssets < ActiveRecord::Migration
3
3
  create_table :releaf_tinymce_assets do |t|
4
4
  t.string :file_uid
5
5
  t.string :file_name
6
+ t.string :file_type
6
7
 
7
8
  t.timestamps
8
9
  end
@@ -29,7 +29,7 @@ class AdminAbility
29
29
 
30
30
  if role.manage_translations_permission
31
31
  # Only manage is available for translation
32
- can :manage, Translation
32
+ can :manage, I18n::Backend::Releaf::Translation
33
33
  end
34
34
 
35
35
  ## Example:
@@ -40,7 +40,7 @@ module I18n
40
40
 
41
41
  # Lookup translation from database
42
42
  def lookup(locale, key, scope = [], options = {})
43
- if scope.blank?
43
+ if scope.blank? && key !~ /\./
44
44
  scope = DEFAULT_SCOPE
45
45
  end
46
46
 
@@ -59,14 +59,15 @@ module I18n
59
59
  keys_to_check_for_other_locales.push check_key
60
60
 
61
61
  next if result.nil? # nothing in cache was found
62
- return search_key.humanize if result == false # found nil translaiton in cache
62
+ return nil if result == false # found nil translaiton in cache
63
63
  return result unless result.blank? # found translation in cache
64
64
  end while chain.empty? == false
65
65
 
66
- return search_key.humanize if Translation.where('releaf_translations.key IN (?)', keys_to_check_for_other_locales).exists?
66
+ return nil if I18N_CACHE.read [:missing, [locale, check_key]]
67
+ I18N_CACHE.write([:missing, [locale, check_key]], true) if Translation.where('releaf_translations.key IN (?)', keys_to_check_for_other_locales).exists?
67
68
 
68
69
  save_missing_translation(locale, key)
69
- return search_key.humanize
70
+ return nil
70
71
  rescue ::ActiveRecord::StatementInvalid
71
72
  # is the translations table missing?
72
73
  nil
@@ -9,9 +9,14 @@ module I18n
9
9
 
10
10
  validates_presence_of :group_id, :key
11
11
  validates_uniqueness_of :key, :scope => :group_id
12
+
12
13
  belongs_to :translation_group, :foreign_key => :group_id
13
14
  has_many :translation_data, :dependent => :destroy, :class_name => 'Releaf::TranslationData'
14
15
 
16
+ attr_accessible \
17
+ :group_id,
18
+ :key
19
+
15
20
  scope :joined, select('releaf_translations.*, releaf_translation_data.lang as "lang", releaf_translation_data.localization as "localization", releaf_translation_groups.scope as "scope"').
16
21
  joins(:translation_data, :translation_group)
17
22
 
@@ -9,9 +9,16 @@ module I18n
9
9
 
10
10
  validates_presence_of :translation_id, :lang
11
11
  validates_uniqueness_of :translation_id, :scope => :lang
12
+
12
13
  belongs_to :translation
13
14
 
15
+ attr_accessible \
16
+ :lang,
17
+ :localization,
18
+ :translation_id
19
+
14
20
  scope :available_locales, where('lang IS NOT NULL').group(:lang).pluck(:lang)
21
+
15
22
  after_commit :reload_cache
16
23
 
17
24
  def text
@@ -10,6 +10,10 @@ module I18n
10
10
  validates_presence_of :scope
11
11
 
12
12
  has_many :translations, :dependent => :destroy, :foreign_key => :group_id, :order => 'releaf_translations.key'
13
+
14
+ attr_accessible \
15
+ :scope
16
+
13
17
  after_commit :reload_cache
14
18
 
15
19
  def to_s
data/lib/releaf.rb CHANGED
@@ -1,5 +1,9 @@
1
1
  require "releaf/slug"
2
+ require 'releaf/globalize3/fallbacks'
2
3
  require "releaf/engine"
4
+ require "releaf/resources"
5
+ require "releaf/boolean_at"
6
+
3
7
 
4
8
  module Releaf
5
9
  mattr_accessor :main_menu
@@ -0,0 +1,77 @@
1
+ module Releaf
2
+ # Adds boolean_at class method, that can be used to create boolean setter and
3
+ # getter for DateTime, Date and Time fields. It will also create scopes for
4
+ # when given attribute is set and when it is not set.
5
+ module BooleanAt
6
+ module ClassMethods
7
+
8
+ # Create boolean setter and getter for given DateTime, Date and Time
9
+ # attributes.
10
+ #
11
+ # Setter will accept "0", 0, false as false, everything else will
12
+ # evaluate to true. Setter accepts TrueClass, FalseClass, String, Fixnum.
13
+ # If you pass nil, it not change current value.
14
+ #
15
+ # Getter returns true or false
16
+ #
17
+ # Unless you add <tt>:without_scopes => true</tt> as last argument, two scopes
18
+ # will be created. One to list all resources with given attribute set and
19
+ # one that does the opposite.
20
+ #
21
+ # For example, if you use
22
+ #
23
+ # @example
24
+ # boolean_at :published_at
25
+ #
26
+ # it will create +published+, +published?+, +published=+ methods and
27
+ # +published+ and +unpublished+ scopes.
28
+ #
29
+ # @param args list of DateTime, Date and Time attributes that ends with
30
+ # _at or _on for which you'd like to create boolean setter and getter
31
+ # and scopes
32
+ def boolean_at *args
33
+ options = {}
34
+ options = args.pop if args.last.is_a? Hash
35
+
36
+ my_table_name = self.table_name
37
+
38
+ args.each do |name|
39
+ # raise ArgumentError, "column must be of type DateTime, Date or Time" unless [:datetime, :date, :time].include?(self.columns_hash[name.to_s].try(:type).try(:to_sym))
40
+ raise ArgumentError, "column name must end with _at or _on" unless name =~ /_(at|on)$/
41
+
42
+ fun_name = name.to_s.sub(/_(at|on)$/, '')
43
+
44
+ # create getter
45
+ define_method fun_name do
46
+ self.send(:"#{name}?")
47
+ end
48
+ alias_method :"#{fun_name}?", :"#{fun_name}"
49
+
50
+ # create setter
51
+ define_method :"#{fun_name}=" do |b|
52
+ return if b.nil?
53
+ raise ArgumentError unless b.is_a?(FalseClass) or b.is_a?(TrueClass) or b.is_a?(String) or b.is_a?(Fixnum)
54
+ if b == false or b == "0" or b == 0
55
+ self.send(:"#{name}=", nil)
56
+ else
57
+ self.send(:"#{name}=", Time.now)
58
+ end
59
+ end
60
+
61
+ unless options[:without_scopes]
62
+ # create scopes
63
+ self.class_eval do
64
+ scope "#{fun_name}", where("#{my_table_name}.#{name} IS NOT NULL")
65
+ scope "un#{fun_name}", where("#{my_table_name}.#{name} IS NULL")
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+
73
+ def self.included base
74
+ base.extend ClassMethods
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,19 @@
1
+ module Releaf
2
+ module Globalize3
3
+ module Fallbacks
4
+ def self.set
5
+ i18n_fallbacks = {}
6
+
7
+ I18n.default_locale ||= 'en'
8
+ I18n.locale ||= 'en'
9
+
10
+ valid_locales = Settings.i18n_locales || []
11
+
12
+ (valid_locales + [I18n.default_locale, I18n.locale]).uniq.each do |locale|
13
+ i18n_fallbacks[locale] = valid_locales - [locale]
14
+ end
15
+ Globalize.fallbacks = i18n_fallbacks
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,101 @@
1
+ require 'action_dispatch/routing/mapper'
2
+
3
+ module ActionDispatch::Routing
4
+ class Mapper
5
+
6
+ def releaf_resources(*args, &block)
7
+ resources *args do
8
+ yield if block_given?
9
+
10
+ add_urls = true
11
+ add_confirm_destroy = true
12
+
13
+ if args.last.is_a? Hash
14
+ options = args.last
15
+ if options.has_key? :only
16
+ add_urls = false unless options[:only].include? :urls
17
+ add_confirm_destroy = false unless options[:only].include? :destroy
18
+ end
19
+
20
+ if options.has_key? :except
21
+ add_urls = false if options[:except].include? :urls
22
+ add_confirm_destroy = false if options[:except].include? :destroy
23
+ end
24
+ end
25
+
26
+ match :urls, :on => :collection if add_urls
27
+ get :confirm_destroy, :on => :member if add_confirm_destroy
28
+ end
29
+ end
30
+
31
+ def slugged_resources(*args, &block)
32
+ add_routes = {
33
+ :new => true,
34
+ :create => true,
35
+ :edit => true,
36
+ :update => true,
37
+ :show => true,
38
+ :index => true,
39
+ :destroy => true
40
+ }
41
+
42
+ new_resources = args
43
+
44
+ if args.last.is_a? Hash
45
+
46
+ options = new_resources.pop
47
+
48
+ if options.has_key? :only
49
+ add_routes.each_key do |key|
50
+ add_routes[key] = false unless options[:only].include? key
51
+ end
52
+ end
53
+
54
+ if options.has_key? :except
55
+ add_routes.each_key do |key|
56
+ add_routes[key] = false if options[:only].include? key
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ new_resources.each do |resource_name|
63
+ res_name = resource_name.to_s
64
+ get res_name, :to => "#{res_name}#index", :as => res_name if add_routes[:index]
65
+ post res_name, :to => "#{res_name}#create" if add_routes[:create]
66
+ get "#{res_name}/new", :to => "#{res_name}#new", :as => "new_#{res_name.singularize}" if add_routes[:new]
67
+ yield if block_given?
68
+ get "#{res_name}/*slug/edit", :to => "#{res_name}#edit", :as => "edit_#{res_name.singularize}" if add_routes[:edit]
69
+ get "#{res_name}/*slug", :to => "#{res_name}#show", :as => "show_#{res_name.singularize}" if add_routes[:show]
70
+ put "#{res_name}/*slug", :to => "#{res_name}#update" if add_routes[:update]
71
+ post "#{res_name}/*slug", :to => "#{res_name}#create" if add_routes[:create]
72
+ delete "#{res_name}/*slug", :to => "#{res_name}#destroy" if add_routes[:destroy]
73
+ end
74
+
75
+ end
76
+
77
+ def mount_releaf_at mount_location
78
+
79
+ post '/tinymce_assets' => 'releaf/tinymce_assets#create'
80
+
81
+ devise_for Releaf.devise_for, :path => mount_location, :controllers => { :sessions => "releaf/sessions" }
82
+
83
+ scope mount_location do
84
+ namespace :releaf, :path => nil do
85
+
86
+ releaf_resources :admins, :roles
87
+
88
+ releaf_resources :nodes, :controller => "content", :path => "content", :except => [:show], :path_names => { :edit => '' } do
89
+ get :generate_url, :on => :collection
90
+ end
91
+
92
+ releaf_resources :translation_groups, :controller => "translations", :path => "translations", :except => [:show], :path_names => { :edit => '' }
93
+
94
+ root :to => "content#index"
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+ end # class Mapper
101
+ end # module ActionDispatch::Routing
data/lib/releaf/slug.rb CHANGED
@@ -1,79 +1,118 @@
1
1
  module Releaf
2
+ # Provides common methods for finding object by slug. Also overrides to_html
3
+ # method.
4
+ #
5
+ # Simply add this line to your models
6
+ #
7
+ # include Releaf::Slug
8
+ #
9
+ # or
10
+ #
11
+ # ActiveRecord::Base.send(:include, Releaf::Slug)
12
+ #
13
+ # to some initializer (<tt>config/initializers/releaf.rb</tt> for example).
14
+ # Then use find_object or find_object! instead of find
2
15
  module Slug
3
- def self.included(base)
4
- base.class_eval {
16
+ module ClassMethods
5
17
 
6
- def self.find_object id_or_slug, scope=nil
7
- raise ArgumentError unless id_or_slug.is_a?(String) or id_or_slug.is_a?(Fixnum)
18
+ # same as find_object, except that it will raise
19
+ # ActiveRecord::RecordNotFound error if no resource was found.
20
+ def find_object! id_or_slug, scope_name=nil, scope_args=nil
21
+ obj = find_object(id_or_slug, scope_name, scope_args)
22
+ raise ActiveRecord::RecordNotFound unless obj
23
+ return obj
24
+ end
8
25
 
9
- unless self.column_names.include?('slug')
10
- if scope.blank?
11
- return self.find(id_or_slug)
12
- else
13
- return self.send(scope).find(id_or_slug)
14
- end
15
- end
26
+ # Find object by slug or id.
27
+ #
28
+ # If id_or_slug looks like id, then tries to find by id first
29
+ # Otherwise it will search by slug field.
30
+ #
31
+ # If instance responds to children method, then it's possible to search
32
+ # for hierarchic resources
33
+ #
34
+ # @param id_or_slug either id of object to find (can be String or Fixnum)
35
+ # or slug (string) slug, may contain slash ('/')
36
+ #
37
+ # @param scope_name optional scope_name to be used for searching. This is
38
+ # especially useful when you are searching hierarchic resources. For
39
+ # example you want to find 2nd level active resource.
40
+ #
41
+ # @param scope_args any arguments that are required for scope
42
+ #
43
+ # @return resource
44
+ def find_object id_or_slug, scope_name=nil, scope_args=nil
45
+ raise ArgumentError, "id_or_slug must be String or Fixnum" unless id_or_slug.is_a?(String) or id_or_slug.is_a?(Fixnum)
16
46
 
17
- obj = nil
47
+ unless column_names.include?('slug')
48
+ return scoped_for_find_by_slug(self, scope_name, scope_args).find(id_or_slug)
49
+ end
18
50
 
19
- # if it looks like id, search by id
20
- if id_or_slug.to_s =~ /\A\d+\z/
21
- if scope.blank?
22
- obj = self.find_by_id(id_or_slug)
23
- else
24
- obj = self.send(scope).find_by_id(id_or_slug)
25
- end
26
- end
51
+ # if it looks like id, search by id first
52
+ if id_or_slug.to_s =~ /\A\d+\z/
53
+ obj = scoped_for_find_by_slug(self, scope_name, scope_args).find_by_id(id_or_slug)
54
+ return obj if obj
55
+ end
27
56
 
28
- unless obj
29
- unless self.column_names.include?('ancestry')
30
- if scope.blank?
31
- obj = self.find_by_slug(id_or_slug)
32
- else
33
- obj = self.send(scope).find_by_slug(id_or_slug)
34
- end
35
- else
36
- slugs = id_or_slug.split('/')
37
- if scope.blank?
38
- obj = self.find_by_slug( slugs.shift )
39
- else
40
- obj = self.send(scope).find_by_slug( slugs.shift )
41
- end
42
- raise ActiveRecord::RecordNotFound unless obj
43
- slugs.each do |slug_part|
44
- if scope.blank?
45
- obj = obj.children.find_by_slug(slug_part)
46
- else
47
- obj = obj.children.send(scope).find_by_slug(slug_part)
48
- end
49
- raise ActiveRecord::RecordNotFound unless obj
50
- end
51
- end
52
- end
57
+ unless column_names.include?('ancestry') || self.new.respond_to?(:children)
58
+ return scoped_for_find_by_slug(self, scope_name, scope_args).find_by_slug(id_or_slug)
59
+ else
60
+ slugs = id_or_slug.split('/')
53
61
 
54
- raise ActiveRecord::RecordNotFound unless obj
62
+ obj = scoped_for_find_by_slug(self, scope_name, scope_args).find_by_slug( slugs.shift )
63
+ return nil unless obj
64
+ slugs.each do |slug_part|
65
+ obj = scoped_for_find_by_slug(obj.children, scope_name, scope_args).find_by_slug( slug_part )
66
+ return nil unless obj
67
+ end
55
68
  return obj
56
69
  end
70
+ end
57
71
 
58
- def to_param
59
- return id unless self.class.column_names.include?('slug')
60
- return id if self.slug.blank?
61
- col_names = self.class.column_names
72
+ private
62
73
 
63
- if col_names.include?('ancestry')
64
- return path.pluck(:slug).join('/')
65
- elsif col_names.include?('lft') && col_names.include?('rgt') && col_names.include?('parent_id') && self.class.respond_to?(:in_list?)
66
- unless parent_id.blank?
67
- return parent.to_param + '/' + slug
68
- else
69
- return slug
70
- end
74
+ def scoped_for_find_by_slug obj, scope_name=nil, scope_args=nil
75
+ unless scope_name.blank?
76
+ if scope_args.nil?
77
+ obj.send(scope_name.to_sym)
71
78
  else
72
- return slug
79
+ obj.send(scope_name.to_sym, *scope_args)
73
80
  end
81
+ else
82
+ obj
74
83
  end
75
- }
84
+ end
76
85
 
77
86
  end
87
+
88
+
89
+ module InstanceMethods
90
+ # Ovverrides to_param method to prefer slug field over id (when
91
+ # possible). It will also generate hearachical uri part if instance
92
+ # supports parrent method, or has ancestry column (ancestry gem
93
+ # {http://rubygems.org/gems/ancestry})
94
+ #
95
+ # @return String or Fixnum
96
+ def to_param
97
+ return id unless self.class.column_names.include?('slug')
98
+ return id if self.slug.blank?
99
+ col_names = self.class.column_names
100
+
101
+ if col_names.include?('ancestry')
102
+ return path.pluck(:slug).join('/')
103
+ elsif self.respond_to?(:parent) && parent
104
+ return parent.to_param + '/' + slug
105
+ else
106
+ return slug
107
+ end
108
+ end
109
+ end
110
+
111
+
112
+ def self.included base
113
+ base.extend ClassMethods
114
+ include InstanceMethods
115
+ end
116
+
78
117
  end
79
118
  end