Module: RearSetup
- Includes:
- RearConstants
- Defined in:
- lib/rear/setup.rb,
lib/rear/setup/menu.rb,
lib/rear/setup/columns.rb,
lib/rear/setup/filters.rb,
lib/rear/setup/generic.rb,
lib/rear/setup/associations.rb
Constant Summary
Constants included from RearConstants
RearConstants::ASSETS__PATH, RearConstants::ASSETS__SUFFIX, RearConstants::ASSETS__SUFFIX_REGEXP, RearConstants::ASSOCS__STRUCT, RearConstants::COLUMNS__BOOLEAN_MAP, RearConstants::COLUMNS__DEFAULT_TYPE, RearConstants::COLUMNS__HANDLED_TYPES, RearConstants::COLUMNS__PANE_MAX_LENGTH, RearConstants::FILTERS__DECORATIVE_CMP, RearConstants::FILTERS__DEFAULT_TYPE, RearConstants::FILTERS__HANDLED_TYPES, RearConstants::FILTERS__QUERY_MAP, RearConstants::FILTERS__STR_TO_BOOLEAN, RearConstants::PAGER__SIDE_PAGES, RearConstants::PATH__TEMPLATES
Instance Method Summary collapse
-
#assoc_columns(*columns) ⇒ Object
when rendering some model in a “remote” association pane, all columns of current model will be displayed.
-
#decorative_filter(*args, &proc) ⇒ Object
sometimes you need to filter by some value that has too much options.
-
#editor_attrs(attrs = {}) ⇒ Object
set HTML attributes to be used on all columns only on editor pages.
-
#filter(column, type = nil, opts_and_or_html_attrs = {}, &proc) ⇒ Object
add a filter.
-
#html_attrs(attrs = {}) ⇒ Object
set HTML attributes to be used on all columns on both pane and editor pages.
-
#ignored_assocs(*assocs) ⇒ Object
(also: #ignored_assoc, #ignore_assocs, #ignore_assoc)
ignore some assocs.
-
#input(name, type = nil, opts_and_or_html_attrs = {}, &proc) ⇒ Object
add new column or override automatically added one.
-
#internal_filter(&proc) ⇒ Object
# then we using internal_filter # to yield selected category and filter articles internal_filter do if category_id = filter?(:Category) Article.all(category_id: category_id.to_i) end end end.
- #items_per_page(n = nil) ⇒ Object (also: #ipp)
-
#menu_group(group = nil) ⇒ Object
(also: #under)
put current controller under some group.
-
#menu_label(label = nil) ⇒ Object
(also: #label)
by default all controllers are shown in main menu using the demodulized controller name.
-
#menu_position(position = nil) ⇒ Object
(also: #position)
by default controllers will be shown in the menu in the order they was defined.
-
#model(model = nil, opts = {}, &proc) ⇒ Object
tell controller to create a CRUD interface for given model opts and proc will be passed to Espresso’s ‘crudify` helper.
- #on_delete(&proc) ⇒ Object (also: #on_destroy)
-
#on_save(&proc) ⇒ Object
executed when new item created and when existing item updated.
-
#on_update(&proc) ⇒ Object
executed when existing item updated.
- #order_by(*columns) ⇒ Object
-
#pane_attrs(attrs = {}) ⇒ Object
set HTML attributes to be used on all columns only on pane pages.
- #pkey(key = nil) ⇒ Object
- #quick_filter(column, *args) ⇒ Object
- #readonly! ⇒ Object
-
#readonly_assocs(*assocs) ⇒ Object
(also: #readonly_assoc)
make some assocs readonly.
-
#reset_columns! ⇒ Object
reset any automatically(or manually) added columns.
-
#row(label = nil, &proc) ⇒ Object
display multiple columns in a row(on editor).
Instance Method Details
#assoc_columns(*columns) ⇒ Object
when rendering some model in a “remote” association pane, all columns of current model will be displayed.
‘assoc_columns` allow to set a list of “remotely” displayed columns.
28 29 30 31 |
# File 'lib/rear/setup/associations.rb', line 28 def assoc_columns *columns @__rear__assoc_columns = columns if columns.any? @__rear__assoc_columns end |
#decorative_filter(*args, &proc) ⇒ Object
decorative filters will not actually query the db, so you can name them as you want.
decorative filters does not support custom comparison functions
sometimes you need to filter by some value that has too much options. For ex. you want to filter pages by author and there are about 1000 authors in db. displaying all authors within a single dropdown filter is kinda cumbersome. we need to somehow narrow them down. decorative filters allow to do this with easy. in our case, we do not display the authors until a letter selected.
200 201 202 203 204 |
# File 'lib/rear/setup/filters.rb', line 200 def decorative_filter *args, &proc html_attrs = args.last.is_a?(Hash) ? Hash[args.pop] : {} setup = {decorative?: true, cmp: FILTERS__DECORATIVE_CMP} filter *args << html_attrs.merge(setup), &proc end |
#editor_attrs(attrs = {}) ⇒ Object
will override any attrs set via ‘html_attrs`
set HTML attributes to be used on all columns only on editor pages.
105 106 107 108 |
# File 'lib/rear/setup/columns.rb', line 105 def editor_attrs attrs = {} @__rear__editor_attrs = attrs if attrs.any? && @__rear__editor_attrs.nil? @__rear__editor_attrs || html_attrs end |
#filter(column, type = nil, opts_and_or_html_attrs = {}, &proc) ⇒ Object
comparison function :text/:string filters will use :like comparison function by default: … WHERE name LIKE ‘%VALUE%’ …
:checkbox filters will use :in comparison function by default: … WHERE column IN (‘VALUE1’, ‘VALUE2’) … if you use a custom cmp function with a :checkbox filter, filter’s column will be compared to each selected value: … WHERE (column LIKE ‘%VALUE1%’ OR column LIKE ‘%VALUE2%’) …
any other types will use :eql comparison function by default: “… WHERE created_at = ‘VALUE’ …
to use a non-default comparison function, set it via :cmp option: ‘filter :name, :cmp => :eql`
available comparison functions:
- :eql # equal
- :not # not equal
- :gt # greater than
- :gte # greater than or equal
- :lt # less than
- :lte # less than or equal
- :like # - column LIKE '%VALUE%'
- :unlike # - column NOT LIKE '%VALUE%'
- :_like # match beginning of line - column LIKE 'VALUE%'
- :_unlike # - column NOT LIKE 'VALUE%'
- :like_ # match end of line - column LIKE '%VALUE'
- :unlike_ # - column NOT LIKE '%VALUE'
- :_like_ # exact match - column LIKE 'VALUE'
- :_unlike_ # - column NOT LIKE 'VALUE'
if type not given, Rear will use the type of the column with same name, if any. if no column found, it will use :text
:radio, :checkbox and :select filters requires a block to run. block should return an Array or a Hash. use an Array when stored keys are the same as displayed values. use a Hash when stored keys are different. Important! if no block given, Rear will search for a column with same name and type and inherit options from there. so if you have say a :checkbox column named :colors with defined options, you only need to do ‘filter :colors`, without specifying type and options. type and options will be inherited from earlier defined column.
add a filter.
by default a text filter will be rendered. to define filters of another type, pass desired type as a Symbol via second argument.
acceptable types:
- :string/:text
- :select
- :radio
- :checkbox
- :date
- :datetime
- :time
- :boolean
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/rear/setup/filters.rb', line 121 def filter column, type = nil, opts_and_or_html_attrs = {}, &proc opts = (opts_and_or_html_attrs||{}).dup type.is_a?(Hash) && (opts = type.dup) && (type = nil) && (opts_and_or_html_attrs = nil) matching_column = columns.find {|c| c && c.first == column} # if no type given, inheriting it from a column with same name, if any. type ||= (matching_column||[])[1] type = FILTERS__DEFAULT_TYPE unless FILTERS__HANDLED_TYPES.include?(type) # if filter is of :select, :radio or :checkbox type and no options block given, # inheriting it from a column with same name, if any. if proc.nil? && matching_column && matching_column[1] == type mci = RearInput.new(matching_column[0], type, &matching_column[3]) mci.optioned? && proc = lambda { mci. } end # using defaults if no comparison function given unless cmp = opts.delete(:cmp) cmp = case type when :text, :string :like when :checkbox :in else :eql end end unless label = opts.delete(:label) label = column.to_s label << '?' if type == :boolean end (filters[column.to_sym] ||= {})[cmp] = { template: 'filters/%s.slim' % type, type: type, label: label.freeze, decorative?: opts.delete(:decorative?), attrs: opts.freeze, proc: proc }.freeze end |
#html_attrs(attrs = {}) ⇒ Object
set HTML attributes to be used on all columns on both pane and editor pages
91 92 93 94 |
# File 'lib/rear/setup/columns.rb', line 91 def html_attrs attrs = {} @__rear__html_attrs = attrs if attrs.any? && @__rear__html_attrs.nil? @__rear__html_attrs || {} end |
#ignored_assocs(*assocs) ⇒ Object Also known as: ignored_assoc, ignore_assocs, ignore_assoc
ignore some assocs. this is a cosmetic measure - assocs just wont be displayed on frontend but the API for their manipulation will still work
15 16 17 18 |
# File 'lib/rear/setup/associations.rb', line 15 def ignored_assocs *assocs (@__rear__ignored_assocs ||= []).concat(assocs) if assocs.any? (@__rear__ignored_assocs || []) end |
#input(name, type = nil, opts_and_or_html_attrs = {}, &proc) ⇒ Object
add new column or override automatically added one
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/rear/setup/columns.rb', line 40 def input name, type = nil, opts_and_or_html_attrs = {}, &proc type.is_a?(Hash) && (opts_and_or_html_attrs = type) && (type = nil) opts_and_or_html_attrs[:row] = opts_and_or_html_attrs[:row] ? opts_and_or_html_attrs[:row].to_s : @__rear__row existing_column = nil columns.each_with_index {|c,i| c && c.first == name && existing_column = [c,i]} column = existing_column ? Array.new(existing_column.first) : [] column[0] = name column[1] = type ? type.to_s.downcase.to_sym : column[1] || COLUMNS__DEFAULT_TYPE column[2] = (column[2]||{}).merge(opts_and_or_html_attrs).freeze column[3] = proc column.freeze existing_column ? columns[existing_column.last] = column : columns << column end |
#internal_filter(&proc) ⇒ Object
# then we using internal_filter
# to yield selected category and filter articles
internal_filter do
if category_id = filter?(:Category)
Article.all(category_id: category_id.to_i)
end
end
end
304 305 306 307 308 309 310 311 312 |
# File 'lib/rear/setup/filters.rb', line 304 def internal_filter &proc # instance_exec at runtime is expensive enough, # so compiling procs into methods at load time. chunks = [self.to_s, proc.__id__] name = ('__rear__%s__' % chunks.join('_').gsub(/\W/, '_')).to_sym define_method name, &proc private name internal_filters.push(name) end |
#items_per_page(n = nil) ⇒ Object Also known as: ipp
33 34 35 36 |
# File 'lib/rear/setup/generic.rb', line 33 def items_per_page n = nil @__rear__ipp = n.to_i if n @__rear__ipp || 10 end |
#menu_group(group = nil) ⇒ Object Also known as: under
put current controller under some group.
34 35 36 37 |
# File 'lib/rear/setup/menu.rb', line 34 def group = nil @__rear__menu_group = group.to_s if group @__rear__menu_group end |
#menu_label(label = nil) ⇒ Object Also known as: label
by default all controllers are shown in main menu using the demodulized controller name.
to use a custom label, set it via ‘menu_label` or its alias - `label` to hide a controller from menu set label to false.
8 9 10 11 |
# File 'lib/rear/setup/menu.rb', line 8 def label = nil @__rear__menu_label = label.freeze if label || label == false @__rear__menu_label.nil? ? default_label : @__rear__menu_label end |
#menu_position(position = nil) ⇒ Object Also known as: position
by default controllers will be shown in the menu in the order they was defined. to have a controller shown before other ones set its menu_position to a higher number.
16 17 18 19 |
# File 'lib/rear/setup/menu.rb', line 16 def position = nil @__rear__menu_position = position.to_i if position @__rear__menu_position || 0 end |
#model(model = nil, opts = {}, &proc) ⇒ Object
tell controller to create a CRUD interface for given model opts and proc will be passed to Espresso’s ‘crudify` helper.
10 11 12 13 14 15 16 17 18 |
# File 'lib/rear/setup/generic.rb', line 10 def model model = nil, opts = {}, &proc return @__rear__model if @__rear__model || model.nil? model = RearUtils.extract_constant(model) RearUtils.is_orm?(model) || raise(ArgumentError, '"%s" is not a ActiveRecord/DataMapper/Sequel model' % model.inspect) @__rear__model = model @__rear__default_label = model.name.gsub(/\W/, '_').freeze RearControllerSetup.crudify self, model, opts, &proc end |
#on_delete(&proc) ⇒ Object Also known as: on_destroy
50 51 52 |
# File 'lib/rear/setup/generic.rb', line 50 def on_delete &proc before :destroy, &proc end |
#on_save(&proc) ⇒ Object
executed when new item created and when existing item updated
40 41 42 43 |
# File 'lib/rear/setup/generic.rb', line 40 def on_save &proc # const_get(:RearController). before :save, &proc end |
#on_update(&proc) ⇒ Object
executed when existing item updated
46 47 48 |
# File 'lib/rear/setup/generic.rb', line 46 def on_update &proc before :update, &proc end |
#order_by(*columns) ⇒ Object
28 29 30 31 |
# File 'lib/rear/setup/generic.rb', line 28 def order_by *columns @__rear__order = columns if columns.any? @__rear__order end |
#pane_attrs(attrs = {}) ⇒ Object
will override any attrs set via ‘html_attrs`
set HTML attributes to be used on all columns only on pane pages.
98 99 100 101 |
# File 'lib/rear/setup/columns.rb', line 98 def pane_attrs attrs = {} @__rear__pane_attrs = attrs if attrs.any? && @__rear__pane_attrs.nil? @__rear__pane_attrs || html_attrs end |
#pkey(key = nil) ⇒ Object
20 21 22 23 24 25 26 |
# File 'lib/rear/setup/generic.rb', line 20 def pkey key = nil return unless model @__rear__pkey = key if key @__rear__pkey || raise(ArgumentError, "Was unable to automatically detect primary key for %s model. Please set it manually via `pkey key_name`" % model) end |
#quick_filter(column, *args) ⇒ Object
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/rear/setup/filters.rb', line 229 def quick_filter column, *args = args.last.is_a?(Hash) ? args.pop : {} cmp = .delete(:cmp) || :eql query_formats = FILTERS__QUERY_MAP.call(orm) if query_format = query_formats[cmp] = Hash[.map do |k,v| [ v.to_s, k.is_a?(Array) ? [query_formats[k.first], k.last] : [query_format, k] ] end] # if options provided as arguments, adding them to options Hash args.each {|a| [a.to_s] = [query_format, a.to_s] } # if no options given, # inheriting them from a column with same name, if any. if .empty? && mc = columns.find {|c| c && c.first == column} mci = RearInput.new(mc[0], mc[1], &mc[3]) mci.optioned? && mci..each_pair do |k,v| [v.to_s] = [query_format, k] end end quick_filters[column.to_sym] = end end |
#readonly! ⇒ Object
55 56 57 |
# File 'lib/rear/setup/generic.rb', line 55 def readonly! @__rear__readonly = true end |
#readonly_assocs(*assocs) ⇒ Object Also known as: readonly_assoc
make some assocs readonly. this is a cosmetic measure - frontend just wont let user modify them but the API for their manipulation will still work
6 7 8 9 |
# File 'lib/rear/setup/associations.rb', line 6 def readonly_assocs *assocs (@__rear__readonly_assocs ||= []).concat(assocs) if assocs.any? (@__rear__readonly_assocs || []) end |
#reset_columns! ⇒ Object
reset any automatically(or manually) added columns
62 63 64 |
# File 'lib/rear/setup/columns.rb', line 62 def reset_columns! @__rear__columns = {} end |
#row(label = nil, &proc) ⇒ Object
display multiple columns in a row(on editor)
82 83 84 85 86 87 88 |
# File 'lib/rear/setup/columns.rb', line 82 def row label = nil, &proc # explicit labels will be strings and implicit ones will be numbers # as a way to distinguish them when rendering templates @__rear__row = label ? label.to_s : (Time.now.to_f + rand) self.instance_exec(&proc) if proc @__rear__row = nil end |