constructor-pages 1.0.0beta1 → 1.0.0beta2

Sign up to get free protection for your applications and to get access to all the features.
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