adminable 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +49 -62
  3. data/app/controllers/adminable/resources_controller.rb +19 -28
  4. data/app/views/adminable/resources/_form.html.haml +2 -2
  5. data/app/views/adminable/resources/_search.html.haml +3 -3
  6. data/app/views/adminable/resources/form/_belongs_to.html.haml +5 -5
  7. data/app/views/adminable/resources/form/_boolean.html.haml +4 -4
  8. data/app/views/adminable/resources/form/_date.html.haml +3 -3
  9. data/app/views/adminable/resources/form/_datetime.html.haml +3 -3
  10. data/app/views/adminable/resources/form/_decimal.html.haml +3 -3
  11. data/app/views/adminable/resources/form/_float.html.haml +3 -3
  12. data/app/views/adminable/resources/form/_has_many.html.haml +5 -5
  13. data/app/views/adminable/resources/form/_integer.html.haml +3 -3
  14. data/app/views/adminable/resources/form/_string.html.haml +3 -3
  15. data/app/views/adminable/resources/form/_text.html.haml +4 -4
  16. data/app/views/adminable/resources/form/_time.html.haml +3 -3
  17. data/app/views/adminable/resources/form/_timestamp.html.haml +3 -3
  18. data/app/views/adminable/resources/index.html.haml +10 -10
  19. data/app/views/adminable/shared/_label.html.haml +4 -4
  20. data/lib/adminable.rb +15 -16
  21. data/lib/adminable/errors.rb +5 -2
  22. data/lib/adminable/field_collector.rb +53 -0
  23. data/lib/adminable/{attributes → fields}/base.rb +21 -13
  24. data/lib/adminable/fields/belongs_to.rb +9 -0
  25. data/lib/adminable/fields/boolean.rb +6 -0
  26. data/lib/adminable/fields/date.rb +6 -0
  27. data/lib/adminable/fields/datetime.rb +6 -0
  28. data/lib/adminable/fields/decimal.rb +6 -0
  29. data/lib/adminable/fields/float.rb +6 -0
  30. data/lib/adminable/fields/has_many.rb +13 -0
  31. data/lib/adminable/fields/integer.rb +6 -0
  32. data/lib/adminable/fields/string.rb +6 -0
  33. data/lib/adminable/fields/text.rb +6 -0
  34. data/lib/adminable/fields/time.rb +6 -0
  35. data/lib/adminable/fields/timestamp.rb +6 -0
  36. data/lib/adminable/presenters/fields.rb +17 -0
  37. data/lib/adminable/resource.rb +5 -17
  38. data/lib/adminable/version.rb +1 -1
  39. data/lib/generators/adminable/resource/templates/resource_controller.rb.erb +6 -1
  40. data/lib/generators/adminable/resource_generator.rb +9 -1
  41. metadata +17 -17
  42. data/lib/adminable/attributes/association.rb +0 -14
  43. data/lib/adminable/attributes/collection.rb +0 -116
  44. data/lib/adminable/attributes/types/belongs_to.rb +0 -11
  45. data/lib/adminable/attributes/types/boolean.rb +0 -8
  46. data/lib/adminable/attributes/types/date.rb +0 -8
  47. data/lib/adminable/attributes/types/datetime.rb +0 -8
  48. data/lib/adminable/attributes/types/decimal.rb +0 -8
  49. data/lib/adminable/attributes/types/float.rb +0 -8
  50. data/lib/adminable/attributes/types/has_many.rb +0 -15
  51. data/lib/adminable/attributes/types/integer.rb +0 -8
  52. data/lib/adminable/attributes/types/string.rb +0 -8
  53. data/lib/adminable/attributes/types/text.rb +0 -8
  54. data/lib/adminable/attributes/types/time.rb +0 -8
  55. data/lib/adminable/attributes/types/timestamp.rb +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 50dbc10813e44d6cbaafaf677198e95604541bd9
4
- data.tar.gz: 1a583fe099f1a41a986ff8e61b2deb632dae6e9e
3
+ metadata.gz: 6ddb7fa61bee7a687cdc0c39c37990d5bb521304
4
+ data.tar.gz: 39e26845450a55d099ed58a2abc9feb49c151427
5
5
  SHA512:
6
- metadata.gz: 1f46365f19a81adde1666e349976db7626b32a396db05ef6546e9e1a2681816ec4b66c7c02e782a4e8d687ffec705c873550311eb3efbf96cd76dec9fff1af2b
7
- data.tar.gz: e735b3c8245ba04e89450b6bf444d9e628eeaa816498875a91fb3d0a6e3918431cc3993f8b6b08b531595b1a3ebb8316af1e022b15204fd2e061d2ccfe2feeeb
6
+ metadata.gz: 030afe5a4016c70a0ecbd93ab4d42872b2b14307f697d2268f36707c400b8cd0d6a28a93baa939dd4de0ce0cf6b2d89260de5ae618089fc5ee97c0b6fd32d85e
7
+ data.tar.gz: be70b417ed4ef1804fd51549fda2443645be24f6cf3463cb9ffbbdafe3df0eef12dc951ec4c0597ce56592b86e439fec6e64c2c06b2d4c0543020b6f2d66f948
data/README.md CHANGED
@@ -11,7 +11,7 @@ Simple admin interface for Ruby on Rails applications.
11
11
 
12
12
  ## Features
13
13
 
14
- * Built with common Rails controllers with a small DSL.
14
+ * Built with common Rails controllers and views without DSL.
15
15
  * Supports namespaced models.
16
16
  * Has simple search with [Ransack](https://github.com/activerecord-hackery/ransack).
17
17
  * Uses [Bootstrap](https://github.com/twbs/bootstrap) 4.0.
@@ -43,7 +43,7 @@ $ gem install adminable
43
43
 
44
44
  ## Getting Started
45
45
 
46
- First things first. Add routes and create `application_controller.rb` class using generator:
46
+ First things first. Add routes and create `adminable/application_controller.rb` class using generator:
47
47
 
48
48
  ```bash
49
49
  rails g adminable:install
@@ -51,93 +51,80 @@ rails g adminable:install
51
51
  # => insert config/routes.rb
52
52
  ```
53
53
 
54
- #### Generating Resources
54
+ ### Generating Resources
55
55
 
56
- For example you have model `User`, then run:
56
+ Assume you have model `User`, then run:
57
57
 
58
58
  ```bash
59
- rails g adminable:resource user
59
+ rails g adminable:resource users
60
60
  # => create app/controllers/adminable/users_controller.rb
61
61
  ```
62
62
 
63
63
  For namespaced models, like `Blog::Post`, use:
64
64
 
65
65
  ```bash
66
- rails g adminable:resource blog/post
66
+ rails g adminable:resource blog/posts
67
67
  # => create app/controllers/adminable/blog/posts_controller.rb
68
68
  ```
69
69
 
70
- #### Customizing Attributes
70
+ ### Customizing Fields
71
71
 
72
- You can update attributes with simple DSL inside `set_attributes` block:
73
-
74
- ##### For existing attributes
72
+ Change fields as you like inside `fields` method array:
75
73
 
76
74
  ```ruby
77
- set(name, options = {})
78
- ```
79
-
80
- ##### For new attributes
81
-
82
- ```ruby
83
- add(name, type, options = {})
75
+ class Adminable::Blog::PostsController < Adminable::ResourcesController
76
+ def fields
77
+ [
78
+ Adminable::Fields::String.new(:title),
79
+ Adminable::Fields::Text.new(:body),
80
+ Adminable::Fields::Float.new(:rating, form: false),
81
+ Adminable::Fields::Boolean.new(:published),
82
+ Adminable::Fields::BelongsTo.new(:user),
83
+ Adminable::Fields::HasMany.new(:blog_comments)
84
+ ]
85
+ end
86
+ end
84
87
  ```
85
88
 
86
- ##### Attributes Parameters
87
-
88
- * `index` - (`true` or `false`) - Shows attribute on index page.
89
- * `form` - (`true` or `false`) - Shows attribute on new/edit page.
90
- * `center` - (`true` or `false`) - Adds `text-align: center` for attribute value on index page.
91
- * `search` - (`true` or `false`) - Enables search for this attribute.
89
+ ### Fields Parameters
92
90
 
93
- ##### Examples
91
+ #### index
92
+ `true` or `false`, default: `true`.
94
93
 
95
- ```ruby
96
- class Adminable::Blog::PostsController < Adminable::ResourcesController
97
- set_attributes do |attributes|
98
- # Enables search for title column
99
- attributes.set :title, search: true
94
+ Shows field on index page.
100
95
 
101
- # Hides title from new and edit pages
102
- attributes.set :title, form: true
96
+ #### form
97
+ `true` or `false`, default: `true`.
103
98
 
104
- # Adds wysiwyg plugin and hides from index table
105
- attributes.set :text, wysiwyg: true, index: false
99
+ Shows field on new/edit page.
106
100
 
107
- # Adds new attribute `password` with type `string` and some options
108
- attributes.add :password, :string, wysiwyg: true, index: false
101
+ #### center
102
+ `true` or `false`, default `true` for `integer`, `boolean`, `float` and `decimal` fields, `false` otherwise.
109
103
 
110
- # Adds new attribute `author`
111
- attributes << Adminable::Attributes::Types::String.new(:author)
104
+ Adds `text-align: center` for field value on index page.
112
105
 
113
- # Allows search for multiple attributes
114
- attributes.set :title, :body, search: true
115
- end
116
- end
117
- ```
106
+ #### search
107
+ `true` or `false`, default: `false`.
108
+ Enables search for this field.
118
109
 
119
- ##### See Also
110
+ ### See Also
120
111
 
121
112
  * Configured controller for Devise model: [app/controllers/adminable/users_controller.rb](https://github.com/droptheplot/adminable/blob/master/spec/dummy/app/controllers/adminable/users_controller.rb)
122
113
 
123
- ## Built-in Attributes
124
-
125
- List of attributes with default parameters.
126
-
127
- | | index | form | center | wysiwyg |
128
- |------------|-------|------|--------|---------|
129
- | String | + | + | | |
130
- | Text | + | + | | + |
131
- | Integer | + | + | + | |
132
- | Float | + | + | + | |
133
- | Decimal | + | + | + | |
134
- | Date | + | + | | |
135
- | DateTime | + | + | | |
136
- | Time | + | + | | |
137
- | Timestamp | + | + | | |
138
- | Boolean | + | + | + | |
139
- | Belongs To | | + | | |
140
- | Has Many | | + | | |
114
+ ## Built-in Fields
115
+
116
+ * String
117
+ * Text
118
+ * Integer
119
+ * Float
120
+ * Decimal
121
+ * Date
122
+ * DateTime
123
+ * Time
124
+ * Timestamp
125
+ * Boolean
126
+ * Belongs To
127
+ * Has Many
141
128
 
142
129
  ## Generating Partials
143
130
 
@@ -146,7 +133,7 @@ You can use generator to copy original partial to your application.
146
133
  `rails g adminable:partial [layout] [type] [resource]`
147
134
 
148
135
  * `layout` - `index` or `form`.
149
- * `type` - `string`, `text` etc. See [Built-in Attributes](#built-in-attributes).
136
+ * `type` - `string`, `text` etc. See [Built-in Fields](#built-in-fields).
150
137
  * `resource` - Use controller name (e.g. `users`) to replace partial only for single controller or leave blank to replace partials for all controllers.
151
138
 
152
139
  ## F.A.Q
@@ -9,6 +9,7 @@ module Adminable
9
9
  end
10
10
 
11
11
  before_action :set_entry, only: [:edit, :update, :destroy]
12
+ before_action :set_fields, only: [:index, :new, :edit, :create, :update]
12
13
 
13
14
  before_action do
14
15
  append_view_path(
@@ -23,7 +24,7 @@ module Adminable
23
24
  def index
24
25
  @q = @resource.model.ransack(params[:q])
25
26
  @entries = Adminable::Presenters::Entries.new(
26
- @q.result.includes(*@resource.includes).order(id: :desc)
27
+ @q.result.includes(*includes).order(id: :desc)
27
28
  .page(params[:page]).per(25)
28
29
  )
29
30
  end
@@ -74,32 +75,6 @@ module Adminable
74
75
  )
75
76
  end
76
77
 
77
- # Calls from children controller class to manage resource attributes
78
- # @example Update attributes for Adminable::Blog::PostsController
79
- # # app/controllers/adminable/blog/posts_controller.rb
80
- #
81
- # set_attributes do |attributes|
82
- # # Enables search for title column
83
- # attributes.set :title, search: true
84
- #
85
- # # Hides title from new and edit pages
86
- # attributes.set :title, form: true
87
- #
88
- # # Adds wysiwyg plugin and hides from index table
89
- # attributes.set :text, wysiwyg: true, index: false
90
- #
91
- # # Adds new attribute `password` with type `string` and some options
92
- # attributes.add :password, :string, wysiwyg: true, index: false
93
- #
94
- # # Adds new attribute `author`
95
- # attributes << Adminable::Attributes::Types::String.new(:author)
96
- # end
97
- def self.set_attributes
98
- before_action do
99
- @resource.attributes.configure { yield(@resource.attributes) }
100
- end
101
- end
102
-
103
78
  private
104
79
 
105
80
  def set_entry
@@ -107,14 +82,30 @@ module Adminable
107
82
  @entry = Adminable::Presenters::Entry.new(entry)
108
83
  end
109
84
 
85
+ def set_fields
86
+ @fields = Adminable::Presenters::Fields.new(fields)
87
+ end
88
+
110
89
  def resource_model_name
111
90
  controller_path.sub(%r{^adminable/}, '')
112
91
  end
113
92
 
114
93
  def resource_params
115
94
  params.require(@resource.model.model_name.param_key).permit(
116
- *@resource.attributes.form.map(&:strong_parameter)
95
+ *fields.map(&:strong_parameter)
117
96
  )
118
97
  end
98
+
99
+ def fields
100
+ raise Adminable::FieldsNotDefined
101
+ end
102
+
103
+ def includes
104
+ association_fields = fields.select do |field|
105
+ %i(belongs_to has_many).include?(field.type)
106
+ end
107
+
108
+ association_fields.any? ? association_fields.map(&:name) : false
109
+ end
119
110
  end
120
111
  end
@@ -1,7 +1,7 @@
1
1
  = form_for @entry, method: (@entry.persisted? ? :patch : :post) do |f|
2
- - @resource.attributes.form.each do |attribute|
2
+ - @fields.form.each do |field|
3
3
  %fieldset.form-group
4
- = render attribute.form_partial_path, entry: @entry, attribute: attribute
4
+ = render field.form_partial_path, entry: @entry, field: field
5
5
  %fieldset.form-group
6
6
  = f.submit t('adminable.buttons.submit'), class: 'btn btn-primary'
7
7
  = link_to t('adminable.buttons.back'), polymorphic_path(@resource.model),
@@ -1,9 +1,9 @@
1
1
  .card.bg-faded
2
2
  .card-block
3
3
  = search_form_for @q do |f|
4
- - @resource.attributes.search.each do |attribute|
4
+ - @fields.search.each do |field|
5
5
  %fieldset.form-group
6
- = f.label attribute.ransack_name, @resource.model.human_attribute_name(attribute.name),
6
+ = f.label field.ransack_name, @resource.model.human_attribute_name(field.name),
7
7
  class: 'text-muted'
8
- = f.search_field attribute.ransack_name, class: 'form-control'
8
+ = f.search_field field.ransack_name, class: 'form-control'
9
9
  = f.submit t('adminable.buttons.search'), class: 'btn btn-primary-outline'
@@ -1,11 +1,11 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = hidden_field_tag "#{@resource.model.model_name.param_key}[#{attribute.key}]", nil
1
+ = render 'adminable/shared/label', field: field
2
+ = hidden_field_tag "#{@resource.model.model_name.param_key}[#{field.key}]", nil
3
3
  #clusterizeScrollArea.clusterize-scroll.associations
4
4
  #clusterizeContentArea.clusterize-content
5
- - attribute.association.entries.each do |association_entry|
5
+ - Adminable::Presenters::Entries.new(entry.association(field.name).klass.all).each do |association_entry|
6
6
  .association
7
7
  %label.c-input.c-radio.m-a-0
8
- = radio_button_tag "#{@resource.model.model_name.param_key}[#{attribute.key}]",
9
- association_entry.id, entry.send(attribute.key) == association_entry.id
8
+ = radio_button_tag "#{@resource.model.model_name.param_key}[#{field.key}]",
9
+ association_entry.id, entry.send(field.key) == association_entry.id
10
10
  %span.c-indicator
11
11
  = association_entry.link_to_self
@@ -1,6 +1,6 @@
1
1
  %label.c-input.c-checkbox
2
- = hidden_field_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]", 0
3
- = check_box_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]", 1,
4
- entry.send(attribute.key)
2
+ = hidden_field_tag "#{@resource.model.model_name.param_key}[#{field.name}]", 0
3
+ = check_box_tag "#{@resource.model.model_name.param_key}[#{field.name}]", 1,
4
+ entry.send(field.key)
5
5
  %span.c-indicator
6
- = @resource.model.human_attribute_name(attribute.name)
6
+ = @resource.model.human_attribute_name(field.name)
@@ -1,3 +1,3 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = date_field_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]",
3
- entry[attribute.name], class: 'form-control'
1
+ = render 'adminable/shared/label', field: field
2
+ = date_field_tag "#{@resource.model.model_name.param_key}[#{field.name}]",
3
+ entry[field.name], class: 'form-control'
@@ -1,3 +1,3 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = datetime_field_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]",
3
- entry[attribute.name], class: 'form-control'
1
+ = render 'adminable/shared/label', field: field
2
+ = datetime_field_tag "#{@resource.model.model_name.param_key}[#{field.name}]",
3
+ entry[field.name], class: 'form-control'
@@ -1,3 +1,3 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = number_field_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]",
3
- entry[attribute.name], class: 'form-control'
1
+ = render 'adminable/shared/label', field: field
2
+ = number_field_tag "#{@resource.model.model_name.param_key}[#{field.name}]",
3
+ entry[field.name], class: 'form-control'
@@ -1,3 +1,3 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = number_field_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]",
3
- entry[attribute.name], class: 'form-control'
1
+ = render 'adminable/shared/label', field: field
2
+ = number_field_tag "#{@resource.model.model_name.param_key}[#{field.name}]",
3
+ entry[field.name], class: 'form-control'
@@ -1,12 +1,12 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = hidden_field_tag "#{@resource.model.model_name.param_key}[#{attribute.key}][]", nil
1
+ = render 'adminable/shared/label', field: field
2
+ = hidden_field_tag "#{@resource.model.model_name.param_key}[#{field.key}][]", nil
3
3
  #clusterizeScrollArea.clusterize-scroll.associations
4
4
  #clusterizeContentArea.clusterize-content
5
- - attribute.association.entries.each do |association_entry|
5
+ - Adminable::Presenters::Entries.new(entry.association(field.name).klass.all).each do |association_entry|
6
6
  .association
7
7
  %label.c-input.c-checkbox.m-a-0
8
- = check_box_tag "#{@resource.model.model_name.param_key}[#{attribute.key}][]",
9
- association_entry.id, entry.send(attribute.key).include?(association_entry.id)
8
+ = check_box_tag "#{@resource.model.model_name.param_key}[#{field.key}][]",
9
+ association_entry.id, entry.send(field.key).include?(association_entry.id)
10
10
  %span.c-indicator
11
11
  = link_to association_entry.to_name,
12
12
  edit_polymorphic_path(association_entry),
@@ -1,3 +1,3 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = number_field_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]",
3
- entry[attribute.name], class: 'form-control'
1
+ = render 'adminable/shared/label', field: field
2
+ = number_field_tag "#{@resource.model.model_name.param_key}[#{field.name}]",
3
+ entry[field.name], class: 'form-control'
@@ -1,3 +1,3 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = text_field_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]",
3
- entry[attribute.name], class: 'form-control'
1
+ = render 'adminable/shared/label', field: field
2
+ = text_field_tag "#{@resource.model.model_name.param_key}[#{field.name}]",
3
+ entry[field.name], class: 'form-control'
@@ -1,4 +1,4 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = text_area_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]",
3
- entry[attribute.name],
4
- class: "form-control #{ 'wysiwyg' if attribute.options[:wysiwyg] }", rows: 5
1
+ = render 'adminable/shared/label', field: field
2
+ = text_area_tag "#{@resource.model.model_name.param_key}[#{field.name}]",
3
+ entry[field.name],
4
+ class: "form-control #{ 'wysiwyg' if field.options[:wysiwyg] }", rows: 5
@@ -1,3 +1,3 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = text_field_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]",
3
- entry[attribute.name], class: 'form-control'
1
+ = render 'adminable/shared/label', field: field
2
+ = text_field_tag "#{@resource.model.model_name.param_key}[#{field.name}]",
3
+ entry[field.name], class: 'form-control'
@@ -1,3 +1,3 @@
1
- = render 'adminable/shared/label', attribute: attribute
2
- = text_field_tag "#{@resource.model.model_name.param_key}[#{attribute.name}]",
3
- entry[attribute.name], class: 'form-control'
1
+ = render 'adminable/shared/label', field: field
2
+ = text_field_tag "#{@resource.model.model_name.param_key}[#{field.name}]",
3
+ entry[field.name], class: 'form-control'
@@ -4,30 +4,30 @@
4
4
  = link_to t('adminable.buttons.new', resource: @resource.model.model_name.human),
5
5
  new_polymorphic_path(@resource.model), class: 'btn btn-primary pull-md-right m-b-2'
6
6
  .row
7
- %div{ :class => (@resource.attributes.search.any? ? 'col-md-9' : 'col-md-12') }
7
+ %div{ :class => (@fields.search.any? ? 'col-md-9' : 'col-md-12') }
8
8
  .table-responsive.m-b-3
9
9
  %table.table.table-striped
10
10
  %thead
11
11
  %tr
12
- - @resource.attributes.index.each do |attribute|
13
- %th.text-nowrap{ :class => ('text-md-center' if attribute.options[:center]) }
14
- = sort_link(@q, attribute.name, hide_indicator: true)
12
+ - @fields.index.each do |field|
13
+ %th.text-nowrap{ :class => ('text-md-center' if field.options[:center]) }
14
+ = sort_link(@q, field.name, hide_indicator: true)
15
15
  %th
16
16
  %tbody
17
17
  - @entries.each do |entry|
18
18
  %tr
19
- - @resource.attributes.index.each do |attribute|
20
- %td{ :class => ('text-md-center' if attribute.options[:center]) }
21
- = render attribute.index_partial_path, entry: entry,
22
- attribute: attribute, value: entry.public_send(attribute.name)
19
+ - @fields.index.each do |field|
20
+ %td{ :class => ('text-md-center' if field.options[:center]) }
21
+ = render field.index_partial_path, entry: entry,
22
+ field: field, value: entry.public_send(field.name)
23
23
  %td.text-nowrap.text-md-right
24
24
  = entry.link_to_edit_small
25
25
  = entry.link_to_delete_small
26
26
  - if @entries.empty?
27
27
  %tr
28
- %td.text-md-center.text-muted{ :colspan => @resource.attributes.index.size + 1 }
28
+ %td.text-md-center.text-muted{ :colspan => @fields.index.size + 1 }
29
29
  No data available
30
- - if @resource.attributes.search.any?
30
+ - if @fields.search.any?
31
31
  .col-md-3.hidden-sm-down
32
32
  = render 'search'
33
33
  = paginate @entries, views_prefix: 'adminable'
@@ -1,8 +1,8 @@
1
- = label_tag attribute.name do
2
- = @resource.model.human_attribute_name(attribute.name)
3
- - if attribute.options[:required]
1
+ = label_tag field.name do
2
+ = @resource.model.human_attribute_name(field.name)
3
+ - if field.options[:required]
4
4
  %span.text-muted.m-l-1
5
5
  %i.fa.fa-exclamation-circle{ 'data-toggle' => :tooltip, 'data-placement' => :right, :title => 'Required' }
6
- - if %i(belongs_to has_many).include?(attribute.type)
6
+ - if %i(belongs_to has_many).include?(field.type)
7
7
  %span.text-muted.m-l-1.uncheck-associations
8
8
  %i.fa.fa-remove{ 'data-toggle' => :tooltip, 'data-placement' => :right, :title => 'Uncheck all' }
@@ -7,24 +7,23 @@ require 'adminable/resource'
7
7
  require 'adminable/presenters/base'
8
8
  require 'adminable/presenters/entry'
9
9
  require 'adminable/presenters/entries'
10
+ require 'adminable/presenters/fields'
10
11
 
11
- require 'adminable/attributes/collection'
12
- require 'adminable/attributes/association'
12
+ require 'adminable/field_collector'
13
13
 
14
- require 'adminable/attributes/base'
15
-
16
- require 'adminable/attributes/types/belongs_to'
17
- require 'adminable/attributes/types/boolean'
18
- require 'adminable/attributes/types/date'
19
- require 'adminable/attributes/types/datetime'
20
- require 'adminable/attributes/types/decimal'
21
- require 'adminable/attributes/types/float'
22
- require 'adminable/attributes/types/has_many'
23
- require 'adminable/attributes/types/integer'
24
- require 'adminable/attributes/types/string'
25
- require 'adminable/attributes/types/text'
26
- require 'adminable/attributes/types/time'
27
- require 'adminable/attributes/types/timestamp'
14
+ require 'adminable/fields/base'
15
+ require 'adminable/fields/belongs_to'
16
+ require 'adminable/fields/boolean'
17
+ require 'adminable/fields/date'
18
+ require 'adminable/fields/datetime'
19
+ require 'adminable/fields/decimal'
20
+ require 'adminable/fields/float'
21
+ require 'adminable/fields/has_many'
22
+ require 'adminable/fields/integer'
23
+ require 'adminable/fields/string'
24
+ require 'adminable/fields/text'
25
+ require 'adminable/fields/time'
26
+ require 'adminable/fields/timestamp'
28
27
 
29
28
  require 'haml-rails'
30
29
  require 'sass-rails'
@@ -1,7 +1,10 @@
1
1
  module Adminable
2
- class AttributeNotImplemented < StandardError
2
+ class FieldsNotDefined < StandardError
3
3
  end
4
4
 
5
- class AttributeNotFound < StandardError
5
+ class FieldNotImplemented < StandardError
6
+ end
7
+
8
+ class FieldNotFound < StandardError
6
9
  end
7
10
  end
@@ -0,0 +1,53 @@
1
+ module Adminable
2
+ class FieldCollector
3
+ # @return [ActiveRecord::Base] activerecord model class
4
+ # @example
5
+ # Adminable::Fields::Collection.new(User).model
6
+ # # => User(id: integer, email: string, password_hash: string)
7
+ attr_reader :model
8
+
9
+ # @return [Array] fields from activerecord model
10
+ attr_reader :all
11
+
12
+ # @param model [ActiveRecord::Base] activerecord model class
13
+ def initialize(model)
14
+ @model = model
15
+ @all ||= columns + associations
16
+ end
17
+
18
+ # Collects fields from model columns
19
+ # @return [Array]
20
+ #
21
+ # rubocop:disable Metrics/MethodLength
22
+ def columns
23
+ @columns ||= [].tap do |fields|
24
+ @model.columns.reject { |a| a.name.match(/_id$/) }.each do |column|
25
+ fields << resolve(column.type, column.name)
26
+ end
27
+ end
28
+ end
29
+
30
+ # Collects fields from model associations
31
+ # @return [Array]
32
+ def associations
33
+ @associations ||= [].tap do |fields|
34
+ @model.reflect_on_all_associations.each do |association|
35
+ fields << resolve(association.macro, association.name)
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def resolve(type, name)
43
+ class_name = "adminable/fields/#{type}".classify
44
+ "#{class_name}.new(:#{name})"
45
+ end
46
+
47
+ def required?(name)
48
+ @model.validators_on(name).any? do |validator|
49
+ validator.class == ActiveRecord::Validations::PresenceValidator
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,44 +1,52 @@
1
1
  module Adminable
2
- module Attributes
3
- # Base class for attributes types
2
+ module Fields
3
+ # Base class for fields
4
4
  # @note Cannot be initialized
5
5
  class Base
6
- attr_reader :name, :options, :key, :strong_parameter, :association
6
+ # @return [Symbol] field name
7
+ attr_reader :name
7
8
 
8
- # @param name [Symbol] attribute name e.g. `:id` or `:title`
9
+ # @return [Hash] default options for field
10
+ attr_reader :options
11
+
12
+ # @param name [Symbol] field name e.g. `:id` or `:title`
9
13
  # @param options [Hash] options, see {default_options}
10
14
  def initialize(name, options = {})
11
15
  raise 'Base class cannot be initialized' if self.class == Base
12
16
 
13
17
  @name = name.to_sym
14
18
  @options = default_options.merge(options)
15
-
16
- @association = Adminable::Attributes::Association.new(
17
- options[:association]
18
- ) if options[:association]
19
19
  end
20
20
 
21
+ # @return [Symbol] field form key
21
22
  def key
22
23
  @key ||= name
23
24
  end
24
25
 
26
+ # @return [Symbol] controller strong parameters key
25
27
  def strong_parameter
26
28
  @strong_parameter ||= key
27
29
  end
28
30
 
31
+ # @return [String] ransack form key
29
32
  def ransack_name
30
33
  @ransack_name ||= "#{name}_cont"
31
34
  end
32
35
 
33
- # @return [Symbol] class type e.g. `:text` for Adminable::Attributes::Text
36
+ # @return [Symbol] field type
37
+ # @example
38
+ # Adminable::Fields::String.new(:title).type
39
+ # # => :string
34
40
  def type
35
41
  @type ||= self.class.name.demodulize.underscore.to_sym
36
42
  end
37
43
 
44
+ # @return [String] path to field index partial
38
45
  def index_partial_path
39
46
  "index/#{type}"
40
47
  end
41
48
 
49
+ # @return [String] path to field form partial
42
50
  def form_partial_path
43
51
  "form/#{type}"
44
52
  end
@@ -47,12 +55,12 @@ module Adminable
47
55
 
48
56
  def default_options
49
57
  {
50
- index: %i(belongs_to has_many).exclude?(type),
58
+ index: true,
59
+ form: true,
60
+ wysiwyg: false,
51
61
  search: false,
52
- form: %i(id created_at updated_at).exclude?(name),
53
62
  required: false,
54
- center: %i(integer boolean float decimal).include?(type),
55
- wysiwyg: false
63
+ center: %i(integer boolean float decimal).include?(type)
56
64
  }
57
65
  end
58
66
  end
@@ -0,0 +1,9 @@
1
+ module Adminable
2
+ module Fields
3
+ class BelongsTo < Base
4
+ def key
5
+ "#{name}_id"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ module Adminable
2
+ module Fields
3
+ class Boolean < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Adminable
2
+ module Fields
3
+ class Date < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Adminable
2
+ module Fields
3
+ class Datetime < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Adminable
2
+ module Fields
3
+ class Decimal < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Adminable
2
+ module Fields
3
+ class Float < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ module Adminable
2
+ module Fields
3
+ class HasMany < Base
4
+ def key
5
+ "#{@name.to_s.singularize}_ids"
6
+ end
7
+
8
+ def strong_parameter
9
+ { key => [] }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module Adminable
2
+ module Fields
3
+ class Integer < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Adminable
2
+ module Fields
3
+ class String < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Adminable
2
+ module Fields
3
+ class Text < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Adminable
2
+ module Fields
3
+ class Time < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Adminable
2
+ module Fields
3
+ class Timestamp < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,17 @@
1
+ module Adminable
2
+ module Presenters
3
+ class Fields < SimpleDelegator
4
+ def index
5
+ select { |field| field.options[:index] }
6
+ end
7
+
8
+ def form
9
+ select { |field| field.options[:form] }
10
+ end
11
+
12
+ def search
13
+ select { |field| field.options[:search] }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,6 +1,8 @@
1
1
  module Adminable
2
2
  class Resource
3
- attr_reader :name, :model, :attributes
3
+ include Comparable
4
+
5
+ attr_reader :name, :model, :fields
4
6
 
5
7
  # @param name [String] resource name, usually same as the model name
6
8
  def initialize(name)
@@ -13,22 +15,8 @@ module Adminable
13
15
  @route ||= @model.name.underscore.pluralize.tr('/', '_')
14
16
  end
15
17
 
16
- # @return [Array] of associations names for ActiveRecord queries
17
- def includes
18
- @includes ||= if attributes.associations.present?
19
- attributes.associations.map(&:name)
20
- else
21
- false
22
- end
23
- end
24
-
25
- # @return [Array] collection, see {Adminable::Attributes::Collection}
26
- def attributes
27
- @attributes ||= Adminable::Attributes::Collection.new(@model)
28
- end
29
-
30
- def ==(other)
31
- other.is_a?(Adminable::Resource) && name == other.name
18
+ def <=>(other)
19
+ other.is_a?(Adminable::Resource) && name <=> other.name
32
20
  end
33
21
  end
34
22
  end
@@ -1,3 +1,3 @@
1
1
  module Adminable
2
- VERSION = '0.0.5'.freeze
2
+ VERSION = '0.0.6'.freeze
3
3
  end
@@ -1,2 +1,7 @@
1
- class <%= resource_class %>Controller < Adminable::ResourcesController
1
+ class <%= resource_class_name %>Controller < Adminable::ResourcesController
2
+ def fields
3
+ [
4
+ <%= fields.join(",\n\t\t\t") %>
5
+ ]
6
+ end
2
7
  end
@@ -20,9 +20,17 @@ module Adminable
20
20
  name.underscore.pluralize
21
21
  end
22
22
 
23
- def resource_class
23
+ def resource_class_name
24
24
  "adminable/#{resource_name}".classify.pluralize
25
25
  end
26
+
27
+ def model_class
28
+ name.classify.constantize
29
+ end
30
+
31
+ def fields
32
+ Adminable::FieldCollector.new(model_class).all
33
+ end
26
34
  end
27
35
  end
28
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: adminable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Novikov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-08 00:00:00.000000000 Z
11
+ date: 2016-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -370,27 +370,27 @@ files:
370
370
  - config/locales/adminable.ru.yml
371
371
  - config/routes.rb
372
372
  - lib/adminable.rb
373
- - lib/adminable/attributes/association.rb
374
- - lib/adminable/attributes/base.rb
375
- - lib/adminable/attributes/collection.rb
376
- - lib/adminable/attributes/types/belongs_to.rb
377
- - lib/adminable/attributes/types/boolean.rb
378
- - lib/adminable/attributes/types/date.rb
379
- - lib/adminable/attributes/types/datetime.rb
380
- - lib/adminable/attributes/types/decimal.rb
381
- - lib/adminable/attributes/types/float.rb
382
- - lib/adminable/attributes/types/has_many.rb
383
- - lib/adminable/attributes/types/integer.rb
384
- - lib/adminable/attributes/types/string.rb
385
- - lib/adminable/attributes/types/text.rb
386
- - lib/adminable/attributes/types/time.rb
387
- - lib/adminable/attributes/types/timestamp.rb
388
373
  - lib/adminable/configuration.rb
389
374
  - lib/adminable/engine.rb
390
375
  - lib/adminable/errors.rb
376
+ - lib/adminable/field_collector.rb
377
+ - lib/adminable/fields/base.rb
378
+ - lib/adminable/fields/belongs_to.rb
379
+ - lib/adminable/fields/boolean.rb
380
+ - lib/adminable/fields/date.rb
381
+ - lib/adminable/fields/datetime.rb
382
+ - lib/adminable/fields/decimal.rb
383
+ - lib/adminable/fields/float.rb
384
+ - lib/adminable/fields/has_many.rb
385
+ - lib/adminable/fields/integer.rb
386
+ - lib/adminable/fields/string.rb
387
+ - lib/adminable/fields/text.rb
388
+ - lib/adminable/fields/time.rb
389
+ - lib/adminable/fields/timestamp.rb
391
390
  - lib/adminable/presenters/base.rb
392
391
  - lib/adminable/presenters/entries.rb
393
392
  - lib/adminable/presenters/entry.rb
393
+ - lib/adminable/presenters/fields.rb
394
394
  - lib/adminable/resource.rb
395
395
  - lib/adminable/version.rb
396
396
  - lib/generators/adminable/install/templates/application_controller.rb
@@ -1,14 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- class Association
4
- attr_reader :reflection, :model, :entries
5
-
6
- # @param reflection [Object] ActiveRecord::Reflection::HasManyReflection
7
- def initialize(reflection)
8
- @reflection = reflection
9
- @model = @reflection.klass
10
- @entries = Adminable::Presenters::Entries.new(@model)
11
- end
12
- end
13
- end
14
- end
@@ -1,116 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- class Collection
4
- include Enumerable
5
- extend Forwardable
6
-
7
- def_delegators :@all, :[], :<<, :each, :first, :last, :push, :unshift
8
-
9
- attr_reader :model, :all
10
-
11
- # @param model [Class] model from Rails application e.g. `User` or `Post`
12
- def initialize(model)
13
- @model = model
14
- @all ||= columns + associations
15
- end
16
-
17
- def index
18
- all.select { |attribute| attribute.options[:index] }
19
- end
20
-
21
- def form
22
- all.select { |attribute| attribute.options[:form] }
23
- end
24
-
25
- def search
26
- all.select { |attribute| attribute.options[:search] }
27
- end
28
-
29
- # Collects attributes from model columns
30
- # @return [Array]
31
- #
32
- # rubocop:disable Metrics/MethodLength
33
- def columns
34
- @columns ||= [].tap do |attributes|
35
- @model.columns.reject { |a| a.name.match(/_id$/) }.each do |column|
36
- begin
37
- attributes << resolve(column.type).new(
38
- column.name,
39
- required: required?(column.name)
40
- )
41
- rescue Adminable::AttributeNotImplemented
42
- next
43
- end
44
- end
45
- end
46
- end
47
-
48
- # Collects attributes from model associations
49
- # @return [Array]
50
- def associations
51
- @associations ||= [].tap do |attributes|
52
- @model.reflect_on_all_associations.each do |association|
53
- attributes << resolve(association.macro).new(
54
- association.name,
55
- required: required?(association.name),
56
- association: association
57
- )
58
- end
59
- end
60
- end
61
-
62
- def configure
63
- yield
64
- end
65
-
66
- # Changes options for given attribute
67
- # @param name [Symbol] name of attribute e.g. `:title`
68
- # @param options [Hash] options to update
69
- def set(*args)
70
- options = args.extract_options!
71
- names = args
72
-
73
- options.each do |key, value|
74
- names.each do |name|
75
- get(name).options[key] = value
76
- end
77
- end
78
- end
79
-
80
- # Finds attribute by name
81
- # @param name [Symbol] name of attribute e.g. `:title`
82
- # @return [Object] e.g. `Adminable::Attribute::Types::String` for `:title`
83
- def get(name)
84
- @all.find { |attribute| attribute.name == name } ||
85
- raise(
86
- Adminable::AttributeNotFound,
87
- "couldn't find attribute with name `#{name}`"
88
- )
89
- end
90
-
91
- # Adds new attribute to collection
92
- # @param name [Symbol] name of attribute e.g. `:title`
93
- # @param type [Symbol] type of attribute e.g. `:string`
94
- def add(name, type, options = {})
95
- @all << resolve(type).new(name, **options)
96
- end
97
-
98
- private
99
-
100
- def resolve(type)
101
- "adminable/attributes/types/#{type}".classify.constantize
102
- rescue NameError
103
- raise(
104
- Adminable::AttributeNotImplemented,
105
- "type `#{type}` is not supported yet."
106
- )
107
- end
108
-
109
- def required?(name)
110
- @model.validators_on(name).any? do |validator|
111
- validator.class == ActiveRecord::Validations::PresenceValidator
112
- end
113
- end
114
- end
115
- end
116
- end
@@ -1,11 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class BelongsTo < Base
5
- def key
6
- @association.reflection.foreign_key
7
- end
8
- end
9
- end
10
- end
11
- end
@@ -1,8 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class Boolean < Base
5
- end
6
- end
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class Date < Base
5
- end
6
- end
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class Datetime < Base
5
- end
6
- end
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class Decimal < Base
5
- end
6
- end
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class Float < Base
5
- end
6
- end
7
- end
8
- end
@@ -1,15 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class HasMany < Base
5
- def key
6
- @key = "#{@name.to_s.singularize}_ids"
7
- end
8
-
9
- def strong_parameter
10
- { key => [] }
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,8 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class Integer < Base
5
- end
6
- end
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class String < Base
5
- end
6
- end
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class Text < Base
5
- end
6
- end
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class Time < Base
5
- end
6
- end
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- module Adminable
2
- module Attributes
3
- module Types
4
- class Timestamp < Base
5
- end
6
- end
7
- end
8
- end