Skip to content

Commit

Permalink
Add the reverse has_many field feature (mainly based on pull request l…
Browse files Browse the repository at this point in the history
  • Loading branch information
did committed Aug 11, 2011
1 parent 333934c commit 67d7b13
Show file tree
Hide file tree
Showing 37 changed files with 411 additions and 48 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ gem 'carrierwave', '~> 0.5.5'
gem 'dragonfly', '~> 0.9.1'
gem 'rack-cache', :require => 'rack/cache'

gem 'custom_fields', '1.0.0.beta.21'
gem 'custom_fields', '1.0.0.beta.22'
gem 'cancan'
gem 'fog', '0.8.2'
gem 'mimetype-fu'
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ GEM
capybara (>= 1.0.0)
cucumber (~> 1.0.0)
nokogiri (>= 1.4.6)
custom_fields (1.0.0.beta.21)
custom_fields (1.0.0.beta.22)
activesupport (~> 3.0.9)
mongoid (= 2.0.2)
daemons (1.1.4)
Expand Down Expand Up @@ -296,7 +296,7 @@ DEPENDENCIES
carrierwave (~> 0.5.5)
cells
cucumber-rails (= 1.0.2)
custom_fields (= 1.0.0.beta.21)
custom_fields (= 1.0.0.beta.22)
database_cleaner
delayed_job (= 2.1.4)
delayed_job_mongoid (= 1.0.2)
Expand Down
2 changes: 1 addition & 1 deletion app/cells/admin/menu_cell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,4 @@ def localize_label(label)
I18n.t("admin.shared.menu.#{label}")
end

end
end
36 changes: 34 additions & 2 deletions app/controllers/admin/contents_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,26 @@ class ContentsController < BaseController

before_filter :authorize_content

helper_method :breadcrumb_root, :breadcrumb_url, :back_url

def index
@contents = @content_type.list_or_group_contents
end

def new
new! { @content.attributes = params[:content] }
end

def create
create! { edit_admin_content_url(@content_type.slug, @content.id) }
create! { after_create_or_update_url }
end

def edit
edit! { @content.attributes = params[:content] }
end

def update
update! { edit_admin_content_url(@content_type.slug, @content.id) }
update! { after_create_or_update_url }
end

def sort
Expand All @@ -43,9 +53,31 @@ def begin_of_association_chain
set_content_type
end

def after_create_or_update_url
if params[:breadcrumb_alias].blank?
edit_admin_content_url(@content_type.slug, @content.id)
else
self.breadcrumb_url
end
end

def authorize_content
authorize! params[:action].to_sym, ContentInstance
end

def breadcrumb_root
return nil if params[:breadcrumb_alias].blank?

@breadcrumb_root ||= resource.send(params[:breadcrumb_alias].to_sym)
end

def breadcrumb_url
edit_admin_content_url(self.breadcrumb_root._parent.slug, self.breadcrumb_root)
end

def back_url
self.breadcrumb_root ? self.breadcrumb_url : admin_contents_url(@content_type.slug)
end

end
end
62 changes: 59 additions & 3 deletions app/helpers/admin/custom_fields_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,30 @@ def options_for_association_target
end.compact
end

def options_for_reverse_lookups(my_content_type)
klass_name = my_content_type.content_klass.to_s

[].tap do |options|
ContentType.where(:'content_custom_fields.kind' => 'has_one', :'content_custom_fields.target' => klass_name).each do |content_type|
content_type.content_custom_fields.find_all { |f| f.has_one? && f.target == klass_name }.each do |field|
options << {
:klass => content_type.content_klass.to_s,
:label => field.label,
:name => field._name
}
end
end
end
end

def filter_options_for_reverse_has_many(contents, reverse_lookup, object)
# Only display items which don't belong to a different object
contents.reject do |c|
owner = c.send(reverse_lookup.to_sym)
!(owner.nil? || owner == object._id)
end
end

def options_for_has_one(field, value)
self.options_for_has_one_or_has_many(field) do |groups|
grouped_options_for_select(groups.collect do |g|
Expand All @@ -57,16 +81,20 @@ def options_for_has_one(field, value)
end
end

def options_for_has_many(field)
self.options_for_has_one_or_has_many(field)
def options_for_has_many(field, content = nil)
self.options_for_has_one_or_has_many(field, content)
end

def options_for_has_one_or_has_many(field, &block)
def options_for_has_one_or_has_many(field, content = nil, &block)
content_type = field.target.constantize._parent

if content_type.groupable?
grouped_contents = content_type.list_or_group_contents

grouped_contents.each do |g|
g[:items] = filter_options_for_reverse_has_many(g[:items], field.reverse_lookup, content)
end if field.reverse_has_many?

if block_given?
block.call(grouped_contents)
else
Expand All @@ -80,8 +108,36 @@ def options_for_has_one_or_has_many(field, &block)
end
else
contents = content_type.ordered_contents

if field.reverse_has_many?
contents = filter_options_for_reverse_has_many(contents, field.reverse_lookup, content)
end

contents.collect { |c| [c._label, c._id] }
end
end

def has_many_data_to_js(field, content)
options = {
:taken_ids => content.send(field._alias.to_sym).ids
}

if !content.new_record? && field.reverse_has_many?
url_options = {
:breadcrumb_alias => field.reverse_lookup_alias,
"content[#{field.reverse_lookup_alias}]" => content._id
}

options.merge!(
:new_item => {
:label => t('admin.contents.form.has_many.new_item'),
:url => new_admin_content_url(field.target_klass._parent.slug, url_options)
},
:edit_item_url => edit_admin_content_url(field.target_klass._parent.slug, 42, url_options)
)
end

collection_to_js(options_for_has_many(field, content), options)
end

end
1 change: 0 additions & 1 deletion app/models/site.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ class Site
## Extensions ##
extend Extensions::Site::SubdomainDomains
extend Extensions::Site::FirstInstallation
extend Extensions::Site::FirstInstallation
include Extensions::Shared::Seo

## fields ##
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/content_types/edit.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@

= render 'admin/shared/form_actions', :back_url => admin_contents_url(@content_type.slug_was), :button_label => :update

= render 'admin/custom_fields/edit_field'
= render 'admin/custom_fields/edit_field', :content_type => @content_type
4 changes: 2 additions & 2 deletions app/views/admin/content_types/new.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

- content_for :submenu do
= render 'admin/shared/menu/contents'

- content_for :actions do
= render 'admin/shared/actions/contents'

Expand All @@ -14,4 +14,4 @@

= render 'admin/shared/form_actions', :back_url => admin_pages_url, :button_label => :create

= render 'admin/custom_fields/edit_field'
= render 'admin/custom_fields/edit_field', :content_type => @content_type
7 changes: 5 additions & 2 deletions app/views/admin/contents/edit.html.haml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
- title t('.title', :type => @content_type.name.capitalize)
- if breadcrumb_root
- title t('.title.breadcrumb', :root => link_to(breadcrumb_root._label, breadcrumb_url), :type => @content_type.name.capitalize)
- else
- title t('.title.default', :type => @content_type.name.capitalize)

- content_for :submenu do
= render 'admin/shared/menu/contents'
Expand All @@ -18,4 +21,4 @@

= render 'form', :f => form

= render 'admin/shared/form_actions', :back_url => admin_contents_url(@content_type.slug), :button_label => :update
= render 'admin/shared/form_actions', :back_url => back_url, :button_label => :update
9 changes: 6 additions & 3 deletions app/views/admin/contents/new.html.haml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
- title t('.title', :type => @content_type.name.capitalize)
- if breadcrumb_root
- title t('.title.breadcrumb', :root => link_to(breadcrumb_root._label, breadcrumb_url), :type => @content_type.name.capitalize)
- else
- title t('.title.default', :type => @content_type.name.capitalize)

- content_for :submenu do
= render 'admin/shared/menu/contents'

- content_for :actions do
= render 'admin/shared/actions/contents'

Expand All @@ -16,4 +19,4 @@

= render 'form', :f => form

= render 'admin/shared/form_actions', :back_url => admin_contents_url(@content_type.slug), :button_label => :create
= render 'admin/shared/form_actions', :back_url => back_url, :button_label => :create
6 changes: 5 additions & 1 deletion app/views/admin/custom_fields/_edit_field.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
= g.input :hint
= g.input :text_formatting, :as => 'select', :collection => options_for_text_formatting, :include_blank => false, :wrapper_html => { :style => 'display: none' }
= g.input :target, :as => 'select', :collection => options_for_association_target, :include_blank => false, :wrapper_html => { :style => 'display: none' }
= g.input :reverse_lookup, :as => 'select', :collection => [], :include_blank => true, :wrapper_html => { :style => 'display: none' }

.popup-actions
%p
%button.button.light{ :type => 'submit' }
%span= t('admin.shared.form_actions.update')
%span= t('admin.shared.form_actions.update')

%script{ :type => 'text/javascript', :name => 'reverse_lookups' }
!= collection_to_js(options_for_reverse_lookups(content_type))
2 changes: 2 additions & 0 deletions app/views/admin/custom_fields/_index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

%input{ :name => '{{base_name}}[target]', :value => '{{{target}}}', :type => 'hidden', :'data-field' => 'target' }

%input{ :name => '{{base_name}}[reverse_lookup]', :value => '{{{reverse_lookup}}}', :type => 'hidden', :'data-field' => 'reverse_lookup' }

%input{ :name => '{{base_name}}[label]', :value => '{{{label}}}', :type => 'text', :'data-field' => 'label' }

&mdash;
Expand Down
4 changes: 3 additions & 1 deletion app/views/admin/custom_fields/types/_has_many.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@
{{/if_template}}

%span.actions
- if field.reverse_lookup?
= link_to image_tag('admin/form/pen.png'), '#', :class => 'edit first'
= link_to image_tag('admin/form/icons/trash.png'), '#', :class => 'remove'
%button{ :class => 'button light mini add', :type => 'button' }
%span!= t('admin.buttons.new_item')

%script{ :type => 'text/javascript', :name => 'data' }
!= collection_to_js(options_for_has_many(field), :taken_ids => form.object.send(field._alias.to_sym).ids)
!= has_many_data_to_js(field, form.object)
12 changes: 10 additions & 2 deletions app/views/admin/custom_fields/types/_has_one.html.haml
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
- field.target.constantize.reload_parent! # to make sure all the contents from the parent are loaded

- selected_id = form.object.send(field._alias.to_sym).try(:_id)
- if breadcrumb_root && params[:breadcrumb_alias] == field._alias

= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :input_html => { :class => 'has_one' }, :as => :select, :collection => options_for_has_one(field, selected_id), :selected => selected_id, :required => required
= form.hidden_field field._name.to_sym

= hidden_field_tag 'breadcrumb_alias', field._alias

- else

- selected_id = form.object.send(field._alias.to_sym).try(:_id)

= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :input_html => { :class => 'has_one' }, :as => :select, :collection => options_for_has_one(field, selected_id), :selected => selected_id, :required => required

12 changes: 9 additions & 3 deletions config/locales/admin_ui.de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ de:
asc: Aufsteigend
desc: Absteigend


contents:
index:
title: '"%{type}" anzeigen'
Expand All @@ -251,9 +250,16 @@ de:
list:
no_items: "Momentan gibt es keine Elemente. Klicke einfach <a href='%{url}'>hier</a>, um das erste Element zu erstellen."
new:
title: '%{type} &mdash; neues Element'
title:
default: '%{type} &mdash; neues Element'
breadcrumb: '%{root} &raquo; %{type} &mdash; Element bearbeiten'
edit:
title: '%{type} &mdash; Element bearbeiten'
title:
default: '%{type} &mdash; editing item'
breadcrumb: '%{root} &raquo; %{type} &mdash; Element bearbeiten'
form:
has_many:
new_item: Neues Element

image_picker:
link: Füge ein Bild in den Code ein
Expand Down
13 changes: 11 additions & 2 deletions config/locales/admin_ui.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ en:
edit_categories: Edit options
file:
delete_file: Delete file
has_many:
empty: Empty
index:
is_required: is required
default_label: Field name
Expand Down Expand Up @@ -246,9 +248,16 @@ en:
list:
no_items: "There are no items for now. Just click <a href=\"%{url}\">here</a> to create the first one."
new:
title: '%{type} &mdash; new item'
title:
default: '%{type} &mdash; new item'
breadcrumb: '%{root} &raquo; %{type} &mdash; new item'
edit:
title: '%{type} &mdash; editing item'
title:
default: '%{type} &mdash; editing item'
breadcrumb: '%{root} &raquo; %{type} &mdash; editing item'
form:
has_many:
new_item: New item

image_picker:
link: Insert an image into the code
Expand Down
11 changes: 9 additions & 2 deletions config/locales/admin_ui.es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,16 @@ es:
list:
no_items: "No hay ningún elemento. Haga click <a href=\"%{url}\">aquí</a> para crear el primero."
new:
title: '%{type} &mdash; nuevo elemento'
title:
default: '%{type} &mdash; nuevo elemento'
breadcrumb: '%{root} &raquo; %{type} &mdash; nuevo elemento'
edit:
title: '%{type} &mdash; editando elemento'
title:
default: '%{type} &mdash; editando elemento'
breadcrumb: '%{root} &raquo; %{type} &mdash; editando elemento'
form:
has_many:
new_item: Nuevo elemento

image_picker:
link: Insertar una imagen el el código
Expand Down
Loading

0 comments on commit 67d7b13

Please sign in to comment.