aa_associations 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +53 -0
- data/Gemfile +10 -0
- data/MIT_LICENSE.txt +20 -0
- data/README.md +213 -0
- data/Rakefile +17 -0
- data/aa_associations.gemspec +31 -0
- data/app/controllers/autocomplete_controller.rb +37 -0
- data/app/helpers/active_admin_associations_helper.rb +77 -0
- data/app/views/admin/shared/_add_to_association.html.erb +21 -0
- data/app/views/admin/shared/_association_collection_table_actions.html.erb +4 -0
- data/app/views/admin/shared/_blank_slate.html.erb +3 -0
- data/app/views/admin/shared/_collection_table.html.erb +58 -0
- data/app/views/admin/shared/_form.html.erb +7 -0
- data/config/routes.rb +7 -0
- data/lib/aa_associations.rb +20 -0
- data/lib/active_admin_associations/active_admin_extensions.rb +13 -0
- data/lib/active_admin_associations/association_actions.rb +43 -0
- data/lib/active_admin_associations/association_config.rb +50 -0
- data/lib/active_admin_associations/autocompleter.rb +64 -0
- data/lib/active_admin_associations/engine.rb +25 -0
- data/lib/active_admin_associations/form_config_dsl.rb +15 -0
- data/lib/active_admin_associations/redirect_destroy_actions.rb +7 -0
- data/lib/active_admin_associations/version.rb +3 -0
- data/lib/formtastic/inputs/token_input.rb +43 -0
- data/lib/formtastic/token_input_default_for_association.rb +19 -0
- data/test/active_admin_associations_test.rb +69 -0
- data/test/admin_posts_controller_test.rb +52 -0
- data/test/association_config_test.rb +43 -0
- data/test/autocomplete_controller_test.rb +27 -0
- data/test/autocompleter_test.rb +62 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/admin/dashboards.rb +44 -0
- data/test/dummy/app/admin/posts.rb +20 -0
- data/test/dummy/app/admin/tags.rb +11 -0
- data/test/dummy/app/assets/javascripts/active_admin.js +8 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/active_admin.css.scss +6 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.gitkeep +0 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/models/admin_user.rb +10 -0
- data/test/dummy/app/models/post.rb +11 -0
- data/test/dummy/app/models/tag.rb +15 -0
- data/test/dummy/app/models/tagging.rb +7 -0
- data/test/dummy/app/models/user.rb +8 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +63 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +19 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/active_admin.rb +129 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/devise.rb +216 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/devise.en.yml +57 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +62 -0
- data/test/dummy/db/.gitignore +1 -0
- data/test/dummy/db/migrate/20120504220404_devise_create_admin_users.rb +52 -0
- data/test/dummy/db/migrate/20120504221534_create_posts.rb +12 -0
- data/test/dummy/db/migrate/20120504221936_create_users.rb +9 -0
- data/test/dummy/db/migrate/20120504222040_create_tags.rb +8 -0
- data/test/dummy/db/migrate/20120504222247_create_taggings.rb +10 -0
- data/test/dummy/db/schema.rb +65 -0
- data/test/dummy/lib/assets/.gitkeep +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/test/factories/admin_users.rb +9 -0
- data/test/dummy/test/factories/posts.rb +11 -0
- data/test/dummy/test/factories/taggings.rb +6 -0
- data/test/dummy/test/factories/tags.rb +7 -0
- data/test/dummy/test/factories/users.rb +8 -0
- data/test/dummy/test/unit/admin_user_test.rb +7 -0
- data/test/dummy/test/unit/post_test.rb +7 -0
- data/test/dummy/test/unit/tag_test.rb +7 -0
- data/test/dummy/test/unit/tagging_test.rb +7 -0
- data/test/dummy/test/unit/user_test.rb +7 -0
- data/test/support/should_change.rb +29 -0
- data/test/test_helper.rb +51 -0
- data/vendor/assets/javascripts/active_admin_associations.js +14 -0
- data/vendor/assets/javascripts/jquery.tokeninput.js +915 -0
- data/vendor/assets/stylesheets/active_admin_associations.css.scss +18 -0
- data/vendor/assets/stylesheets/token-input-facebook.css +121 -0
- metadata +362 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
<%- if resource_administrated?(relationship_class) && relationship_class.respond_to?(:autocomplete_attribute) && relationship_class.autocomplete_attribute.present? -%>
|
2
|
+
<%= form_tag relate_to_url(object), :class => 'relate-to-form', :method => :put do %>
|
3
|
+
<fieldset class="inputs">
|
4
|
+
<h4>Add a <%= relationship_class.model_name.human %></h4>
|
5
|
+
<%= hidden_field_tag 'relationship_name', relationship %>
|
6
|
+
<ol>
|
7
|
+
<li class="label">
|
8
|
+
<label for="related_id">
|
9
|
+
<%= relationship_class.model_name.human %>
|
10
|
+
<%= relationship_class.human_attribute_name(relationship_class.autocomplete_attribute) %>
|
11
|
+
</label>
|
12
|
+
</li>
|
13
|
+
<li class="input">
|
14
|
+
<%= hidden_field_tag 'related_id', nil, :class => 'token-input',
|
15
|
+
'data-model-name' => relationship_class.model_name.singular %>
|
16
|
+
</li>
|
17
|
+
<li class="button"><%= submit_tag "Add #{relationship_class.model_name.human}" %></li>
|
18
|
+
</ol>
|
19
|
+
</fieldset>
|
20
|
+
<% end %>
|
21
|
+
<%- end -%>
|
@@ -0,0 +1,58 @@
|
|
1
|
+
<div class="relationship-table" id="relationship-table-<%= relationship %>">
|
2
|
+
<h3><%= object.class.human_attribute_name(relationship) %></h3>
|
3
|
+
<%= render :partial => 'admin/shared/add_to_association', :locals => {
|
4
|
+
:relationship_class => relationship_class,
|
5
|
+
:object => object,
|
6
|
+
:relationship => relationship
|
7
|
+
} %>
|
8
|
+
<%- if collection.present? -%>
|
9
|
+
<table class="index_table">
|
10
|
+
<thead>
|
11
|
+
<tr>
|
12
|
+
<th>ID</th>
|
13
|
+
<% columns.each do |column| %>
|
14
|
+
<th><%= relationship_class.human_attribute_name(column) %></th>
|
15
|
+
<%- end -%>
|
16
|
+
<th> </th>
|
17
|
+
</tr>
|
18
|
+
</thead>
|
19
|
+
<tbody>
|
20
|
+
<%- collection.each do |record| -%>
|
21
|
+
<tr class="<%= cycle("odd", "even") -%>">
|
22
|
+
<td><%= record.id %></td>
|
23
|
+
<%- columns.each do |column| -%>
|
24
|
+
<%- if record.send(column).is_a?(ActiveRecord::Base) -%>
|
25
|
+
<td><%= display_name_for(record.send(column)) %></td>
|
26
|
+
<%- else -%>
|
27
|
+
<td><%= record.send(column) %></td>
|
28
|
+
<%- end -%>
|
29
|
+
<%- end -%>
|
30
|
+
<td class="actions">
|
31
|
+
<%- if resource_administrated?(record.class) -%>
|
32
|
+
<%= render :partial => 'admin/shared/association_collection_table_actions', :locals => {
|
33
|
+
:record => record,
|
34
|
+
:object => object,
|
35
|
+
:relationship => relationship
|
36
|
+
} %>
|
37
|
+
<%- else -%>
|
38
|
+
|
39
|
+
<%- end -%>
|
40
|
+
</td>
|
41
|
+
</tr>
|
42
|
+
<%- end -%>
|
43
|
+
</tbody>
|
44
|
+
</table>
|
45
|
+
<div class="resource-table-footer">
|
46
|
+
<%= paginate collection, :remote => true, :params => {
|
47
|
+
:action => 'page_related', :relationship_name => relationship
|
48
|
+
} %>
|
49
|
+
<div class="pagination_information">
|
50
|
+
<%= raw page_entries_info(collection) %>
|
51
|
+
</div>
|
52
|
+
</div>
|
53
|
+
<%- else -%>
|
54
|
+
<%= render :partial => 'admin/shared/blank_slate', :locals => {
|
55
|
+
:blank_text => "There are no #{object.class.human_attribute_name(relationship)}"
|
56
|
+
} %>
|
57
|
+
<%- end -%>
|
58
|
+
</div>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<%= admin_form_for resource %>
|
2
|
+
|
3
|
+
<%- if resource.persisted? && active_admin_config.form_associations.present? -%>
|
4
|
+
<%- active_admin_config.form_associations.each do |association| -%>
|
5
|
+
<%= collection_relationship_manager(resource, association) %>
|
6
|
+
<%- end -%>
|
7
|
+
<%- end -%>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
if Rails.application.config.aa_associations.autocomplete_models
|
2
|
+
models = Rails.application.config.aa_associations.autocomplete_models.join('|')
|
3
|
+
Rails.application.routes.draw do
|
4
|
+
match '/autocomplete/:model' => 'autocomplete#index', :model => /(#{models})/,
|
5
|
+
:defaults => { :format => 'json' }
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'activeadmin'
|
3
|
+
require 'active_admin_associations/version'
|
4
|
+
require 'active_admin_associations/active_admin_extensions'
|
5
|
+
require 'formtastic/token_input_default_for_association'
|
6
|
+
require 'formtastic/inputs/token_input'
|
7
|
+
|
8
|
+
module ActiveAdminAssociations
|
9
|
+
extend ActiveSupport::Autoload
|
10
|
+
|
11
|
+
eager_autoload do
|
12
|
+
autoload :AssociationActions
|
13
|
+
autoload :FormConfigDSL
|
14
|
+
autoload :RedirectDestroyActions
|
15
|
+
autoload :Autocompleter
|
16
|
+
autoload :AssociationConfig
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'active_admin_associations/engine'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActiveAdmin
|
2
|
+
class Resource
|
3
|
+
attr_accessor :form_columns
|
4
|
+
attr_accessor :form_associations
|
5
|
+
attr_accessor :active_association_form
|
6
|
+
end
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def resources
|
10
|
+
application.namespaces.values.map{|n| n.resources.resources }.flatten.compact.map(&:resource_class)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ActiveAdminAssociations
|
2
|
+
module AssociationActions
|
3
|
+
def association_actions
|
4
|
+
member_action :unrelate, :method => :put do
|
5
|
+
reflection = resource_class.reflect_on_association(params[:relationship_name].to_sym)
|
6
|
+
if reflection.collection?
|
7
|
+
related_record = reflection.klass.find(params[:related_id])
|
8
|
+
resource.send(params[:relationship_name]).delete(related_record)
|
9
|
+
else
|
10
|
+
resource.update_attribute("#{params[:relationship_name]}_id", nil)
|
11
|
+
end
|
12
|
+
flash[:notice] = "The recored has been unrelated."
|
13
|
+
redirect_to request.headers["Referer"].presence || admin_dashboard_url
|
14
|
+
end
|
15
|
+
|
16
|
+
member_action :relate, :method => :put do
|
17
|
+
reflection = resource_class.reflect_on_association(params[:relationship_name].to_sym)
|
18
|
+
if reflection.collection?
|
19
|
+
record_to_relate = reflection.klass.find(params[:related_id])
|
20
|
+
resource.send(params[:relationship_name]) << record_to_relate
|
21
|
+
else
|
22
|
+
resource.update_attribute("#{params[:relationship_name]}_id", record_to_relate)
|
23
|
+
end
|
24
|
+
flash[:notice] = "The recored has been related."
|
25
|
+
redirect_to request.headers["Referer"].presence || admin_dashboard_url
|
26
|
+
end
|
27
|
+
|
28
|
+
member_action :page_related, :method => :get do
|
29
|
+
relationship_name = params[:relationship_name].to_sym
|
30
|
+
association_config = active_admin_config.form_associations[relationship_name]
|
31
|
+
relationship_class = resource_class.reflect_on_association(relationship_name).klass
|
32
|
+
association_columns = association_config.fields.presence || relationship_class.content_columns
|
33
|
+
render :partial => 'admin/shared/collection_table', :locals => {
|
34
|
+
:object => resource,
|
35
|
+
:collection => resource.send(relationship_name).page(params[:page]),
|
36
|
+
:relationship => relationship_name,
|
37
|
+
:columns => association_columns,
|
38
|
+
:relationship_class => relationship_class
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ActiveAdminAssociations
|
2
|
+
class AssociationConfig
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
class Association
|
6
|
+
attr_reader :name
|
7
|
+
attr_reader :fields
|
8
|
+
|
9
|
+
def initialize(name, fields = [], &block)
|
10
|
+
@name = name.to_sym
|
11
|
+
@fields = fields
|
12
|
+
instance_exec(&block) if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
def field(name)
|
16
|
+
@fields << name
|
17
|
+
end
|
18
|
+
|
19
|
+
def fields(*names)
|
20
|
+
@fields += names
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :association_configs
|
25
|
+
delegate :each, :to => :association_configs
|
26
|
+
|
27
|
+
def initialize(&block)
|
28
|
+
@association_configs = []
|
29
|
+
instance_exec(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def blank?
|
33
|
+
@association_configs.blank?
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](association_name)
|
37
|
+
@association_configs.detect {|a| a.name == association_name.to_sym }
|
38
|
+
end
|
39
|
+
|
40
|
+
def association(name, fields = [], &block)
|
41
|
+
@association_configs << Association.new(name, fields, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
def associations(*names)
|
45
|
+
names.each do |name|
|
46
|
+
@association_configs << Association.new(name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module ActiveAdminAssociations
|
2
|
+
module Autocompleter
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def autocomplete(attribute, options = {})
|
7
|
+
class_attribute :autocomplete_attribute
|
8
|
+
class_attribute :autocomplete_options
|
9
|
+
|
10
|
+
self.autocomplete_attribute = attribute
|
11
|
+
self.autocomplete_options = options
|
12
|
+
|
13
|
+
extend AutocompleteMethods
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module AutocompleteMethods
|
18
|
+
def autocomplete_results(query)
|
19
|
+
results = where("LOWER(#{table_name}.#{autocomplete_attribute}) LIKE ?", "#{query.downcase}%").
|
20
|
+
order("#{table_name}.#{autocomplete_attribute} ASC")
|
21
|
+
results.map do |record|
|
22
|
+
_autocomplete_format_result(record)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def _autocomplete_format_result(record)
|
29
|
+
if configured_autocomplete_result_formatter?
|
30
|
+
aa_associations_config.autocomplete_result_formatter.call(record,
|
31
|
+
autocomplete_attribute, autocomplete_options)
|
32
|
+
else
|
33
|
+
label = _format_autocomplete_label(record)
|
34
|
+
{"label" => label, # This plays nice with both jQuery UI autocomplete and jquery.tokeninput
|
35
|
+
"value" => record.send(autocomplete_attribute),
|
36
|
+
"id" => record.id}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def _format_autocomplete_label(record)
|
41
|
+
if autocomplete_options[:format_label].present?
|
42
|
+
if autocomplete_options[:format_label].is_a?(Symbol)
|
43
|
+
record.send(autocomplete_options[:format_label])
|
44
|
+
elsif autocomplete_options[:format_label].respond_to?(:call)
|
45
|
+
autocomplete_options[:format_label].call(record)
|
46
|
+
else
|
47
|
+
record.send(autocomplete_attribute)
|
48
|
+
end
|
49
|
+
else
|
50
|
+
record.send(autocomplete_attribute)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def configured_autocomplete_result_formatter?
|
55
|
+
aa_associations_config.autocomplete_result_formatter.present? &&
|
56
|
+
aa_associations_config.autocomplete_result_formatter.respond_to?(:call)
|
57
|
+
end
|
58
|
+
|
59
|
+
def aa_associations_config
|
60
|
+
Rails.application.config.aa_associations
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActiveAdminAssociations
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
config.aa_associations = ActiveSupport::OrderedOptions.new
|
4
|
+
|
5
|
+
initializer "active_admin_associations.load_extensions" do |app|
|
6
|
+
ActiveAdmin::BaseController.helper ActiveAdminAssociationsHelper
|
7
|
+
ActiveAdmin::ResourceDSL.send(:include, ActiveAdminAssociations::AssociationActions)
|
8
|
+
ActiveAdmin::ResourceDSL.send(:include, ActiveAdminAssociations::FormConfigDSL)
|
9
|
+
|
10
|
+
unless app.config.aa_associations.destroy_redirect == false
|
11
|
+
ActiveAdmin::BaseController.send(:include, ActiveAdminAssociations::RedirectDestroyActions)
|
12
|
+
end
|
13
|
+
|
14
|
+
unless app.config.aa_associations.autocomplete == false
|
15
|
+
ActiveSupport.on_load(:active_record) do
|
16
|
+
ActiveRecord::Base.send(:include, ActiveAdminAssociations::Autocompleter)
|
17
|
+
end
|
18
|
+
|
19
|
+
Formtastic::Helpers::InputHelper.send(:include, Formtastic::TokenInputDefaultForAssociation)
|
20
|
+
end
|
21
|
+
|
22
|
+
ActiveAdmin.application.register_stylesheet 'active_admin_associations'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActiveAdminAssociations
|
2
|
+
module FormConfigDSL
|
3
|
+
def active_association_form(&block)
|
4
|
+
config.active_association_form = block
|
5
|
+
end
|
6
|
+
|
7
|
+
def form_columns(*column_names)
|
8
|
+
config.form_columns = column_names.flatten
|
9
|
+
end
|
10
|
+
|
11
|
+
def form_associations(&block)
|
12
|
+
config.form_associations = AssociationConfig.new(&block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Formtastic
|
2
|
+
module Inputs
|
3
|
+
class TokenInput
|
4
|
+
include Base
|
5
|
+
|
6
|
+
def to_html
|
7
|
+
input_wrapping do
|
8
|
+
label_html <<
|
9
|
+
builder.hidden_field(input_name, input_html_options)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def input_html_options
|
14
|
+
super.merge({
|
15
|
+
:required => nil,
|
16
|
+
:autofocus => nil,
|
17
|
+
:class => 'token-input',
|
18
|
+
'data-model-name' => reflection.klass.model_name.singular
|
19
|
+
}).tap do |html_options|
|
20
|
+
if record.present?
|
21
|
+
html_options["data-pre"] = prepopulated_value.to_json
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def prepopulated_value
|
27
|
+
[{"value" => name_value, "id" => record.id}]
|
28
|
+
end
|
29
|
+
|
30
|
+
def name_method
|
31
|
+
builder.collection_label_methods.find { |m| record.respond_to?(m) }
|
32
|
+
end
|
33
|
+
|
34
|
+
def name_value
|
35
|
+
record.send(name_method)
|
36
|
+
end
|
37
|
+
|
38
|
+
def record
|
39
|
+
@object.send(method)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Formtastic
|
2
|
+
module TokenInputDefaultForAssociation
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
alias_method_chain :default_input_type, :token_default_for_association
|
7
|
+
end
|
8
|
+
|
9
|
+
def default_input_type_with_token_default_for_association(method, options = {})
|
10
|
+
if @object
|
11
|
+
reflection = reflection_for(method)
|
12
|
+
if reflection && reflection.klass.respond_to?(:autocomplete_attribute) && reflection.macro == :belongs_to
|
13
|
+
return :token
|
14
|
+
end
|
15
|
+
end
|
16
|
+
default_input_type_without_token_default_for_association(method, options)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ActiveAdminAssociationsTest < ActionDispatch::IntegrationTest
|
4
|
+
setup do
|
5
|
+
admin_login_as
|
6
|
+
@post = Factory(:post)
|
7
|
+
@tag = Factory(:tag)
|
8
|
+
@post.tags = [@tag]
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'editing a post' do
|
12
|
+
setup do
|
13
|
+
visit "/admin/posts/#{@post.id}/edit"
|
14
|
+
end
|
15
|
+
|
16
|
+
should 'have correct inputs from form_columns config' do
|
17
|
+
assert page.has_selector?('form.post fieldset.inputs input#post_title'), 'no input for Post title'
|
18
|
+
assert page.has_selector?('form.post fieldset.inputs textarea#post_body'), 'no input for Post body'
|
19
|
+
assert page.has_selector?('form.post fieldset.inputs input#post_creator_id'), 'no input for Post creator'
|
20
|
+
end
|
21
|
+
|
22
|
+
should 'have correct inputs from active_association_form config' do
|
23
|
+
assert page.has_selector?('form.post fieldset#more-inputs input.my-date-picker#post_published_at'), 'no input for Post published_at'
|
24
|
+
assert page.has_selector?('form.post fieldset#more-inputs input#post_featured'), 'no input for Post featured'
|
25
|
+
end
|
26
|
+
|
27
|
+
should 'have correct token input for post creator' do
|
28
|
+
token_input = page.find('form.post fieldset.inputs input.token-input#post_creator_id')
|
29
|
+
assert_equal 'hidden', token_input["type"]
|
30
|
+
assert_equal 'user', token_input['data-model-name']
|
31
|
+
assert_equal '1', token_input['value']
|
32
|
+
assert_equal [{"value" => "Bill Tester", "id" => @post.creator_id}], MultiJson.decode(token_input['data-pre'])
|
33
|
+
end
|
34
|
+
|
35
|
+
should 'have a form to relate new tags' do
|
36
|
+
assert page.has_selector?('.relationship-table#relationship-table-tags form.relate-to-form')
|
37
|
+
assert page.has_selector?('#relationship-table-tags form.relate-to-form input[type="hidden"]#relationship_name')
|
38
|
+
assert_equal 'tags', page.find('#relationship-table-tags form.relate-to-form input#relationship_name')['value']
|
39
|
+
token_input = page.find('#relationship-table-tags form.relate-to-form input.token-input#related_id')
|
40
|
+
assert_equal 'tag', token_input['data-model-name']
|
41
|
+
end
|
42
|
+
|
43
|
+
should 'have a table of the related tags' do
|
44
|
+
assert page.has_xpath?('//div[@id="relationship-table-tags"]//table[@class="index_table"]/thead//th[text()="Name"]')
|
45
|
+
assert_equal @tag.name, page.find(:xpath, "//div[@id='relationship-table-tags']//table[@class='index_table']/tbody//tr[td[1][text()=#{@tag.id}]]//td[2]").text
|
46
|
+
edit_link = page.find(:xpath, "//div[@id='relationship-table-tags']//table[@class='index_table']/tbody//tr/td[3]/a[text()='Edit']")
|
47
|
+
assert_match %r{\A/admin/tags/\d+/edit}, edit_link['href']
|
48
|
+
|
49
|
+
assert page.has_xpath?("//div[@id='relationship-table-tags']//table[@class='index_table']/tbody//tr/td[3]/form//input[@type='submit'][@value='Unrelate']")
|
50
|
+
unrelate_form = page.find(:xpath, "//div[@id='relationship-table-tags']//table[@class='index_table']/tbody//tr/td[3]/form[@class='button_to']")
|
51
|
+
unrelate_url = unrelate_form['action']
|
52
|
+
assert_match %r{\A/admin/posts/#{@post.id}/unrelate}, unrelate_url
|
53
|
+
query_params = unrelate_url.split('?')[1].split('&')
|
54
|
+
assert_same_elements ["related_id=#{@tag.id}", 'relationship_name=tags'], query_params
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'editing a tag' do
|
59
|
+
setup do
|
60
|
+
visit "/admin/tags/#{@tag.id}/edit"
|
61
|
+
end
|
62
|
+
|
63
|
+
should 'have a table of the related posts' do
|
64
|
+
assert page.has_xpath?('//div[@id="relationship-table-posts"]//table[@class="index_table"]/thead//th[text()="Title"]')
|
65
|
+
assert_equal @post.title, page.find(:xpath, "//div[@id='relationship-table-posts']//table[@class='index_table']/tbody//tr[td[1][text()=#{@post.id}]]//td[2]").text
|
66
|
+
assert_equal @post.creator.name, page.find(:xpath, "//div[@id='relationship-table-posts']//table[@class='index_table']/tbody//tr[td[1][text()=#{@post.id}]]//td[3]").text
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|