releaf 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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