rails_admin 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rails_admin might be problematic. Click here for more details.

Files changed (44) hide show
  1. data/Gemfile +3 -1
  2. data/README.md +8 -1
  3. data/app/assets/javascripts/rails_admin/ra.filtering-multiselect.js +4 -0
  4. data/app/assets/javascripts/rails_admin/ra.filtering-select.js +9 -0
  5. data/app/assets/javascripts/rails_admin/ra.widgets.coffee +13 -1
  6. data/app/assets/javascripts/rails_admin/ui.js.coffee +4 -2
  7. data/app/assets/stylesheets/rails_admin/imports.css.scss.erb +0 -1
  8. data/app/controllers/rails_admin/application_controller.rb +2 -0
  9. data/app/controllers/rails_admin/main_controller.rb +1 -1
  10. data/app/helpers/rails_admin/application_helper.rb +1 -1
  11. data/app/views/layouts/rails_admin/_secondary_navigation.html.haml +2 -2
  12. data/app/views/rails_admin/main/_form_text.html.haml +10 -1
  13. data/app/views/rails_admin/main/index.html.haml +1 -1
  14. data/config/initializers/mongoid_extensions.rb +0 -1
  15. data/lib/rails_admin/adapters/active_record.rb +9 -3
  16. data/lib/rails_admin/adapters/mongoid.rb +23 -7
  17. data/lib/rails_admin/adapters/mongoid/abstract_object.rb +0 -5
  18. data/lib/rails_admin/adapters/mongoid/extension.rb +17 -20
  19. data/lib/rails_admin/config/actions/delete.rb +1 -1
  20. data/lib/rails_admin/config/actions/show.rb +4 -2
  21. data/lib/rails_admin/config/fields/association.rb +6 -6
  22. data/lib/rails_admin/config/fields/types/bson_object_id.rb +5 -2
  23. data/lib/rails_admin/config/fields/types/text.rb +41 -0
  24. data/lib/rails_admin/engine.rb +1 -1
  25. data/lib/rails_admin/extensions/history/history.rb +4 -10
  26. data/lib/rails_admin/version.rb +1 -1
  27. data/spec/controllers/main_controller_spec.rb +8 -1
  28. data/spec/dummy_app/Gemfile +3 -3
  29. data/spec/dummy_app/app/active_record/player.rb +4 -0
  30. data/spec/dummy_app/app/mongoid/player.rb +4 -0
  31. data/spec/dummy_app/app/mongoid/team.rb +1 -1
  32. data/spec/dummy_app/app/mongoid/user.rb +2 -2
  33. data/spec/dummy_app/config/initializers/devise.rb +2 -9
  34. data/spec/dummy_app/config/initializers/dragonfly.rb +1 -4
  35. data/spec/dummy_app/config/mongoid.yml +11 -0
  36. data/spec/integration/basic/destroy/rails_admin_basic_destroy_spec.rb +11 -3
  37. data/spec/integration/config/edit/rails_admin_config_edit_spec.rb +20 -0
  38. data/spec/integration/config/show/rails_admin_config_show_spec.rb +18 -0
  39. data/spec/integration/history/rails_admin_history_spec.rb +6 -0
  40. data/spec/integration/rails_admin_spec.rb +18 -0
  41. data/spec/orm/mongoid.rb +2 -0
  42. data/spec/unit/adapters/active_record_spec.rb +3 -3
  43. data/spec/unit/adapters/mongoid_spec.rb +65 -4
  44. metadata +8 -2
data/Gemfile CHANGED
@@ -36,13 +36,15 @@ group :mongoid do
36
36
  case ENV['CI_ORM_VERSION']
37
37
  when 'head'
38
38
  gem 'mongoid', :git => 'git://github.com/mongoid/mongoid.git'
39
+ gem 'mongoid-paperclip', :require => 'mongoid_paperclip', :git => 'git://github.com/mshibuya/mongoid-paperclip.git', :branch => 'fix-stop-patching-logger'
39
40
  # For now, carrierwave-mongoid's mongoid dependency is restricted to '~> 2.1'
40
41
  gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid', :git => 'git://github.com/tanordheim/carrierwave-mongoid.git', :branch => 'mongoid_3_0'
42
+ gem 'database_cleaner', :git => 'git://github.com/potatosalad/database_cleaner.git'
41
43
  else
42
44
  gem 'mongoid'
45
+ gem 'mongoid-paperclip', :require => 'mongoid_paperclip'
43
46
  gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'
44
47
  end
45
- gem 'mongoid-paperclip', :require => 'mongoid_paperclip'
46
48
  end
47
49
 
48
50
  group :debug do
data/README.md CHANGED
@@ -58,7 +58,10 @@ And then run:
58
58
 
59
59
  This generator will install RailsAdmin and [Devise](https://github.com/plataformatec/devise) if you
60
60
  don't already have it installed. [Devise](https://github.com/plataformatec/devise) is strongly
61
- recommended to protect your data from anonymous users.
61
+ recommended to protect your data from anonymous users. Note: If you do not already have [Devise](https://github.com/plataformatec/devise)
62
+ installed, make sure you remove the registerable module from the generated user model.
63
+
64
+
62
65
  It will modify your `config/routes.rb`, adding:
63
66
 
64
67
  ```ruby
@@ -67,6 +70,10 @@ mount RailsAdmin::Engine => '/admin', :as => 'rails_admin' # Feel free to change
67
70
 
68
71
  It will also add an intializer that will help you getting started. (head for config/initializers/rails_admin.rb)
69
72
 
73
+ Finally run:
74
+
75
+ $ bundle exec rake db:migrate
76
+
70
77
  Optionally, you may wish to set up [Cancan](https://github.com/ryanb/cancan),
71
78
  [PaperTrail](https://github.com/airblade/paper_trail), [CKeditor](https://github.com/galetahub/ckeditor)
72
79
 
@@ -103,24 +103,28 @@
103
103
  this.addAll.click(function(e){
104
104
  widget._select($('option', widget.collection));
105
105
  e.preventDefault();
106
+ widget.selection.trigger('change');
106
107
  });
107
108
 
108
109
  /* Add to selection */
109
110
  this.add.click(function(e){
110
111
  widget._select($(':selected', widget.collection));
111
112
  e.preventDefault();
113
+ widget.selection.trigger('change');
112
114
  });
113
115
 
114
116
  /* Remove all from selection */
115
117
  this.removeAll.click(function(e){
116
118
  widget._deSelect($('option', widget.selection));
117
119
  e.preventDefault();
120
+ widget.selection.trigger('change');
118
121
  });
119
122
 
120
123
  /* Remove from selection */
121
124
  this.remove.click(function(e){
122
125
  widget._deSelect($(':selected', widget.selection));
123
126
  e.preventDefault();
127
+ widget.selection.trigger('change');
124
128
  });
125
129
 
126
130
  var timeout = null;
@@ -52,6 +52,7 @@
52
52
  select: function(event, ui) {
53
53
  var option = $('<option value="' + ui.item.id + '" selected="selected">' + ui.item.value + '</option>');
54
54
  select.html(option);
55
+ select.trigger("change", ui.item.id);
55
56
  self._trigger("selected", event, {
56
57
  item: option
57
58
  });
@@ -79,6 +80,14 @@
79
80
  }
80
81
  }
81
82
  })
83
+ .keyup(function() {
84
+ /* Clear select options and trigger change if selected item is deleted */
85
+ if ($(this).val().length == 0) {
86
+ select.empty();
87
+ select.trigger("change");
88
+ }
89
+ })
90
+
82
91
  if(select.attr('placeholder'))
83
92
  input.attr('placeholder', select.attr('placeholder'))
84
93
 
@@ -125,11 +125,23 @@ $(document).live 'rails_admin.dom_ready', ->
125
125
  # ckeditor
126
126
 
127
127
  $('form [data-richtext=ckeditor]').not('.ckeditored').each ->
128
- window.CKEDITOR_BASEPATH = '/assets/ckeditor/'
129
128
  options = $(this).data('options')
129
+ window.CKEDITOR_BASEPATH = options['base_location']
130
130
  if not window.CKEDITOR
131
131
  $(window.document).append('<script src="' + options['jspath'] + '"><\/script>')
132
132
  if instance = window.CKEDITOR.instances[this.id]
133
133
  instance.destroy(true)
134
134
  window.CKEDITOR.replace(this, options['options'])
135
135
  $(this).addClass('ckeditored')
136
+
137
+ #codemirror
138
+
139
+ $('form [data-richtext=codemirror]').not('.codemirrored').each ->
140
+ options = $(this).data('options')
141
+ if not window.CodeMirror
142
+ $(window.document).append('<script src="' + options['jspath'] + '" type="text\/javascript"><\/script>')
143
+ $('head').append('<script src="' + options['locations']['mode'] + '" type="text\/javascript"><\/script>')
144
+ $('head').append('<link href="' + options['csspath'] + '" rel="stylesheet" media="all" type="text\/css">')
145
+ $('head').append('<link href="' + options['locations']['theme'] + '" rel="stylesheet" media="all" type="text\/css">')
146
+ CodeMirror.fromTextArea(this,{mode:options['options']['mode'],theme:options['options']['theme']})
147
+ $(this).addClass('codemirrored')
@@ -4,7 +4,9 @@ $("#list input.toggle").live "click", ->
4
4
  $("#list [name='bulk_ids[]']").attr "checked", $(this).is(":checked")
5
5
 
6
6
  $('.pjax').live 'click', (event) ->
7
- if $.support.pjax
7
+ if event.which > 1 || event.metaKey || event.ctrlKey
8
+ return
9
+ else if $.support.pjax
8
10
  event.preventDefault()
9
11
  $.pjax
10
12
  container: $(this).data('pjax-container') || '[data-pjax-container]'
@@ -24,7 +26,7 @@ $('.pjax-form').live 'submit', (event) ->
24
26
  $(document)
25
27
  .on 'pjax:start', ->
26
28
  $('#loading').show()
27
- .on 'pjax:end', ->
29
+ .on 'pjax:end', ->
28
30
  $('#loading').hide()
29
31
 
30
32
  $('[data-target]').live 'click', ->
@@ -34,7 +34,6 @@
34
34
  @import "bootstrap/grid";
35
35
  @import "bootstrap/layouts";
36
36
  @import "bootstrap/type";
37
- @import "bootstrap/code";
38
37
  @import "bootstrap/forms";
39
38
  @import "bootstrap/tables";
40
39
  @import "bootstrap/sprites";
@@ -55,6 +55,8 @@ module RailsAdmin
55
55
  instance_eval &RailsAdmin::Config.current_user_method
56
56
  end
57
57
 
58
+ alias_method :user_for_paper_trail, :_current_user
59
+
58
60
  def _attr_accessible_role
59
61
  instance_eval &RailsAdmin::Config.attr_accessible_role
60
62
  end
@@ -123,7 +123,7 @@ module RailsAdmin
123
123
  options = {}
124
124
  options = options.merge(:page => (params[:page] || 1).to_i, :per => (params[:per] || model_config.list.items_per_page)) if pagination
125
125
  options = options.merge(:include => associations) unless associations.blank?
126
- options = options.merge(get_sort_hash(model_config)) unless params[:associated_collection]
126
+ options = options.merge(get_sort_hash(model_config))
127
127
  options = options.merge(:query => params[:query]) if params[:query].present?
128
128
  options = options.merge(:filters => params[:f]) if params[:f].present?
129
129
  options = options.merge(:bulk_ids => params[:bulk_ids]) if params[:bulk_ids]
@@ -114,7 +114,7 @@ module RailsAdmin
114
114
  content_tag(:ul, :class => 'dropdown-menu', :style => 'left:auto; right:0;') do
115
115
  actions.map do |action|
116
116
  content_tag :li do
117
- link_to_function wording_for(:bulk_link, action), "jQuery('#bulk_action').val('#{action.action_name}'); jQuery('#bulk_form').submit()"
117
+ link_to wording_for(:bulk_link, action), '#', :onclick => "jQuery('#bulk_action').val('#{action.action_name}'); jQuery('#bulk_form').submit(); return false;"
118
118
  end
119
119
  end.join.html_safe
120
120
  end
@@ -2,11 +2,11 @@
2
2
  - actions(:root).each do |action|
3
3
  %li= link_to wording_for(:menu, action), { :action => action.action_name, :controller => 'rails_admin/main' }, :class => 'pjax'
4
4
  - if main_app_root_path = (main_app.root_path rescue false)
5
- %li= link_to t('home.name').capitalize, main_app_root_path, :class => 'pjax'
5
+ %li= link_to t('home.name').capitalize, main_app_root_path
6
6
  - if _current_user
7
7
  - if user_link = edit_user_link
8
8
  %li= user_link
9
9
  - if defined?(Devise) && (devise_scope = request.env["warden"].config[:default_scope] rescue false) && (logout_path = main_app.send("destroy_#{devise_scope}_session_path") rescue false)
10
10
  %li= link_to content_tag('span', t('admin.misc.log_out'), :class => 'label label-important'), logout_path, :method => Devise.sign_out_via
11
- - if _current_user.respond_to?(:email)
11
+ - if _current_user.respond_to?(:email) && _current_user.email.present?
12
12
  %li= image_tag "#{(request.ssl? ? 'https://secure' : 'http://www')}.gravatar.com/avatar/#{Digest::MD5.hexdigest _current_user.email}?s=30", :style => 'padding-top:5px'
@@ -2,11 +2,20 @@
2
2
  if field.ckeditor
3
3
  richtext = 'ckeditor'
4
4
  js_data = {
5
- :jspath => '/assets/ckeditor/ckeditor.js',
5
+ :jspath => field.ckeditor_location,
6
+ :base_location => field.ckeditor_base_location,
6
7
  :options => {
7
8
  :customConfig => field.ckeditor_config_js
8
9
  }
9
10
  }
11
+ elsif field.codemirror
12
+ richtext = 'codemirror'
13
+ js_data = {
14
+ :csspath => field.codemirror_css_location,
15
+ :jspath => field.codemirror_js_location,
16
+ :options => field.codemirror_config,
17
+ :locations => field.codemirror_assets
18
+ }
10
19
  else
11
20
  richtext = false
12
21
  js_data = {}
@@ -132,7 +132,7 @@
132
132
  %td.last.links
133
133
  %ul.inline= menu_for :member, @abstract_model, object, true
134
134
  - if @objects.respond_to?(:total_count)
135
- - total_count = @objects.total_count
135
+ - total_count = @objects.total_count.to_i
136
136
  = paginate(@objects, :theme => 'twitter-bootstrap', :remote => true)
137
137
  = link_to(t("admin.misc.show_all"), index_path(params.merge(:all => true)), :class => "show-all btn clearfix pjax") unless total_count > 100 || total_count <= @objects.to_a.size
138
138
  .clearfix.total-count= "#{total_count} #{@model_config.label_plural.downcase}"
@@ -1,5 +1,4 @@
1
1
  if defined?(::Mongoid::Document)
2
2
  require 'rails_admin/adapters/mongoid/extension'
3
3
  Mongoid::Document.send(:include, RailsAdmin::Adapters::Mongoid::Extension)
4
- Mongoid::NestedAttributes::ClassMethods.send(:include, RailsAdmin::Adapters::Mongoid::NestedAttributesExtension)
5
4
  end
@@ -5,8 +5,14 @@ module RailsAdmin
5
5
  module Adapters
6
6
  module ActiveRecord
7
7
  DISABLED_COLUMN_TYPES = [:tsvector, :blob, :binary, :spatial, :hstore]
8
- AR_ADAPTER = ::ActiveRecord::Base.configurations[Rails.env]['adapter']
9
- LIKE_OPERATOR = AR_ADAPTER == "postgresql" ? 'ILIKE' : 'LIKE'
8
+
9
+ def ar_adapter
10
+ Rails.configuration.database_configuration[Rails.env]['adapter']
11
+ end
12
+
13
+ def like_operator
14
+ ar_adapter == "postgresql" ? 'ILIKE' : 'LIKE'
15
+ end
10
16
 
11
17
  def new(params = {})
12
18
  AbstractObject.new(model.new(params))
@@ -184,7 +190,7 @@ module RailsAdmin
184
190
  else
185
191
  return
186
192
  end
187
- ["(#{column} #{LIKE_OPERATOR} ?)", value]
193
+ ["(#{column} #{like_operator} ?)", value]
188
194
  when :date
189
195
  start_date, end_date = get_filtering_duration(operator, value)
190
196
 
@@ -15,8 +15,13 @@ module RailsAdmin
15
15
  def get(id)
16
16
  begin
17
17
  AbstractObject.new(model.find(id))
18
- rescue BSON::InvalidObjectId, ::Mongoid::Errors::DocumentNotFound
19
- nil
18
+ rescue => e
19
+ if ['BSON::InvalidObjectId', 'Mongoid::Errors::DocumentNotFound',
20
+ 'Mongoid::Errors::InvalidFind', 'Moped::Errors::InvalidObjectId'].include? e.class.to_s
21
+ nil
22
+ else
23
+ raise e
24
+ end
20
25
  end
21
26
  end
22
27
 
@@ -82,6 +87,7 @@ module RailsAdmin
82
87
  "BigDecimal" => { :type => :decimal },
83
88
  "Boolean" => { :type => :boolean },
84
89
  "BSON::ObjectId" => { :type => :bson_object_id, :serial? => (name == primary_key) },
90
+ "Moped::BSON::ObjectId" => { :type => :bson_object_id, :serial? => (name == primary_key) },
85
91
  "Date" => { :type => :date },
86
92
  "DateTime" => { :type => :datetime },
87
93
  "Float" => { :type => :float },
@@ -118,7 +124,7 @@ module RailsAdmin
118
124
  end
119
125
 
120
126
  def table_name
121
- model.collection.name
127
+ model.collection_name.to_s
122
128
  end
123
129
 
124
130
  def serialized_attributes
@@ -143,7 +149,7 @@ module RailsAdmin
143
149
  fields.each do |field|
144
150
  conditions_per_collection = {}
145
151
  field.searchable_columns.flatten.each do |column_infos|
146
- collection_name, column_name = column_infos[:column].split('.')
152
+ collection_name, column_name = parse_collection_name(column_infos[:column])
147
153
  statement = build_statement(column_name, column_infos[:type], query, field.search_operator)
148
154
  if statement
149
155
  conditions_per_collection[collection_name] ||= []
@@ -171,7 +177,7 @@ module RailsAdmin
171
177
  field = fields.find{|f| f.name.to_s == field_name}
172
178
  next unless field
173
179
  field.searchable_columns.each do |column_infos|
174
- collection_name, column_name = column_infos[:column].split('.')
180
+ collection_name, column_name = parse_collection_name(column_infos[:column])
175
181
  statement = build_statement(column_name, column_infos[:type], filter_dump[:v], (filter_dump[:o] || 'default'))
176
182
  if statement
177
183
  conditions_per_collection[collection_name] ||= []
@@ -261,7 +267,7 @@ module RailsAdmin
261
267
  return if value.blank?
262
268
  { column => { "$in" => Array.wrap(value) } }
263
269
  when :belongs_to_association, :bson_object_id
264
- object_id = (BSON::ObjectId(value) rescue nil)
270
+ object_id = (BSON::ObjectId.from_string(value) rescue nil)
265
271
  { column => object_id } if object_id
266
272
  end
267
273
  end
@@ -337,7 +343,8 @@ module RailsAdmin
337
343
 
338
344
  def length_validation_lookup(name)
339
345
  shortest = model.validators.select do |validator|
340
- validator.attributes.include?(name.to_sym) &&
346
+ validator.respond_to?(:attributes) &&
347
+ validator.attributes.include?(name.to_sym) &&
341
348
  validator.kind == :length &&
342
349
  validator.options[:maximum]
343
350
  end.min{|a, b| a.options[:maximum] <=> b.options[:maximum] }
@@ -348,6 +355,15 @@ module RailsAdmin
348
355
  end
349
356
  end
350
357
 
358
+ def parse_collection_name(column)
359
+ collection_name, column_name = column.split('.')
360
+ if [:embeds_one, :embeds_many].include?(model.associations[collection_name].try(:macro).try(:to_sym))
361
+ [table_name, column]
362
+ else
363
+ [collection_name, column_name]
364
+ end
365
+ end
366
+
351
367
  def make_condition_for_current_collection(target_field, conditions_per_collection)
352
368
  result =[]
353
369
  conditions_per_collection.each do |collection_name, conditions|
@@ -37,11 +37,6 @@ RUBY
37
37
  end
38
38
  end
39
39
  end
40
-
41
- def destroy
42
- object.destroy
43
- object
44
- end
45
40
  end
46
41
  end
47
42
  end
@@ -5,8 +5,13 @@ module RailsAdmin
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- def self.rails_admin(&block)
9
- RailsAdmin::Config.model(self, &block)
8
+ class_attribute :nested_attributes_options
9
+ self.nested_attributes_options = {}
10
+ class << self
11
+ def rails_admin(&block)
12
+ RailsAdmin::Config.model(self, &block)
13
+ end
14
+ alias_method_chain :accepts_nested_attributes_for, :rails_admin
10
15
  end
11
16
  end
12
17
 
@@ -21,26 +26,18 @@ module RailsAdmin
21
26
  self.send(value)
22
27
  end
23
28
  end
24
- end
25
-
26
- module NestedAttributesExtension
27
- extend ActiveSupport::Concern
28
-
29
- included do
30
- attr_reader :nested_attributes_options
31
- alias_method_chain :accepts_nested_attributes_for, :rails_admin
32
- end
33
29
 
34
- # Mongoid accepts_nested_attributes_for does not store options in accessible scope,
35
- # so we intercept the call and store it in instance variable which can be accessed from outside
36
- def accepts_nested_attributes_for_with_rails_admin(*args)
37
- @nested_attributes_options ||= {}
38
- options = args.extract_options!
39
- args.each do |arg|
40
- @nested_attributes_options[arg.to_sym] = options.reverse_merge(:allow_destroy=>false, :update_only=>false)
30
+ module ClassMethods
31
+ # Mongoid accepts_nested_attributes_for does not store options in accessible scope,
32
+ # so we intercept the call and store it in instance variable which can be accessed from outside
33
+ def accepts_nested_attributes_for_with_rails_admin(*args)
34
+ options = args.extract_options!
35
+ args.each do |arg|
36
+ self.nested_attributes_options[arg.to_sym] = options.reverse_merge(:allow_destroy=>false, :update_only=>false)
37
+ end
38
+ args << options
39
+ accepts_nested_attributes_for_without_rails_admin(*args)
41
40
  end
42
- args << options
43
- accepts_nested_attributes_for_without_rails_admin(*args)
44
41
  end
45
42
  end
46
43
  end
@@ -32,7 +32,7 @@ module RailsAdmin
32
32
  elsif request.delete? # DESTROY
33
33
 
34
34
  @auditing_adapter && @auditing_adapter.delete_object("Destroyed #{@model_config.with(:object => @object).object_label}", @object, @abstract_model, _current_user)
35
- if @abstract_model.destroy(@object)
35
+ if @object.destroy
36
36
  flash[:success] = t("admin.flash.successful", :name => @model_config.label, :action => t("admin.actions.delete.done"))
37
37
  else
38
38
  flash[:error] = t("admin.flash.error", :name => @model_config.label, :action => t("admin.actions.delete.done"))
@@ -18,11 +18,13 @@ module RailsAdmin
18
18
 
19
19
  register_instance_option :controller do
20
20
  Proc.new do
21
- render @action.template_name
21
+ respond_to do |format|
22
+ format.json { render :json => @object }
23
+ format.html { render @action.template_name }
24
+ end
22
25
  end
23
26
  end
24
27
 
25
-
26
28
  register_instance_option :link_icon do
27
29
  'icon-info-sign'
28
30
  end
@@ -47,7 +47,12 @@ module RailsAdmin
47
47
  scope.limit(associated_collection_scope_limit)
48
48
  end
49
49
  end
50
-
50
+
51
+ # inverse relationship
52
+ register_instance_option :inverse_of do
53
+ association[:inverse_of]
54
+ end
55
+
51
56
  # preload entire associated collection (per associated_collection_scope) on load
52
57
  # Be sure to set limit in associated_collection_scope if set is large
53
58
  register_instance_option :associated_collection_cache_all do
@@ -73,11 +78,6 @@ module RailsAdmin
73
78
  def foreign_key
74
79
  association[:foreign_key]
75
80
  end
76
-
77
- # Reader for the inverse relationship
78
- def inverse_of
79
- association[:inverse_of]
80
- end
81
81
 
82
82
  # Reader whether this is a polymorphic association
83
83
  def polymorphic?
@@ -28,8 +28,11 @@ module RailsAdmin
28
28
 
29
29
  def parse_input(params)
30
30
  begin
31
- params[name] = (params[name].blank? ? nil : BSON::ObjectId(params[name])) if params[name].is_a?(::String)
32
- rescue BSON::InvalidObjectId
31
+ params[name] = (params[name].blank? ? nil : BSON::ObjectId.from_string(params[name])) if params[name].is_a?(::String)
32
+ rescue => e
33
+ unless ['BSON::InvalidObjectId', 'Moped::Errors::InvalidObjectId'].include? e.class.to_s
34
+ raise e
35
+ end
33
36
  end
34
37
  end
35
38
  end
@@ -19,6 +19,47 @@ module RailsAdmin
19
19
  "/assets/ckeditor/config.js"
20
20
  end
21
21
 
22
+ #Use this if you want to point to a cloud instances of CKeditor
23
+ register_instance_option(:ckeditor_location) do
24
+ '/assets/ckeditor/ckeditor.js'
25
+ end
26
+
27
+ #Use this if you want to point to a cloud instances of the base CKeditor
28
+ register_instance_option(:ckeditor_base_location) do
29
+ '/assets/ckeditor/'
30
+ end
31
+
32
+ # Codemirror is disabled by default and CKEditor takes precedence
33
+ register_instance_option(:codemirror) do
34
+ false
35
+ end
36
+
37
+ #Pass the theme and mode for Codemirror
38
+ register_instance_option(:codemirror_config) do
39
+ {
40
+ :mode => 'css',
41
+ :theme => 'night'
42
+ }
43
+ end
44
+
45
+ #Pass the location of the theme and mode for Codemirror
46
+ register_instance_option(:codemirror_assets) do
47
+ {
48
+ :mode => '/assets/codemirror/modes/css.js',
49
+ :theme => '/assets/codemirror/themes/night.css'
50
+ }
51
+ end
52
+
53
+ #Use this if you want to point to a cloud instances of CodeMirror
54
+ register_instance_option(:codemirror_js_location) do
55
+ '/assets/codemirror.js'
56
+ end
57
+
58
+ #Use this if you want to point to a cloud instances of CodeMirror
59
+ register_instance_option(:codemirror_css_location) do
60
+ '/assets/codemirror.css'
61
+ end
62
+
22
63
  register_instance_option(:html_attributes) do
23
64
  {
24
65
  :cols => "48",
@@ -11,7 +11,7 @@ require 'rails_admin'
11
11
  module RailsAdmin
12
12
  class Engine < Rails::Engine
13
13
  isolate_namespace RailsAdmin
14
- initializer "RailsAdmin precompile hook" do |app|
14
+ initializer "RailsAdmin precompile hook", :group => :assets do |app|
15
15
  app.config.assets.precompile += ['rails_admin/rails_admin.js', 'rails_admin/rails_admin.css', 'rails_admin/jquery.colorpicker.js', 'rails_admin/jquery.colorpicker.css']
16
16
  end
17
17
 
@@ -5,6 +5,8 @@ class RailsAdmin::History < ActiveRecord::Base
5
5
 
6
6
  attr_accessible :message, :item, :table, :username
7
7
 
8
+ default_scope order('id DESC')
9
+
8
10
  def self.latest
9
11
  self.limit(100)
10
12
  end
@@ -49,22 +51,14 @@ class RailsAdmin::History < ActiveRecord::Base
49
51
  def self.history_for_model(model, query, sort, sort_reverse, all, page, per_page = (RailsAdmin::Config.default_items_per_page || 20))
50
52
  history = where(:table => model.pretty_name)
51
53
  history = history.where("message LIKE ? OR username LIKE ?", "%#{query}%", "%#{query}%") if query
52
- if sort
53
- history = history.order(sort_reverse == "true" ? "#{sort} DESC" : sort)
54
- else
55
- history = history.order('created_at DESC')
56
- end
54
+ history = history.order(sort_reverse == "true" ? "#{sort} DESC" : sort) if sort
57
55
  all ? history : history.send(Kaminari.config.page_method_name, page.presence || "1").per(per_page)
58
56
  end
59
57
 
60
58
  def self.history_for_object(model, object, query, sort, sort_reverse, all, page, per_page = (RailsAdmin::Config.default_items_per_page || 20))
61
59
  history = where(:table => model.pretty_name, :item => object.id)
62
60
  history = history.where("message LIKE ? OR username LIKE ?", "%#{query}%", "%#{query}%") if query
63
- if sort
64
- history = history.order(sort_reverse == "true" ? "#{sort} DESC" : sort)
65
- else
66
- history = history.order('created_at DESC')
67
- end
61
+ history = history.order(sort_reverse == "true" ? "#{sort} DESC" : sort) if sort
68
62
  all ? history : history.send(Kaminari.config.page_method_name, page.presence || "1").per(per_page)
69
63
  end
70
64
  end
@@ -1,3 +1,3 @@
1
1
  module RailsAdmin
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -67,7 +67,7 @@ describe RailsAdmin::MainController do
67
67
  end
68
68
 
69
69
  it "scopes associated collection records according to bindings" do
70
- @team.revenue = 3
70
+ @team.revenue = BigDecimal.new('3')
71
71
  @team.save
72
72
 
73
73
  @players = 5.times.map do
@@ -107,7 +107,14 @@ describe RailsAdmin::MainController do
107
107
  end
108
108
  end
109
109
  controller.list_entries.length.should == @players.size
110
+ end
111
+
112
+ it "orders associated collection records by desc" do
113
+ @players = 3.times.map do
114
+ FactoryGirl.create :player
115
+ end
110
116
 
117
+ controller.list_entries.to_a.first.should == @players.last
111
118
  end
112
119
  end
113
120
 
@@ -28,7 +28,7 @@ group :active_record do
28
28
  gem 'sqlite3', '~> 1.3'
29
29
  end
30
30
  end
31
- gem 'paperclip', '~> 2.4'
31
+ gem 'paperclip', '~> 2.7'
32
32
  gem 'carrierwave'
33
33
  gem 'dragonfly'
34
34
  end
@@ -44,8 +44,8 @@ group :mongoid do
44
44
  gem 'mongoid'
45
45
  gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'
46
46
  end
47
- gem 'mongoid-paperclip', :require => 'mongoid_paperclip'
48
- gem 'paperclip', '~> 2.4'
47
+ gem 'mongoid-paperclip', :require => 'mongoid_paperclip', :git => 'git://github.com/mshibuya/mongoid-paperclip.git', :branch => 'fix-stop-patching-logger'
48
+ gem 'paperclip', '~> 2.7'
49
49
  gem 'dragonfly'
50
50
  end
51
51
 
@@ -13,6 +13,10 @@ class Player < ActiveRecord::Base
13
13
  record.errors.add(:base, "Player is cheating") if value.to_s =~ /on steroids/
14
14
  end
15
15
 
16
+ before_destroy :destroy_hook
17
+
18
+ def destroy_hook; end
19
+
16
20
  def draft_id
17
21
  self.draft.try :id
18
22
  end
@@ -27,6 +27,10 @@ class Player
27
27
  has_one :draft, :dependent => :destroy
28
28
  has_many :comments, :as => :commentable
29
29
 
30
+ before_destroy :destroy_hook
31
+
32
+ def destroy_hook; end
33
+
30
34
  def draft_id
31
35
  self.draft.try :id
32
36
  end
@@ -20,7 +20,7 @@ class Team
20
20
 
21
21
  attr_accessible :name, :division_id, :logo_url, :manager, :ballpark, :mascot, :founded, :wins, :losses, :win_percentage, :revenue, :color, :custom_field, :fan_ids, :player_ids, :comment_ids
22
22
 
23
- has_many :players, :inverse_of => :team, :order => :_id
23
+ has_many :players, :inverse_of => :team, :order => :_id.asc
24
24
  has_and_belongs_to_many :fans
25
25
  has_many :comments, :as => :commentable
26
26
 
@@ -6,8 +6,8 @@ class User
6
6
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
7
7
 
8
8
  ## Database authenticatable
9
- field :email, :type => String, :null => false
10
- field :encrypted_password, :type => String, :null => false
9
+ field :email, :type => String
10
+ field :encrypted_password, :type => String
11
11
 
12
12
  ## Recoverable
13
13
  field :reset_password_token, :type => String
@@ -9,9 +9,6 @@ Devise.setup do |config|
9
9
  # Configure the class responsible to send e-mails.
10
10
  # config.mailer = "Devise::Mailer"
11
11
 
12
- # Automatically apply schema changes in tableless databases
13
- config.apply_schema = false
14
-
15
12
  # ==> ORM configuration
16
13
  # Load and configure the ORM. Supports :active_record (default) and
17
14
  # :mongoid (bson_ext recommended) by default. Other ORMs may be
@@ -95,7 +92,7 @@ Devise.setup do |config|
95
92
  # the user cannot access the website without confirming his account.
96
93
  # config.allow_unconfirmed_access_for = 2.days
97
94
 
98
- # If true, requires any email changes to be confirmed (exctly the same way as
95
+ # If true, requires any email changes to be confirmed (exactly the same way as
99
96
  # initial account confirmation) to be applied. Requires additional unconfirmed_email
100
97
  # db field (see migrations). Until confirmed new email is stored in
101
98
  # unconfirmed email column, and copied to email column on successful confirmation.
@@ -111,13 +108,9 @@ Devise.setup do |config|
111
108
  # If true, extends the user's remember period when remembered via cookie.
112
109
  # config.extend_remember_period = false
113
110
 
114
- # If true, uses the password salt as remember token. This should be turned
115
- # to false if you are not using database authenticatable.
116
- config.use_salt_as_remember_token = true
117
-
118
111
  # Options to be passed to the created cookie. For instance, you can set
119
112
  # :secure => true in order to force SSL only cookies.
120
- # config.cookie_options = {}
113
+ # config.rememberable_options = {}
121
114
 
122
115
  # ==> Configuration for :validatable
123
116
  # Range for password length. Default is 6..128.
@@ -3,11 +3,8 @@ if defined?(Mongoid::Document)
3
3
 
4
4
  app = Dragonfly[:images]
5
5
 
6
- # Configure to use ImageMagick, Rails defaults, and the Mongo data store
6
+ # Configure to use ImageMagick, Rails defaults
7
7
  app.configure_with(:imagemagick)
8
- app.configure_with(:rails) do |c|
9
- c.datastore = Dragonfly::DataStorage::MongoDataStore.new :db => Mongoid.database
10
- end
11
8
 
12
9
  # Allow all mongoid models to use the macro 'image_accessor'
13
10
  app.define_macro_on_include(Mongoid::Document, :image_accessor)
@@ -5,7 +5,18 @@ defaults: &defaults
5
5
  development:
6
6
  <<: *defaults
7
7
  database: dummy_app_development
8
+ sessions:
9
+ default:
10
+ database: dummy_app_development
11
+ hosts:
12
+ - localhost:27017
13
+
8
14
 
9
15
  test:
10
16
  <<: *defaults
11
17
  database: dummy_app_test
18
+ sessions:
19
+ default:
20
+ database: dummy_app_test
21
+ hosts:
22
+ - localhost:27017
@@ -15,19 +15,27 @@ describe "RailsAdmin Basic Destroy" do
15
15
  it "should destroy an object" do
16
16
  @player.should be_nil
17
17
  end
18
+
19
+ it "should show success message" do
20
+ should have_content('Player successfully deleted')
21
+ end
18
22
  end
19
23
 
20
- describe "destroy with errors" do
24
+ describe "handle destroy errors" do
21
25
  before(:each) do
22
- Player.any_instance.stub(:destroy).and_return false
26
+ Player.any_instance.stub(:destroy_hook).and_return false
23
27
  @player = FactoryGirl.create :player
24
28
  visit delete_path(:model_name => "player", :id => @player.id)
25
29
  click_button "Yes, I'm sure"
26
30
  end
27
31
 
28
- it "should destroy an object" do
32
+ it "should not destroy an object" do
29
33
  @player.reload.should be
30
34
  end
35
+
36
+ it "should show error message" do
37
+ should have_content('Player failed to be deleted')
38
+ end
31
39
  end
32
40
 
33
41
  describe "destroy" do
@@ -918,6 +918,26 @@ describe "RailsAdmin Config DSL Edit Section" do
918
918
  end
919
919
  end
920
920
 
921
+ describe "CodeMirror Support" do
922
+
923
+ it "should start with CodeMirror disabled" do
924
+ field = RailsAdmin::config("Draft").edit.fields.find{|f| f.name == :notes}
925
+ field.codemirror.should be false
926
+ end
927
+
928
+ it "should add Javascript to enable CodeMirror" do
929
+ RailsAdmin.config Draft do
930
+ edit do
931
+ field :notes do
932
+ codemirror true
933
+ end
934
+ end
935
+ end
936
+ visit new_path(:model_name => "draft")
937
+ should have_selector('textarea#draft_notes[data-richtext="codemirror"]')
938
+ end
939
+ end
940
+
921
941
  describe "Paperclip Support" do
922
942
 
923
943
  it "should show a file upload field" do
@@ -13,6 +13,24 @@ describe "RailsAdmin Config DSL Show Section" do
13
13
  visit show_path(:model_name => "team", :id => team.id)
14
14
  end
15
15
 
16
+ describe "JSON show view" do
17
+ before do
18
+ @player = FactoryGirl.create :player
19
+ visit uri
20
+ end
21
+
22
+ let(:uri) { show_path(:model_name => 'player', :id => @player.id, :format => :json) }
23
+ let(:body) { page.body }
24
+
25
+ it 'should create a JSON uri' do
26
+ uri.should == "/admin/player/#{@player.id}.json"
27
+ end
28
+
29
+ it 'should contain the JSONified object' do
30
+ body.should include(@player.to_json)
31
+ end
32
+ end
33
+
16
34
  describe "compact_show_view" do
17
35
 
18
36
  it 'should hide empty fields in show view by default' do
@@ -72,6 +72,12 @@ describe "RailsAdmin History", :active_record => true do
72
72
  RailsAdmin::History.latest.count.should == 100
73
73
  end
74
74
 
75
+ it 'should get latest ones orderly' do
76
+ latest = RailsAdmin::History.latest
77
+ latest.first.message.should == "change 100"
78
+ latest.last.message.should == "change 1"
79
+ end
80
+
75
81
  it "should render a XHR request successfully" do
76
82
  xhr :get, history_index_path(@model, :page => 2)
77
83
  end
@@ -121,4 +121,22 @@ describe "RailsAdmin" do
121
121
  end
122
122
  end
123
123
 
124
+ describe "secondary navigation" do
125
+ it "should have Gravatar image" do
126
+ visit dashboard_path
127
+ should have_selector("ul.nav.pull-right li img")
128
+ end
129
+
130
+ it "should not show Gravatar when user doesn't have email method" do
131
+ User.any_instance.stub(:respond_to?).with(:email).and_return(false)
132
+ visit dashboard_path
133
+ should_not have_selector("ul.nav.pull-right li img")
134
+ end
135
+
136
+ it "should not cause error when email is nil" do
137
+ User.any_instance.stub(:email).and_return(nil)
138
+ visit dashboard_path
139
+ should have_selector("body.rails_admin")
140
+ end
141
+ end
124
142
  end
data/spec/orm/mongoid.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'rails_admin/adapters/mongoid'
2
2
 
3
+ Paperclip.logger = Logger.new(nil)
4
+
3
5
  class Tableless
4
6
  include Mongoid::Document
5
7
 
@@ -179,8 +179,8 @@ describe 'RailsAdmin::Adapters::ActiveRecord', :active_record => true do
179
179
  @abstract_model.get('abc').should be_nil
180
180
  end
181
181
 
182
- it "#first returns first item" do
183
- @abstract_model.first.should == @players.first
182
+ it "#first returns a player" do
183
+ @players.should include @abstract_model.first
184
184
  end
185
185
 
186
186
  it "#count returns count of items" do
@@ -206,7 +206,7 @@ describe 'RailsAdmin::Adapters::ActiveRecord', :active_record => true do
206
206
  end
207
207
 
208
208
  it "supports limiting" do
209
- @abstract_model.all(:limit => 2).count.should == 2
209
+ @abstract_model.all(:limit => 2).should have(2).items
210
210
  end
211
211
 
212
212
  it "supports retrieval by bulk_ids" do
@@ -238,7 +238,24 @@ describe 'RailsAdmin::Adapters::Mongoid', :mongoid => true do
238
238
  lambda{ RailsAdmin::AbstractModel.new(MongoEmbedsMany).associations }.should raise_error(RuntimeError,
239
239
  "Embbeded association without accepts_nested_attributes_for can't be handled by RailsAdmin,\nbecause embedded model doesn't have top-level access.\nPlease add `accepts_nested_attributes_for :mongo_embeddeds' line to `MongoEmbedsMany' model.\n"
240
240
  )
241
- end
241
+ end
242
+
243
+ it "should work with inherited embeds_many model" do
244
+ class MongoEmbedsParent
245
+ include Mongoid::Document
246
+ embeds_many :mongo_embeddeds
247
+ accepts_nested_attributes_for :mongo_embeddeds
248
+ end
249
+
250
+ class MongoEmbedded
251
+ include Mongoid::Document
252
+ embedded_in :mongo_embeds_many
253
+ end
254
+
255
+ class MongoEmbedsChild < MongoEmbedsParent; end
256
+
257
+ lambda{ RailsAdmin::AbstractModel.new(MongoEmbedsChild).associations }.should_not raise_error
258
+ end
242
259
  end
243
260
 
244
261
  describe "#properties" do
@@ -380,6 +397,27 @@ describe 'RailsAdmin::Adapters::Mongoid', :mongoid => true do
380
397
  :length => 255 }
381
398
  ]
382
399
  end
400
+
401
+ it "detects validation length properly" do
402
+ class LengthValiated
403
+ include Mongoid::Document
404
+ field :text, :type => String
405
+ validates :text, :length => {:maximum => 50}
406
+ end
407
+ RailsAdmin::AbstractModel.new('LengthValiated').send(:length_validation_lookup, :text).should == 50
408
+ end
409
+
410
+ it "should not cause problem with custom validators" do
411
+ class MyCustomValidator < ActiveModel::Validator
412
+ def validate(r); end
413
+ end
414
+ class CustomValiated
415
+ include Mongoid::Document
416
+ field :text, :type => String
417
+ validates_with MyCustomValidator
418
+ end
419
+ lambda{ RailsAdmin::AbstractModel.new('CustomValiated').send(:length_validation_lookup, :text) }.should_not raise_error
420
+ end
383
421
  end
384
422
 
385
423
  describe "data access method" do
@@ -400,8 +438,8 @@ describe 'RailsAdmin::Adapters::Mongoid', :mongoid => true do
400
438
  @abstract_model.get('4f4f0824dcf2315093000000').should be_nil
401
439
  end
402
440
 
403
- it "#first returns first item" do
404
- @abstract_model.first.should == @players.first
441
+ it "#first returns a player" do
442
+ @players.should include @abstract_model.first
405
443
  end
406
444
 
407
445
  it "#count returns count of items" do
@@ -427,7 +465,7 @@ describe 'RailsAdmin::Adapters::Mongoid', :mongoid => true do
427
465
  end
428
466
 
429
467
  it "supports limiting" do
430
- @abstract_model.all(:limit => 2).to_a.count.should == 2
468
+ @abstract_model.all(:limit => 2).to_a.should have(2).items
431
469
  end
432
470
 
433
471
  it "supports retrieval by bulk_ids" do
@@ -530,6 +568,29 @@ describe 'RailsAdmin::Adapters::Mongoid', :mongoid => true do
530
568
  @abstract_model.all(:filters => {"fans" => {"0000" => {:o=>"is", :v=>'foobar'}}}).to_a.should == @teams[1..1]
531
569
  end
532
570
  end
571
+
572
+ describe "whose type is embedded has_many" do
573
+ before do
574
+ RailsAdmin.config FieldTest do
575
+ field :embeds do
576
+ queryable true
577
+ searchable :all
578
+ end
579
+ end
580
+ @field_tests = FactoryGirl.create_list(:field_test, 3)
581
+ @field_tests[0].embeds.create :name => 'foo'
582
+ @field_tests[1].embeds.create :name => 'bar'
583
+ @abstract_model = RailsAdmin::AbstractModel.new('FieldTest')
584
+ end
585
+
586
+ it "supports querying" do
587
+ @abstract_model.all(:query => 'bar').to_a.should == @field_tests[1..1]
588
+ end
589
+
590
+ it "supports filtering" do
591
+ @abstract_model.all(:filters => {"embeds" => {"0000" => {:o=>"is", :v=>'bar'}}}).to_a.should == @field_tests[1..1]
592
+ end
593
+ end
533
594
  end
534
595
 
535
596
  describe "#query_conditions" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-05-15 00:00:00.000000000 Z
15
+ date: 2012-06-06 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: bbenezech-nested_form
@@ -54,6 +54,9 @@ dependencies:
54
54
  - - ~>
55
55
  - !ruby/object:Gem::Version
56
56
  version: '2.0'
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: 2.0.3
57
60
  type: :runtime
58
61
  prerelease: false
59
62
  version_requirements: !ruby/object:Gem::Requirement
@@ -62,6 +65,9 @@ dependencies:
62
65
  - - ~>
63
66
  - !ruby/object:Gem::Version
64
67
  version: '2.0'
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: 2.0.3
65
71
  - !ruby/object:Gem::Dependency
66
72
  name: jquery-ui-rails
67
73
  requirement: !ruby/object:Gem::Requirement