constructor-pages 1.0.0beta1 → 1.0.0beta2

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/constructor_pages/urlify.js +1 -0
  3. data/app/controllers/constructor_pages/fields_controller.rb +22 -28
  4. data/app/controllers/constructor_pages/pages_controller.rb +19 -48
  5. data/app/controllers/constructor_pages/templates_controller.rb +8 -20
  6. data/app/helpers/constructor_pages/fields_helper.rb +0 -2
  7. data/app/helpers/constructor_pages/pages_helper.rb +2 -9
  8. data/app/models/constructor_pages/field.rb +24 -10
  9. data/app/models/constructor_pages/page.rb +10 -13
  10. data/app/models/constructor_pages/template.rb +5 -4
  11. data/app/models/constructor_pages/types/boolean_type.rb +0 -2
  12. data/app/models/constructor_pages/types/date_type.rb +0 -2
  13. data/app/models/constructor_pages/types/float_type.rb +0 -2
  14. data/app/models/constructor_pages/types/html_type.rb +0 -2
  15. data/app/models/constructor_pages/types/image_type.rb +0 -2
  16. data/app/models/constructor_pages/types/integer_type.rb +0 -2
  17. data/app/models/constructor_pages/types/string_type.rb +0 -2
  18. data/app/models/constructor_pages/types/text_type.rb +0 -2
  19. data/app/views/constructor_pages/fields/_form.html.slim +4 -4
  20. data/app/views/constructor_pages/fields/types/_boolean.html.slim +1 -0
  21. data/app/views/constructor_pages/fields/types/_html.html.slim +1 -1
  22. data/app/views/constructor_pages/fields/types/_string.html.slim +1 -1
  23. data/app/views/constructor_pages/fields/types/_text.html.slim +1 -1
  24. data/app/views/constructor_pages/pages/_form.html.slim +5 -8
  25. data/app/views/constructor_pages/pages/index.html.slim +2 -3
  26. data/app/views/constructor_pages/templates/_form.html.slim +0 -4
  27. data/config/locales/en.yml +2 -0
  28. data/config/locales/fr.yml +2 -0
  29. data/config/locales/ru.yml +2 -0
  30. data/config/routes.rb +1 -1
  31. data/constructor-pages.gemspec +1 -2
  32. data/db/migrate/10_create_html_types.rb +1 -5
  33. data/db/migrate/11_create_image_types.rb +1 -5
  34. data/db/migrate/12_add_default_template.rb +3 -3
  35. data/db/migrate/14_remove_child_id_from_templates.rb +2 -6
  36. data/db/migrate/15_rename_link_to_redirect.rb +1 -5
  37. data/db/migrate/16_add_indexes.rb +13 -0
  38. data/db/migrate/1_create_pages.rb +12 -16
  39. data/db/migrate/2_create_templates.rb +1 -5
  40. data/db/migrate/3_create_fields.rb +1 -5
  41. data/db/migrate/4_create_string_types.rb +2 -6
  42. data/db/migrate/5_create_float_types.rb +2 -6
  43. data/db/migrate/6_create_boolean_types.rb +2 -6
  44. data/db/migrate/7_create_integer_types.rb +2 -6
  45. data/db/migrate/8_create_text_types.rb +1 -5
  46. data/db/migrate/9_create_date_types.rb +2 -6
  47. data/lib/constructor-pages.rb +1 -0
  48. data/spec/features/constructor_pages/fields_spec.rb +5 -6
  49. data/spec/features/constructor_pages/pages_spec.rb +26 -63
  50. data/spec/features/constructor_pages/templates_spec.rb +15 -28
  51. data/spec/models/constructor_pages/field_spec.rb +0 -2
  52. data/spec/models/constructor_pages/page_spec.rb +15 -31
  53. data/spec/models/constructor_pages/template_spec.rb +0 -2
  54. data/spec/models/constructor_pages/types/boolean_type_spec.rb +0 -2
  55. data/spec/models/constructor_pages/types/date_type_spec.rb +0 -2
  56. data/spec/models/constructor_pages/types/float_type_spec.rb +0 -5
  57. data/spec/models/constructor_pages/types/html_type_spec.rb +0 -2
  58. data/spec/models/constructor_pages/types/integer_type_spec.rb +0 -2
  59. data/spec/models/constructor_pages/types/string_type_spec.rb +0 -2
  60. data/spec/models/constructor_pages/types/text_type_spec.rb +0 -2
  61. metadata +19 -7
  62. data/app/helpers/constructor_pages/code_name_uniq.rb +0 -7
  63. data/app/helpers/constructor_pages/for_select.rb +0 -13
  64. data/app/helpers/constructor_pages/templates_helper.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 076592077cf4756361ca5c20ab57059950ffc7f5
4
- data.tar.gz: b6fdd943392882e13f845a80b61a02696a449230
3
+ metadata.gz: f675af9c0fbb73b082bfa366e4f96428ef9c9b0e
4
+ data.tar.gz: 6c2a949553d8d3aca605e8b7b5e9c19fcb045139
5
5
  SHA512:
6
- metadata.gz: ad18e8a26816becc289dd612ddd8270cdc3babacb8deb4b792f0e108e557fcec13138135b49fc1ab2cf4c430f3f97e17c0c8ef3ef36d579a36594cbb487577d3
7
- data.tar.gz: 72d2db5db1bd322ec155f42e77284b1e952f002692f485f848a5b1ef34afa42d62c442abddc5cb342fce915ab9a1fb81776fe812ec0e4b36c710fe8f9ff9a0d8
6
+ metadata.gz: c012caaa5894b41848bed34798e3a9dbdbe98690321eb5eb2e2b3546a83b4545ed04b83f4b1f1070198dd77f8c6a38b7efd46c840618161a4dbdaf91241a946a
7
+ data.tar.gz: 17091449e7387cf48d44d91005c6391be092434e92715bd4d3696c6f6d531a6dda1cdd33efb88aee8b95feefeebb31830b0cee9c9687cd2bb352ad9420189ae3
@@ -69,6 +69,7 @@ function URLify(s, num_chars) {
69
69
  s = s.replace(/[^-\w\s]/g, '-'); // remove unneeded chars
70
70
  s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
71
71
  s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
72
+ s = s.replace(/^-+|-+$/g, ''); // trim leading/trailing hyphens
72
73
  s = s.toLowerCase(); // convert to lowercase
73
74
  return s.substring(0, num_chars);// trim to first num_chars chars
74
75
  }
@@ -1,68 +1,62 @@
1
- # encoding: utf-8
2
-
3
1
  module ConstructorPages
4
2
  class FieldsController < ConstructorCore::ApplicationController
5
3
  include TheSortableTreeController::Rebuild
6
4
  include TheSortableTreeController::ExpandNode
7
5
 
6
+ before_action :set_field, only: [:edit, :update, :destroy]
7
+
8
8
  def new
9
- @field = Field.new.tap {|f| @template = f.template = Template.find(params[:template_id])}
9
+ @field = Field.new template_id: params[:template_id]
10
10
  end
11
11
 
12
12
  def edit
13
- @field = Field.find(params[:id]).tap {|f| @template = f.template = Template.find(params[:template_id])}
14
13
  end
15
14
 
16
15
  def create
17
16
  @field = Field.new field_params
18
- @template = @field.template
19
17
 
20
18
  if @field.save
21
- redirect_to edit_template_path(@template), notice: t(:field_success_added, name: @field.name)
19
+ redirect_to edit_template_path(@field.template), notice: t(:field_success_added, name: @field.name)
22
20
  else
23
- render action: :new
21
+ render :new
24
22
  end
25
23
  end
26
24
 
27
25
  def update
28
- @field = Field.find params[:id]
29
- @template = @field.template
30
-
31
26
  unless @field.type_value == params[:field][:type_value]
32
27
  @field.type_class.where(field_id: @field.id).each do |field|
33
- "constructor_pages/types/#{params[:field][:type_value]}_type".classify.constantize.new(
34
- field_id: @field.id, page_id: field.page_id).tap {|f|
35
- f.value = field.value unless [@field.type_value, params[:field][:type_value]].include?('image') and
36
- (@field.type_value == 'string' and field.value.strip == '')
37
- f.save; field.destroy
38
- }
28
+ _field = "constructor_pages/types/#{params[:field][:type_value]}_type".classify.constantize.new(field_id: @field.id, page_id: field.page_id)
29
+
30
+ unless [@field.type_value, params[:field][:type_value]].include?('image') && (@field.type_value == 'string' && field.value.strip == '')
31
+ _field.value = field.value
32
+ end
33
+
34
+ _field.save
35
+ field.destroy
39
36
  end
40
37
  end
41
38
 
42
39
  if @field.update field_params
43
- redirect_to edit_template_path(@template.id), notice: t(:field_success_updated, name: @field.name)
40
+ redirect_to edit_template_path(@field.template.id), notice: t(:field_success_updated, name: @field.name)
44
41
  else
45
- render action: :edit
42
+ render :edit
46
43
  end
47
44
  end
48
45
 
49
46
  def destroy
50
- @field = Field.find(params[:id])
51
- name, template = @field.name, @field.template.id
52
47
  @field.destroy
53
- redirect_to edit_template_url(template), notice: t(:field_success_removed, name: name)
48
+ redirect_to edit_template_url(@field.template), notice: t(:field_success_removed, name: @field.name)
54
49
  end
55
50
 
56
- def sortable_model
57
- Field
58
- end
59
-
60
- def sortable_collection
61
- ConstructorPages::Field
62
- end
51
+ def sortable_model; Field end
52
+ def sortable_collection; ConstructorPages::Field end
63
53
 
64
54
  private
65
55
 
56
+ def set_field
57
+ @field = Field.find params[:id]
58
+ end
59
+
66
60
  def field_params
67
61
  params.require(:field).permit(
68
62
  :name,
@@ -1,95 +1,71 @@
1
- # encoding: utf-8
2
-
3
1
  module ConstructorPages
4
2
  class PagesController < ConstructorCore::ApplicationController
5
3
  include TheSortableTreeController::Rebuild
6
4
  include TheSortableTreeController::ExpandNode
7
5
 
8
- layout 'constructor_core/application_core', except: [:show]
6
+ skip_before_filter :authenticate_user!, only: [:show]
9
7
 
10
- before_filter -> {@pages = Page.all}, only: [:new, :edit]
8
+ before_action :set_page, only: [:edit, :update, :destroy]
11
9
 
12
10
  def index
13
- @pages = Page.nested_set.roots.includes(:template)
14
- @pages_cache = Digest::MD5.hexdigest(@pages.map{|p| [p.id, p.name, p.full_url, p.in_url, p.template.lft, p.lft, p.template_id]}.join)
15
- @template_exists = Template.count != 0
16
- flash[:notice] = 'Create at least one template' unless @template_exists
11
+ @pages = Page.roots
17
12
  end
18
13
 
19
14
  def new
20
- @page = Page.new
15
+ @page, @templates = Page.new, Template.all
16
+
17
+ if @templates.blank?
18
+ redirect_to pages_path, notice: t(:create_template_first)
19
+ end
21
20
  end
22
21
 
23
22
  def show
24
- _request = "/#{params[:all]}"
25
- @page = Page.find_by_request_or_first(_request)
26
- error_404 and return if @page.nil? or (!@page.published? and _request != '/')
23
+ @page = Page.find_by_path request.path
24
+
27
25
  redirect_to(@page.redirect) && return if @page.redirect?
26
+
28
27
  _code_name = @page.template.code_name
29
28
  instance_variable_set('@'+_code_name, @page)
30
29
 
31
- respond_to do |format|
32
- format.html { render "#{_code_name.pluralize}/show" rescue render "templates/#{_code_name}"}
33
- format.json { render "#{_code_name.pluralize}/show.json", layout: false rescue render json: @page }
34
- format.xml { render "#{_code_name.pluralize}/show.xml", layout: false rescue render xml: @page }
35
- end
30
+ render "templates/#{_code_name}", layout: 'application'
36
31
  end
37
32
 
38
33
  def edit
39
- @page = Page.find(params[:id])
40
- @parent_id, @template_id = @page.parent.try(:id), @page.template.id
41
- _code_name = @page.template.code_name.pluralize
42
- render "#{_code_name}/edit" rescue render :edit
43
34
  end
44
35
 
45
36
  def create
46
37
  @page = Page.new page_params
47
38
 
48
39
  if @page.save
49
- @page.touch_branch
50
40
  redirect_to pages_path, notice: t(:page_success_added, name: @page.name)
51
41
  else
52
- if @page.template_id
53
- _template = Template.find(@page.template_id)
54
- _code_name = _template.code_name.pluralize if _template
55
- render "#{_code_name}/new" rescue render :new
56
- else
57
- render :new
58
- end
42
+ render :new
59
43
  end
60
44
  end
61
45
 
62
46
  def update
63
- @page = Page.find params[:id]
64
-
65
- _template_changed = @page.template.id != params[:page][:template_id].to_i
66
-
67
- @page.remove_fields_values if _template_changed
68
-
69
47
  if @page.update page_params
70
- @page.create_fields_values if _template_changed
71
48
  @page.update_fields_values params[:fields]
72
- @page.touch_branch
73
49
 
74
50
  redirect_to pages_path, notice: t(:page_success_updated, name: @page.name)
75
51
  else
76
- render "#{@page.template.code_name.pluralize}/new" rescue render :edit
52
+ render :edit
77
53
  end
78
54
  end
79
55
 
80
56
  def destroy
81
- @page = Page.find(params[:id])
82
- @page.touch_branch
83
57
  @page.destroy
84
58
  redirect_to pages_path, notice: t(:page_success_removed, name: @page.name)
85
59
  end
86
60
 
87
- def sortable_model
88
- Page
89
- end
61
+ def sortable_model; Page end
90
62
 
91
63
  private
92
64
 
65
+ def set_page
66
+ @page = Page.find params[:id]
67
+ end
68
+
93
69
  def page_params
94
70
  params.require(:page).permit(
95
71
  :active,
@@ -99,7 +75,6 @@ module ConstructorPages
99
75
  :keywords,
100
76
  :description,
101
77
  :auto_url,
102
- :parent_id,
103
78
  :template_id,
104
79
  :in_nav,
105
80
  :in_map,
@@ -108,9 +83,5 @@ module ConstructorPages
108
83
  :redirect
109
84
  )
110
85
  end
111
-
112
- def error_404
113
- render file: "#{Rails.root}/public/404", layout: false, status: :not_found
114
- end
115
86
  end
116
87
  end
@@ -1,15 +1,12 @@
1
- # encoding: utf-8
2
-
3
1
  module ConstructorPages
4
2
  class TemplatesController < ConstructorCore::ApplicationController
5
3
  include TheSortableTreeController::Rebuild
6
4
  include TheSortableTreeController::ExpandNode
7
5
 
8
- before_filter -> {@templates = Template.all}, only: [:new, :edit, :update, :create]
6
+ before_action :set_template, only: [:edit, :update, :destroy]
9
7
 
10
8
  def index
11
9
  @templates = Template.roots
12
- @templates_cache = Digest::MD5.hexdigest(@templates.map{|t| [t.id, t.name, t.lft]}.join)
13
10
  end
14
11
 
15
12
  def new
@@ -17,7 +14,6 @@ module ConstructorPages
17
14
  end
18
15
 
19
16
  def edit
20
- @template = Template.find(params[:id])
21
17
  end
22
18
 
23
19
  def create
@@ -31,8 +27,6 @@ module ConstructorPages
31
27
  end
32
28
 
33
29
  def update
34
- @template = Template.find params[:id]
35
-
36
30
  if @template.update template_params
37
31
  redirect_to templates_url, notice: t(:template_success_updated, name: @template.name)
38
32
  else
@@ -41,28 +35,22 @@ module ConstructorPages
41
35
  end
42
36
 
43
37
  def destroy
44
- @template = Template.find(params[:id])
45
-
46
- if @template.pages.count == 0
47
- name = @template.name
48
- @template.destroy
49
- redirect_to templates_url, notice: t(:template_success_removed, name: name)
50
- else
51
- redirect_to :back, alert: t(:template_error_delete_pages)
52
- end
38
+ @template.destroy
39
+ redirect_to templates_url, notice: t(:template_success_removed, name: @template.name)
53
40
  end
54
41
 
55
- def sortable_model
56
- Template
57
- end
42
+ def sortable_model; Template end
58
43
 
59
44
  private
60
45
 
46
+ def set_template
47
+ @template = Template.find params[:id]
48
+ end
49
+
61
50
  def template_params
62
51
  params.require(:template).permit(
63
52
  :name,
64
53
  :code_name,
65
- :parent_id,
66
54
  :child_id
67
55
  )
68
56
  end
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module ConstructorPages
4
2
  module FieldsHelper
5
3
  def types_value
@@ -1,14 +1,7 @@
1
1
  module ConstructorPages
2
2
  module PagesHelper
3
- include ForSelect
4
-
5
- def templates
6
- Template.all.map{|t| ["#{'--'*t.level} #{t.name}", t.id]}
7
- end
8
-
9
- def image_tag_with_at2x(name_at_1x, options={})
10
- name_at_2x = name_at_1x.gsub(%r{\.\w+$}, '@2x\0')
11
- image_tag(name_at_1x, options.merge("data-at2x" => asset_path(name_at_2x)))
3
+ def templates_tree(templates)
4
+ templates.map{|t| ["#{'--'*t.level} #{t.name}", t.id]}
12
5
  end
13
6
  end
14
7
  end
@@ -1,15 +1,11 @@
1
- # encoding: utf-8
2
-
3
1
  module ConstructorPages
4
2
  # Field model. Fields allows to add custom fields for template.
5
3
  # Each field has type of value such as float, integer, string...
6
4
  class Field < ActiveRecord::Base
7
- # Adding code_name_uniqueness method
8
- include CodeNameUniq
9
-
10
5
  # Array of available field types
11
- TYPES = %w{string integer float boolean text date html image}.tap {|_t|
12
- _t.each {|t| class_eval %{has_many :#{t}_types, dependent: :destroy, class_name: 'Types::#{t.titleize}Type'}}}
6
+ TYPES = %w{string integer float boolean text date html image}
7
+
8
+ TYPES.each {|t| class_eval %{has_many :#{t}_types, class_name: 'Types::#{t.titleize}Type'} }
13
9
 
14
10
  validates_presence_of :name
15
11
  validates_uniqueness_of :code_name, scope: :template_id
@@ -47,6 +43,11 @@ module ConstructorPages
47
43
 
48
44
  private
49
45
 
46
+ # Check if code_name is not available
47
+ def code_name_uniqueness
48
+ errors.add(:base, :code_name_already_in_use) unless Page.check_code_name(code_name) and check_code_name(code_name)
49
+ end
50
+
50
51
  # Check if there is code_name in template branch
51
52
  def check_code_name(code_name)
52
53
  [code_name.pluralize, code_name.singularize].each {|name|
@@ -55,8 +56,21 @@ module ConstructorPages
55
56
  true
56
57
  end
57
58
 
58
- # Create and destroy page fields
59
- %w{create destroy_all}.each {|m| class_eval %{
60
- def #{m}_page_fields; template.pages.each {|page| type_class.#{m} page_id: page.id, field_id: id} end }}
59
+ def create_page_fields
60
+ template.page_ids.each_slice(500) do |batch|
61
+ _items = []
62
+ batch.each do |_id|
63
+ _items << type_class.new({page_id: _id, field_id: id})
64
+ end
65
+ type_class.import _items
66
+ end
67
+ end
68
+
69
+ def destroy_all_page_fields
70
+ template.page_ids.each_slice(1000) do |batch|
71
+ type_class.where(page_id: batch, field_id: id).delete_all
72
+ Page.update_all({updated_at: Time.now}, {id: batch})
73
+ end
74
+ end
61
75
  end
62
76
  end
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module ConstructorPages
4
2
  # Page model. Pages are core for company websites, blogs etc.
5
3
  class Page < ActiveRecord::Base
@@ -14,9 +12,12 @@ module ConstructorPages
14
12
  has_many :fields, through: :template
15
13
  belongs_to :template
16
14
 
15
+ scope :published, -> { where(active: true) }
16
+
17
17
  default_scope -> { order :lft }
18
18
 
19
19
  validate :templates_existing_check
20
+ validate :check_template_changing, on: :update
20
21
 
21
22
  before_save :friendly_url, :assign_template, :full_url_update
22
23
  after_update :descendants_update
@@ -25,10 +26,10 @@ module ConstructorPages
25
26
  acts_as_nested_set
26
27
 
27
28
  class << self
28
- # Used for find page by request. It return first page if no request given or request is home page
29
+ # Used for find page by request path. It return first page if no request given or request is home page
29
30
  # @param request for example <tt>'/conditioners/split-systems/zanussi'</tt>
30
- def find_by_request_or_first(request = nil)
31
- (request.nil? || request == '/') ? Page.first : Page.find_by(full_url: request)
31
+ def find_by_path(path)
32
+ path == '/' ? Page.published.first! : Page.published.find_by!(full_url: path)
32
33
  end
33
34
 
34
35
  # Generate full_url from parent id and url
@@ -129,12 +130,10 @@ module ConstructorPages
129
130
 
130
131
  # Update all fields values with given params.
131
132
  # @param params should looks like <tt>{price: 500, content: 'Hello'}</tt>
132
- # @param reset_booleans reset all boolean fields to false before assign params
133
- def update_fields_values(params, reset_booleans = true)
133
+ def update_fields_values(params)
134
134
  params || return
135
135
 
136
136
  fields.each {|f| f.find_or_create_type_object(self).tap {|t| t || next
137
- t.value = 0 if f.type_value == 'boolean' && reset_booleans
138
137
  params[f.code_name.to_sym].tap {|v| v && t.value = v}
139
138
  t.save }}
140
139
  end
@@ -184,11 +183,6 @@ module ConstructorPages
184
183
  # Check if link specified
185
184
  def redirect?; url != redirect && !redirect.empty? end
186
185
 
187
- # Touch all pages in same branch
188
- def touch_branch
189
- [ancestors, descendants].each {|p| p.map(&:touch)}
190
- end
191
-
192
186
  # When method missing it get/set field value or get page in branch
193
187
  #
194
188
  # Examples:
@@ -211,6 +205,9 @@ module ConstructorPages
211
205
  # Page is not valid if there is no template
212
206
  def templates_existing_check; errors.add_on_empty(:template_id) if Template.count == 0 end
213
207
 
208
+ # Page should not change template
209
+ def check_template_changing; errors.add(:base, :can_not_change_template) if template_id_changed? end
210
+
214
211
  # If template_id is nil then get first template
215
212
  def assign_template; self.template_id = Template.first.id unless template_id end
216
213