lolita 3.1.17 → 3.1.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/VERSION +1 -1
  2. data/app/controllers/lolita/field_data_controller.rb +36 -0
  3. data/app/controllers/lolita/info_controller.rb +12 -1
  4. data/app/controllers/lolita/rest_controller.rb +8 -3
  5. data/app/helpers/lolita_helper.rb +12 -1
  6. data/app/views/components/lolita/configuration/column/_display.html.erb +1 -1
  7. data/app/views/components/lolita/configuration/column/_header.html.erb +1 -1
  8. data/app/views/components/lolita/configuration/column/_sort.html.erb +7 -4
  9. data/app/views/components/lolita/configuration/field/array/_display.html.erb +1 -1
  10. data/app/views/components/lolita/configuration/field/array/autocomplete/_display.html.haml +11 -0
  11. data/app/views/components/lolita/configuration/field/array/checkbox/_display.html.haml +8 -0
  12. data/app/views/components/lolita/configuration/field/array/polymorphic/_display.html.haml +6 -0
  13. data/app/views/components/lolita/configuration/field/array/polymorphic/_options_for_select.html.haml +1 -0
  14. data/app/views/components/lolita/configuration/field/array/select/_display.html.erb +1 -1
  15. data/app/views/components/lolita/configuration/field/string/_display.html.erb +1 -5
  16. data/app/views/components/lolita/configuration/field/string/disabled/_display.html.erb +1 -1
  17. data/app/views/components/lolita/configuration/field/string/text/_display.html.erb +1 -1
  18. data/app/views/components/lolita/configuration/list/_paginator.html.erb +1 -1
  19. data/app/views/components/lolita/configuration/list/_title.html.erb +6 -1
  20. data/app/views/components/lolita/configuration/nested_form/_display.html.erb +8 -6
  21. data/app/views/components/lolita/configuration/search/_display.html.haml +2 -0
  22. data/app/views/components/lolita/navigation/_tree.html.erb +18 -25
  23. data/app/views/components/lolita/shared/_header.html.erb +1 -1
  24. data/app/views/components/lolita/shared/_right_sidebar.html.erb +1 -6
  25. data/app/views/components/lolita/shared/_save_button.html.erb +6 -0
  26. data/config/locales/en.yml +9 -1
  27. data/config/locales/lv.yml +6 -5
  28. data/config/routes.rb +3 -1
  29. data/lib/lolita.rb +52 -35
  30. data/lib/lolita/adapter/abstract_adapter.rb +5 -5
  31. data/lib/lolita/adapter/active_record.rb +190 -84
  32. data/lib/lolita/adapter/field_helper.rb +19 -0
  33. data/lib/lolita/adapter/mongoid.rb +217 -64
  34. data/lib/lolita/builder.rb +1 -1
  35. data/lib/lolita/configuration/base.rb +17 -4
  36. data/lib/lolita/configuration/column.rb +47 -28
  37. data/lib/lolita/configuration/columns.rb +1 -1
  38. data/lib/lolita/configuration/factory/field.rb +45 -0
  39. data/lib/lolita/configuration/factory/tab.rb +18 -0
  40. data/lib/lolita/configuration/field.rb +30 -115
  41. data/lib/lolita/configuration/field/array.rb +126 -41
  42. data/lib/lolita/configuration/field/big_decimal.rb +2 -2
  43. data/lib/lolita/configuration/field/boolean.rb +2 -2
  44. data/lib/lolita/configuration/field/date.rb +2 -2
  45. data/lib/lolita/configuration/field/date_time.rb +2 -2
  46. data/lib/lolita/configuration/field/float.rb +9 -0
  47. data/lib/lolita/configuration/field/hash.rb +9 -0
  48. data/lib/lolita/configuration/field/hidden.rb +2 -2
  49. data/lib/lolita/configuration/field/integer.rb +2 -3
  50. data/lib/lolita/configuration/field/range.rb +9 -0
  51. data/lib/lolita/configuration/field/string.rb +5 -2
  52. data/lib/lolita/configuration/field/symbol.rb +9 -0
  53. data/lib/lolita/configuration/field/time.rb +2 -2
  54. data/lib/lolita/configuration/list.rb +41 -8
  55. data/lib/lolita/configuration/nested_form.rb +2 -2
  56. data/lib/lolita/configuration/search.rb +91 -0
  57. data/lib/lolita/configuration/tab.rb +11 -14
  58. data/lib/lolita/configuration/tab/content.rb +1 -2
  59. data/lib/lolita/configuration/tab/default.rb +0 -1
  60. data/lib/lolita/configuration/tabs.rb +17 -11
  61. data/lib/lolita/controller_additions.rb +15 -0
  62. data/lib/lolita/controllers/authorization_helpers.rb +56 -0
  63. data/lib/lolita/controllers/component_helpers.rb +1 -1
  64. data/lib/lolita/controllers/internal_helpers.rb +18 -4
  65. data/lib/lolita/controllers/url_helpers.rb +5 -1
  66. data/lib/lolita/controllers/user_helpers.rb +23 -11
  67. data/lib/lolita/dbi/base.rb +7 -1
  68. data/lib/lolita/hooks.rb +163 -120
  69. data/lib/lolita/lazy_loader.rb +3 -0
  70. data/lib/lolita/mapping.rb +25 -2
  71. data/lib/lolita/modules/rest.rb +1 -1
  72. data/lib/lolita/navigation/branch.rb +52 -1
  73. data/lib/lolita/navigation/tree.rb +10 -0
  74. data/lib/lolita/rails.rb +1 -2
  75. data/lib/lolita/rails/routes.rb +4 -5
  76. data/lib/lolita/search/simple.rb +76 -0
  77. data/lib/lolita/system_configuration/application.rb +7 -1
  78. data/lolita.gemspec +33 -13
  79. data/public/stylesheets/lolita/style.css +21 -0
  80. data/spec/configuration/column_spec.rb +2 -2
  81. data/spec/configuration/columns_spec.rb +1 -1
  82. data/spec/configuration/field_spec.rb +14 -43
  83. data/spec/configuration/list_spec.rb +24 -20
  84. data/spec/configuration/search_spec.rb +44 -0
  85. data/spec/configuration/tab_spec.rb +21 -31
  86. data/spec/configuration/tabs_spec.rb +2 -2
  87. data/spec/dbi/base_spec.rb +3 -9
  88. data/spec/rails_app/app/mongoid/post.rb +4 -0
  89. data/spec/rails_app/config/application.rb +12 -1
  90. data/spec/rails_app/config/environments/development.rb +6 -2
  91. data/spec/rails_app/config/environments/production.rb +5 -1
  92. data/spec/rails_app/config/environments/test.rb +5 -1
  93. data/spec/search/simple_spec.rb +48 -0
  94. data/spec/spec_helper.rb +29 -18
  95. metadata +55 -38
  96. data/spec/configuration/page_spec.rb +0 -20
@@ -0,0 +1,91 @@
1
+ module Lolita
2
+ module Configuration
3
+ # Proxy class for search. It supports two methods #with and #run.
4
+ # By default with method accepts method name or nothing and creates Lolita::Search::Simple instance
5
+ # that will be used to run search on current dbi.
6
+ # By default search run against all content fields, but when _:fields_ options is passed it search in
7
+ # those fields only.
8
+ # ==== Example
9
+ # class Post < ActiveRecord::Base
10
+ # include Lolita::Configuration
11
+ # lolita do
12
+ # list do
13
+ # search :fields => [:name]
14
+ # end
15
+ # end
16
+ # end
17
+ # #with method also accepts class or instance of some class, that will be used to run search.
18
+ # That class should have #run method that accepts query and request.
19
+ # ====Example
20
+ # class MyCustomSearch
21
+ # def initialize(dbi)
22
+ # @dbi = dbi
23
+ # end
24
+ #
25
+ # def run(query,request = nil)
26
+ # @dbi.klass.where(:my_field => query)
27
+ # end
28
+ # end
29
+ # Also you can put your search method in model. For more see Lolita::Search::Simple
30
+ # ====Example
31
+ # class Post < ActiveRecord::Base
32
+ # include Lolita::Configuration
33
+ # lolita do
34
+ # list do
35
+ # search :my_custom_search
36
+ # end
37
+ # end
38
+ #
39
+ # def self.my_custom_search(query,request)
40
+ # self.where(:title => query, :user_id => request.params[:user_id])
41
+ # end
42
+ # end
43
+ class Search
44
+ include Lolita::Builder
45
+ attr_reader :dbi
46
+ attr_writer :with, :fields
47
+
48
+ def initialize dbi, *args, &block
49
+ @dbi = dbi
50
+ set_attributes(args ? args.extract_options! : {})
51
+ instance_eval(&block) if block_given?
52
+ @with ||= args[0]!=true && args[0] ? args[0] : nil
53
+ end
54
+
55
+ def with(value = nil)
56
+ @with = value if value
57
+ if !@with || [String,Symbol].include?(@with.class)
58
+ @with = Lolita::Search::Simple.new(dbi,@with, :fields => @fields)
59
+ elsif @with.class == Class
60
+ initialize_arity = @with.instance_method(:initialize).arity
61
+ @with = if initialize_arity < 0 || initialize_arity > 1
62
+ @with.new(dbi,:fields => @fields)
63
+ else
64
+ @with.new(dbi)
65
+ end
66
+ end
67
+ @with
68
+ end
69
+
70
+ def run(query,request = nil)
71
+ if self.with.method(:run).arity < 0 || self.with.method(:run).arity > 1
72
+ self.with.run(query,request)
73
+ else
74
+ self.with.run(query)
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def set_attributes options
81
+ if options.respond_to?(:each)
82
+ options.each do |method_name, value|
83
+ self.send(:"#{method_name}=",value)
84
+ end
85
+ end
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+ end
@@ -22,7 +22,6 @@ module Lolita
22
22
  include Lolita::Builder
23
23
 
24
24
  # For different types there are different builders(cells)
25
- @@default_tab_type=:default
26
25
  @@available_types=[:content]
27
26
 
28
27
  lolita_accessor :title,:name,:type
@@ -33,10 +32,11 @@ module Lolita
33
32
  # * <tt>dbi</tt> Lolita::DBI::Base object, that represents database.
34
33
  # * <tt>*args</tt> See #set_attributes, for how these args are processed.
35
34
  # * <tt>&block</tt> Block can be passed, anything in block will be evaled for current instance.
36
- def initialize dbi,*args,&block
37
- @fields=Lolita::Configuration::Fields.new
35
+ def initialize dbi,type,*args,&block
36
+ @fields = Lolita::Configuration::Fields.new
38
37
  @field_sets = []
39
38
  @nested_forms = []
39
+ @type = type
40
40
  self.dbi=dbi
41
41
  self.current_dbi=dbi
42
42
  self.set_attributes(*args)
@@ -49,7 +49,7 @@ module Lolita
49
49
  # For details how to pass args and block see Lolita::Configuration::Field.
50
50
  # Return field itself.
51
51
  def field *args, &block
52
- field=Lolita::Configuration::Field.add(self.current_dbi,*args,&block)
52
+ field=Lolita::Configuration::Factory::Field.add(self.current_dbi,*args,&block)
53
53
  field.field_set = current_fieldset
54
54
  if self.current_dbi!=self.dbi
55
55
  field.nested_in=self.dbi
@@ -61,7 +61,7 @@ module Lolita
61
61
 
62
62
  # Return all fields in tab.
63
63
  def fields
64
- @fields
64
+ @fields
65
65
  end
66
66
 
67
67
  # Set all fields in tab. Accept <code>fields</code> as Array.
@@ -84,7 +84,7 @@ module Lolita
84
84
  # See Lolita::Adapter classes for use of DB field method.
85
85
  def default_fields
86
86
  self.current_dbi.fields.each{|db_field|
87
- self.field(db_field) unless Lolita::Configuration::Helper.tehnical_field?(db_field,self.current_dbi)
87
+ self.field(:name => db_field.name, :type => db_field.type, :dbi_field => db_field) if db_field.content?
88
88
  }
89
89
  end
90
90
 
@@ -95,7 +95,7 @@ module Lolita
95
95
  nested_form = Lolita::Configuration::NestedForm.new(self,class_or_name, options)
96
96
  self.current_nested_form = nested_form
97
97
  @nested_forms << nested_form
98
- self.current_dbi = Lolita::DBI::Base.new(current_class)
98
+ self.current_dbi = Lolita::DBI::Base.create(current_class)
99
99
  self.instance_eval(&block)
100
100
  self.current_dbi = self.dbi
101
101
  self.current_nested_form = nil
@@ -164,7 +164,6 @@ module Lolita
164
164
  def set_attributes *args
165
165
  if args
166
166
  options=args.extract_options!
167
- self.type=args.first if args.first.is_a?(Symbol)
168
167
  options.each{|method,options|
169
168
  self.send(:"#{method}=",options)
170
169
  }
@@ -174,8 +173,11 @@ module Lolita
174
173
 
175
174
  private
176
175
 
176
+ def my_type
177
+ self.class.to_s.split("::").last.downcase.to_sym
178
+ end
179
+
177
180
  def set_default_attributes
178
- @type=@@default_tab_type unless @type
179
181
  @name="tab_#{self.__id__}" unless @name
180
182
  @title=set_default_title unless @title
181
183
  end
@@ -204,11 +206,6 @@ module Lolita
204
206
  :tab
205
207
  end
206
208
 
207
- class << self
208
- def default_types
209
- @@available_types
210
- end
211
- end
212
209
  end
213
210
  end
214
211
  end
@@ -3,8 +3,7 @@ module Lolita
3
3
  module Tab
4
4
  class Content < Lolita::Configuration::Tab::Base
5
5
 
6
- def initialize(dbi,*args,&block)
7
- @type=:content
6
+ def initialize(*args,&block)
8
7
  super
9
8
  set_default_fields
10
9
  end
@@ -4,7 +4,6 @@ module Lolita
4
4
  class Default < Lolita::Configuration::Tab::Base
5
5
 
6
6
  def initialize *args,&block
7
- self.type=:default
8
7
  super
9
8
  end
10
9
 
@@ -3,17 +3,19 @@ module Lolita
3
3
  # Lolita::Configuration::Tabs is container class that holds all
4
4
  # tabs for each lolita instance.
5
5
  # Also it has some useful methods.
6
-
7
6
  class Tabs
8
7
  include Enumerable
9
8
  include Lolita::ObservedArray
10
9
  include Lolita::Builder
11
10
 
12
11
  attr_reader :dbi,:excluded
12
+ attr_accessor :tab_types
13
+
13
14
  def initialize dbi,*args,&block
14
15
  @dbi=dbi
15
16
  @tabs=[]
16
17
  @excluded=[]
18
+ @tab_types = [:content]
17
19
  self.set_attributes(*args)
18
20
  self.instance_eval(&block) if block_given?
19
21
  end
@@ -43,7 +45,13 @@ module Lolita
43
45
  end
44
46
 
45
47
  def tab *args,&block
46
- self<<Lolita::Configuration::Tab.add(@dbi,*args,&block)
48
+ self<<Lolita::Configuration::Factory::Tab.add(@dbi,*args,&block)
49
+ end
50
+
51
+ def fields
52
+ @tabs.collect{|tab|
53
+ tab.fields
54
+ }.flatten
47
55
  end
48
56
 
49
57
  def by_type(type)
@@ -62,18 +70,20 @@ module Lolita
62
70
  tab_types=if args
63
71
  args
64
72
  else
65
- default_tab_types
73
+ @tab_types
66
74
  end
67
75
  tab_types.each{|type|
68
- self<<Lolita::Configuration::Tab.add(@dbi,type.to_sym)
76
+ self<<Lolita::Configuration::Factory::Tab.add(@dbi,type.to_sym)
69
77
  }
70
78
  end
71
79
 
72
80
  def exclude *args
73
81
  @excluded=if args && args.include?(:all)
74
- default_tab_types
75
- else
82
+ tab_types
83
+ elsif args.is_a?(Array)
76
84
  args
85
+ else
86
+ []
77
87
  end
78
88
  end
79
89
 
@@ -103,10 +113,6 @@ module Lolita
103
113
  end
104
114
  end
105
115
  end
106
-
107
- def default_tab_types
108
- Lolita::Configuration::Tab::Base.default_types
109
- end
110
116
 
111
117
  def set_tab_attributes(tab)
112
118
  if tab
@@ -120,7 +126,7 @@ module Lolita
120
126
 
121
127
  def build_element(element,&block)
122
128
  current_tab=if element.is_a?(Hash) || element.is_a?(Symbol)
123
- Lolita::Configuration::Tab.add(@dbi,element,&block)
129
+ Lolita::Configuration::Factory::Tab.add(@dbi,element,&block)
124
130
  else
125
131
  element
126
132
  end
@@ -0,0 +1,15 @@
1
+ module Lolita
2
+ # Basic module for custom Lolita controllers. Is used in Lolita::RestController.
3
+ module ControllerAdditions
4
+
5
+ def self.included(base_class)
6
+ base_class.class_eval do
7
+ include Lolita::Controllers::UserHelpers
8
+ include Lolita::Controllers::InternalHelpers
9
+ include Lolita::Controllers::AuthorizationHelpers
10
+ include LolitaHelper
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,56 @@
1
+ module Lolita
2
+ module Controllers
3
+ # Helper and controller methods that are used to authorize access to resource. Include this when auhtorization for lolita resources are needed.
4
+ module AuthorizationHelpers
5
+
6
+ extend ActiveSupport::Concern
7
+ included do
8
+ helpers = %w(current_ability can? cannot? authorize!)
9
+
10
+ helper_method *helpers
11
+ end
12
+
13
+ private
14
+
15
+ # Proxy method for current_abi, it gives control back to superclass when method is called in
16
+ # other controller than Lolita's (it responds to #lolita_mapping) otherwise it creates or return existing ability with #lolita_current_user.
17
+ def current_ability
18
+ if self.respond_to?(:is_lolita_resource?) && self.is_lolita_resource? && lolita_current_user
19
+ if defined?(::CanCan)
20
+ @current_ability||= ::Ability.new(lolita_current_user)
21
+ else
22
+ super
23
+ end
24
+ else
25
+ super
26
+ end
27
+ end
28
+
29
+ def can? *args
30
+ if defined?(::CanCan)
31
+ super
32
+ else
33
+ true
34
+ end
35
+ end
36
+
37
+ def cannot? *args
38
+ if defined?(::CanCan)
39
+ super
40
+ else
41
+ true
42
+ end
43
+ end
44
+
45
+ def authorize! *args
46
+
47
+ if defined?(::CanCan)
48
+ super
49
+ else
50
+ true
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -70,7 +70,7 @@ module Lolita
70
70
  def output_with_callbacks(partial_name,name,locals)
71
71
  @component_locals ||={}
72
72
  @component_locals[name] = locals
73
-
73
+
74
74
  output = Lolita::Hooks.component(name).run(:before,:run_scope => self).to_s
75
75
  block_output = Lolita::Hooks.component(name).run(:around, :run_scope => self) do
76
76
  render(:partial => partial_name,:locals=>locals)
@@ -5,7 +5,7 @@ module Lolita
5
5
  included do
6
6
  helper LolitaHelper
7
7
  #TODO pārnest helperus uz lolitu vai arī uz lolita app nevis likt iekš controllers iekš lolitas
8
- helpers = %w(resource resource_name
8
+ helpers = %w(resource resource_name use_mapping
9
9
  resource_class lolita_mapping show_response tab_form tab_form=)
10
10
  hide_action *helpers
11
11
 
@@ -21,14 +21,14 @@ module Lolita
21
21
  end
22
22
 
23
23
  def resource_name
24
- lolita_mapping.name
24
+ lolita_mapping.class_name.underscore.to_sym
25
25
  end
26
26
 
27
27
  def resource_class
28
28
  lolita_mapping.to
29
29
  end
30
30
 
31
- def lolita_mapping
31
+ def lolita_mapping(new_mapping = nil)
32
32
  @lolita_mapping||=request.env["lolita.mapping"]
33
33
  end
34
34
 
@@ -45,6 +45,19 @@ module Lolita
45
45
  end
46
46
  @tab_form
47
47
  end
48
+
49
+ def use_mapping(new_mapping)
50
+ if block_given?
51
+ begin
52
+ @old_mapping = lolita_mapping
53
+ @lolita_mapping = new_mapping
54
+ yield
55
+ ensure
56
+ @lolita_mapping = @old_mapping
57
+ @old_mapping = nil
58
+ end
59
+ end
60
+ end
48
61
 
49
62
  protected
50
63
 
@@ -62,6 +75,7 @@ module Lolita
62
75
 
63
76
  def is_lolita_resource?
64
77
  raise ActionController::UnknownAction unless lolita_mapping
78
+ true
65
79
  end
66
80
 
67
81
  def resource=(new_resource)
@@ -81,7 +95,7 @@ module Lolita
81
95
  end
82
96
 
83
97
  def get_resource(id=nil)
84
- self.resource=resource_class.lolita.dbi.find_by_id(id||params[:id])
98
+ self.resource = resource_class.lolita.dbi.find_by_id(id || params[:id])
85
99
  end
86
100
 
87
101
  def build_resource(attributes=nil)
@@ -47,6 +47,7 @@ module Lolita
47
47
  options = self.send(resource_type[action] || :lolita_resource_path,options)
48
48
  end
49
49
  end
50
+
50
51
  url_for_without_lolita(options)
51
52
  end
52
53
  alias_method_chain :url_for, :lolita
@@ -104,7 +105,10 @@ module Lolita
104
105
  mapping=(options[:mapping]||lolita_mapping)
105
106
  name=!options[:plural] ? mapping.name : mapping.plural
106
107
  name="#{mapping.path}_#{name}"
107
- :"#{options[:action]}#{options[:action] ? "_" : ""}#{name}_path"
108
+ addon = if mapping.plural == mapping.singular && options[:plural]
109
+ "_index"
110
+ end
111
+ :"#{options[:action]}#{options[:action] ? "_" : ""}#{name}#{addon}_path"
108
112
  end
109
113
  end
110
114
  end
@@ -5,28 +5,40 @@ module Lolita
5
5
  # Authentication should be defined through Lolita#setup.
6
6
  # Method call block or send given method name to current controller
7
7
  # or return True when no authentication is defined.
8
+ # Include this if authentication is neccessary for controller.
8
9
  module UserHelpers
9
10
  extend ActiveSupport::Concern
10
11
  included do
11
- helper LolitaHelper
12
+ helpers = %w(lolita_current_user)
13
+
14
+ helper_method *helpers
12
15
  end
13
-
16
+
14
17
  private
15
- # FIXME what to do when block or method return false, and do not redirect
16
- # need some redirect, but how to detect it?
17
- def authenticate_lolita_user!
18
- if auth=Lolita.authentication
19
- if auth.is_a?(Proc)
20
- self.instance_eval(&auth)
18
+
19
+ def lolita_current_user
20
+ @lolita_current_user ||= Lolita.user_classes.inject(nil) do |user,user_class|
21
+ unless user
22
+ if self.respond_to?(:"current_#{user_class.to_s.downcase}")
23
+ self.send(:"current_#{user_class.to_s.downcase}")
24
+ else
25
+ false
26
+ end
21
27
  else
22
- send(auth)
28
+ user
23
29
  end
30
+ end
31
+ end
32
+
33
+
34
+ def authenticate_lolita_user!
35
+ if auth = Lolita.authentication
36
+ send(auth)
24
37
  else
25
- #TODO warning
38
+ warn("There is no authentication. See initializers/lolita.rb")
26
39
  true
27
40
  end
28
41
  end
29
-
30
42
  end
31
43
  end
32
44
  end