puffer 0.0.23 → 0.0.24

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/.rspec +1 -0
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +55 -53
  4. data/VERSION +1 -1
  5. data/app/assets/javascripts/puffer/application.js +6 -3
  6. data/app/assets/javascripts/puffer/paginator.js +223 -0
  7. data/app/assets/javascripts/puffer/puffer.js +12 -0
  8. data/app/assets/javascripts/puffer/rails.js +1 -0
  9. data/app/assets/javascripts/puffer/{right-autocompleter.js → right-autocompleter-src.js} +45 -41
  10. data/app/assets/javascripts/puffer/{right-calendar.js → right-calendar-src.js} +53 -50
  11. data/app/assets/javascripts/puffer/right-dialog-src.js +768 -0
  12. data/app/assets/javascripts/puffer/right-slider-src.js +507 -0
  13. data/app/assets/javascripts/puffer/{right.js → right-src.js} +1000 -230
  14. data/app/assets/stylesheets/puffer/application.css +2 -0
  15. data/app/assets/stylesheets/puffer/paginator.css +33 -0
  16. data/app/assets/stylesheets/puffer/right.css +4 -0
  17. data/app/components/base/form.html.erb +15 -0
  18. data/app/components/base_component.rb +15 -0
  19. data/app/components/boolean/form.html.erb +3 -0
  20. data/app/components/boolean/index.html.erb +3 -0
  21. data/app/components/boolean_component.rb +13 -0
  22. data/app/components/date_time/form.html.erb +5 -0
  23. data/app/components/date_time_component.rb +12 -0
  24. data/app/components/file/form.html.erb +5 -0
  25. data/app/components/file_component.rb +3 -0
  26. data/app/components/hidden/form.html.erb +1 -0
  27. data/app/components/hidden_component.rb +3 -0
  28. data/app/components/password/form.html.erb +5 -0
  29. data/app/components/password_component.rb +7 -0
  30. data/app/components/references_many/form.html.erb +1 -0
  31. data/app/components/references_many_component.rb +7 -0
  32. data/app/components/references_one/choose.html.erb +9 -0
  33. data/app/components/references_one/form.html.erb +28 -0
  34. data/app/components/references_one_component.rb +12 -0
  35. data/app/components/select/form.html.erb +5 -0
  36. data/app/components/select_component.rb +15 -0
  37. data/app/components/string/form.html.erb +5 -0
  38. data/app/components/string_component.rb +3 -0
  39. data/app/components/text/form.html.erb +5 -0
  40. data/app/components/text_component.rb +3 -0
  41. data/app/controllers/puffer/base.rb +4 -0
  42. data/app/views/puffer/base/_form.html.erb +0 -1
  43. data/app/views/puffer/base/_table.html.erb +25 -0
  44. data/app/views/puffer/base/index.html.erb +14 -28
  45. data/app/views/puffer/tree_base/_record.html.erb +1 -1
  46. data/lib/generators/puffer/component/USAGE +12 -0
  47. data/lib/generators/puffer/component/component_generator.rb +19 -0
  48. data/lib/generators/puffer/component/templates/component.rb +15 -0
  49. data/lib/generators/puffer/component/templates/component_spec.rb +19 -0
  50. data/lib/puffer/component.rb +141 -0
  51. data/lib/puffer/controller/dsl.rb +25 -12
  52. data/lib/puffer/engine.rb +5 -0
  53. data/lib/puffer/extensions/controller.rb +11 -9
  54. data/lib/puffer/extensions/form.rb +2 -1
  55. data/lib/puffer/extensions/mapper.rb +2 -0
  56. data/lib/puffer/field.rb +30 -19
  57. data/lib/puffer/field_set.rb +17 -2
  58. data/lib/puffer.rb +25 -8
  59. data/puffer.gemspec +59 -28
  60. data/spec/app/components/base_component_spec.rb +19 -0
  61. data/spec/app/components/boolean_component_spec.rb +36 -0
  62. data/spec/app/components/date_time_component_spec.rb +26 -0
  63. data/spec/app/components/file_component_spec.rb +25 -0
  64. data/spec/app/components/hidden_component_spec.rb +24 -0
  65. data/spec/app/components/password_component_spec.rb +37 -0
  66. data/spec/app/components/references_many_component_spec.rb +19 -0
  67. data/spec/app/components/references_one_component_spec.rb +19 -0
  68. data/spec/app/components/select_component_spec.rb +30 -0
  69. data/spec/app/components/string_component_spec.rb +25 -0
  70. data/spec/app/components/text_component_spec.rb +25 -0
  71. data/spec/dummy/app/controllers/admin/categories_controller.rb +3 -3
  72. data/spec/dummy/app/controllers/admin/posts_controller.rb +3 -0
  73. data/spec/dummy/app/controllers/{puffer → admin}/sessions_controller.rb +1 -1
  74. data/spec/dummy/app/controllers/admin/users_controller.rb +2 -2
  75. data/spec/dummy/app/models/post.rb +4 -0
  76. data/spec/dummy/db/migrate/20100930132656_create_posts.rb +2 -0
  77. data/spec/dummy/db/migrate/20100930132726_create_categories.rb +1 -0
  78. data/spec/dummy/db/schema.rb +3 -0
  79. data/spec/dummy/db/seeds.rb +6 -1
  80. data/spec/fabricators/categories_fabricator.rb +1 -0
  81. data/spec/fabricators/posts_fabricator.rb +1 -0
  82. data/spec/lib/component_spec.rb +7 -0
  83. data/spec/lib/fields_spec.rb +0 -4
  84. metadata +85 -56
  85. data/app/views/puffer/base/associated/_many.html.erb +0 -56
  86. data/app/views/puffer/base/associated/many.rjs +0 -1
  87. data/app/views/puffer/base/associated/one.js.erb +0 -13
  88. data/app/views/puffer/base/association/_many.html.erb +0 -7
  89. data/lib/puffer/controller/generated.rb +0 -65
  90. data/lib/puffer/customs.rb +0 -64
  91. data/lib/puffer/inputs/association.rb +0 -38
  92. data/lib/puffer/inputs/base.rb +0 -51
  93. data/lib/puffer/inputs/boolean.rb +0 -19
  94. data/lib/puffer/inputs/collection_association.rb +0 -11
  95. data/lib/puffer/inputs/date_time.rb +0 -16
  96. data/lib/puffer/inputs/file.rb +0 -11
  97. data/lib/puffer/inputs/hidden.rb +0 -15
  98. data/lib/puffer/inputs/password.rb +0 -11
  99. data/lib/puffer/inputs/select.rb +0 -19
  100. data/lib/puffer/inputs/text.rb +0 -11
@@ -1,5 +1,7 @@
1
1
  /*
2
2
  *= require puffer/reset
3
+ *= require puffer/right
4
+ *= require puffer/paginator
3
5
  *= require puffer/puffer
4
6
  *= require puffer/puffer_tree
5
7
  */
@@ -0,0 +1,33 @@
1
+ .rui-paginator {
2
+ margin: 10px 0;
3
+ }
4
+
5
+ .rui-paginator .rui-slider {
6
+ width: 100%;
7
+ }
8
+
9
+ .rui-paginator .rui-paginator-pages-wrapper {
10
+ width: 100%;
11
+ overflow: hidden;
12
+ }
13
+
14
+ .rui-paginator .rui-paginator-pages {
15
+ display: inline-block;
16
+ white-space: nowrap;
17
+ }
18
+
19
+ .rui-paginator .rui-paginator-pages li {
20
+ display: inline-block;
21
+ width: 40px;
22
+ height: 20px;
23
+ text-align: center;
24
+ }
25
+
26
+ .rui-paginator .rui-paginator-pages li a, .rui-paginator .rui-paginator-pages li span {
27
+ line-height: 20px;
28
+ padding: 0 5px;
29
+ }
30
+
31
+ .rui-paginator .rui-paginator-pages li.current span {
32
+ background: #ccc;
33
+ }
@@ -0,0 +1,4 @@
1
+ div.rui-dialog-head div.title
2
+ {
3
+ line-height: 2em;
4
+ }
@@ -0,0 +1,15 @@
1
+ <% content_for :label do %>
2
+ <%= opts[:form].label field %>
3
+ <% end unless content_for? :label %>
4
+
5
+ <% content_for :error do %>
6
+ <%= opts[:form].object.errors[field.name.to_sym].first %>
7
+ <% end unless content_for? :error %>
8
+
9
+ <div class="label">
10
+ <%= yield :label %>
11
+ <div class="field_error">
12
+ <%= yield :error %>
13
+ </div>
14
+ </div>
15
+ <%= yield :input %>
@@ -0,0 +1,15 @@
1
+ class BaseComponent < Puffer::Component::Base
2
+
3
+ def index
4
+ opts[:record].call_chain(field.to_s)
5
+ end
6
+
7
+ def form
8
+ render
9
+ end
10
+
11
+ def filter
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,3 @@
1
+ <%= opts[:form].check_box field, field.input_options %>
2
+ <%= opts[:form].label field %>
3
+ <%= opts[:form].object.errors[field.name.to_sym].first %>
@@ -0,0 +1,3 @@
1
+ <%= component_wrap do %>
2
+ <%= link_to opts[:record].call_chain(field.to_s) ? 'True' : 'False', event_path(:update, :id => opts[:record].to_param), :remote => true %>
3
+ <% end %>
@@ -0,0 +1,13 @@
1
+ class BooleanComponent < BaseComponent
2
+
3
+ def index
4
+ render
5
+ end
6
+
7
+ def update
8
+ opts[:record] = resource.member
9
+ opts[:record].update_attributes field.to_s => !opts[:record].call_chain(field.to_s)
10
+ replace :index
11
+ end
12
+
13
+ end
@@ -0,0 +1,5 @@
1
+ <% content_for :input do %>
2
+ <%= opts[:form].text_field field, field.input_options.merge("data-calendar" => "{showButtons: true, listYears: true, format: '#{@format}'}", :autocomplete => :off) %>
3
+ <% end %>
4
+
5
+ <%= render :file => 'base/form' %>
@@ -0,0 +1,12 @@
1
+ class DateTimeComponent < BaseComponent
2
+
3
+ def form
4
+ @format = case field.type
5
+ when :date then '%Y-%m-%d'
6
+ when :time then '%H:%M:%S'
7
+ when :datetime, :timestamp then '%Y-%m-%d %H:%M:%S'
8
+ end
9
+ super
10
+ end
11
+
12
+ end
@@ -0,0 +1,5 @@
1
+ <% content_for :input do %>
2
+ <%= opts[:form].file_field field, field.input_options %>
3
+ <% end %>
4
+
5
+ <%= render :file => 'base/form' %>
@@ -0,0 +1,3 @@
1
+ class FileComponent < BaseComponent
2
+
3
+ end
@@ -0,0 +1 @@
1
+ <%= opts[:form].hidden_field field, field.input_options %>
@@ -0,0 +1,3 @@
1
+ class HiddenComponent < BaseComponent
2
+
3
+ end
@@ -0,0 +1,5 @@
1
+ <% content_for :input do %>
2
+ <%= opts[:form].password_field field, field.input_options %>
3
+ <% end %>
4
+
5
+ <%= render :file => 'base/form' %>
@@ -0,0 +1,7 @@
1
+ class PasswordComponent < BaseComponent
2
+
3
+ def index
4
+ '*' * opts[:record].call_chain(field.to_s).mb_chars.length
5
+ end
6
+
7
+ end
@@ -0,0 +1 @@
1
+ # I'm form
@@ -0,0 +1,7 @@
1
+ class ReferencesManyComponent < Puffer::Component::Base
2
+
3
+ def form
4
+ render
5
+ end
6
+
7
+ end
@@ -0,0 +1,9 @@
1
+ <%= render :layout => '../views/puffer/base/table', :locals => { :table_fields => field.children, :controller => controller.parent_controller } do |record| %>
2
+ <% link_to t('.choose'), '#' %>
3
+ <% end %>
4
+
5
+ <div id="paginator"></div>
6
+
7
+ <%= javascript_tag do %>
8
+ new Paginator({total: <%= records.num_pages %>, current: <%= params[:page] || 1 %>, link: {'data-dialog-uri': '<%= event_path(:choose, :page => '%{page}') %>'}}).insertTo('paginator', 'instead');
9
+ <% end %>
@@ -0,0 +1,28 @@
1
+ <% content_for :input do %>
2
+ <% value = [
3
+ swallow_nil{opts[:form].object.send(field.name)[field.reflection.primary_key_column.name.to_sym]},
4
+ swallow_nil{opts[:form].object.send(field.name).to_title}
5
+ ].compact.join(' - ')
6
+ %>
7
+
8
+ <div class="association">
9
+ <%= text_field_tag field, value, field.input_options.merge(
10
+ :autocomplete => :off,
11
+ :disabled => (true if opts[:form].object.send(field.name)),
12
+ 'data-autocompleter' => "{url: '#{event_path :choose}', onDone: association_done}"
13
+ ) %>
14
+ <div class="association_clear">×</div>
15
+ <%= opts[:form].hidden_field field.reflection.foreign_key %>
16
+ </div>
17
+ <% end %>
18
+
19
+ <% clean_content_for :input do %>
20
+ <% link_to "Choose", '#', :"data-dialog-uri" => event_path(:choose) %>
21
+ <% end %>
22
+
23
+ <% content_for :error do %>
24
+ <%= opts[:form].object.errors[field.reflection.foreign_key.to_sym].first ||
25
+ opts[:form].object.errors[field.name.to_sym].first.presence %>
26
+ <% end %>
27
+
28
+ <%= render :file => 'base/form' %>
@@ -0,0 +1,12 @@
1
+ class ReferencesOneComponent < Puffer::Component::Base
2
+
3
+ def form
4
+ render
5
+ end
6
+
7
+ def choose
8
+ @records = field.reflection.klass.includes(field.children.includes).where(field.children.searches(params[:search])).page(params[:page])
9
+ render
10
+ end
11
+
12
+ end
@@ -0,0 +1,5 @@
1
+ <% content_for :input do %>
2
+ <%= opts[:form].select field, @options, {:include_blank => field.options[:include_blank]}, field.input_options %>
3
+ <% end %>
4
+
5
+ <%= render :file => 'base/form' %>
@@ -0,0 +1,15 @@
1
+ class SelectComponent < BaseComponent
2
+
3
+ def form
4
+ @options = case field.options[:select]
5
+ when Symbol then
6
+ parent_controller.send field.options[:select]
7
+ when Proc then
8
+ field.options[:select].bind(self).call
9
+ else
10
+ field.options[:select]
11
+ end
12
+ super
13
+ end
14
+
15
+ end
@@ -0,0 +1,5 @@
1
+ <% content_for :input do %>
2
+ <%= opts[:form].text_field field, field.input_options %>
3
+ <% end %>
4
+
5
+ <%= render :file => 'base/form' %>
@@ -0,0 +1,3 @@
1
+ class StringComponent < BaseComponent
2
+
3
+ end
@@ -0,0 +1,5 @@
1
+ <% content_for :input do %>
2
+ <%= opts[:form].text_area field, field.input_options %>
3
+ <% end %>
4
+
5
+ <%= render :file => 'base/form' %>
@@ -0,0 +1,3 @@
1
+ class TextComponent < BaseComponent
2
+
3
+ end
@@ -43,6 +43,10 @@ module Puffer
43
43
  redirect_to (request.referrer || resource.collection_path)
44
44
  end
45
45
 
46
+ def event
47
+ render :text => fields(params[:fieldset])[params[:field]].render(self, params[:event])
48
+ end
49
+
46
50
  private
47
51
 
48
52
  def puffer_saving_location
@@ -9,4 +9,3 @@
9
9
  <%= f.submit t('puffer.save_and_exit') %>
10
10
  <%= link_to 'cancel', (request.referer || resource.collectin_path) %>
11
11
  </div>
12
-
@@ -0,0 +1,25 @@
1
+ <table class="list_table">
2
+
3
+ <thead>
4
+ <tr>
5
+ <% table_fields.each do |field| -%>
6
+ <th><%= render_head field %></th>
7
+ <% end -%>
8
+ <th class="actions">Actions</th>
9
+ </tr>
10
+ </thead>
11
+
12
+ <tbody>
13
+ <% records.each do |record| -%>
14
+ <tr>
15
+ <% table_fields.each do |field| -%>
16
+ <td><%= field.render controller, :index, :record => record %></td>
17
+ <% end -%>
18
+ <td class="actions">
19
+ <%= yield record %>
20
+ </td>
21
+ </tr>
22
+ <% end -%>
23
+ </tbody>
24
+
25
+ </table>
@@ -1,34 +1,20 @@
1
1
  <% @title = resource.human %>
2
2
  <h1><%= @title %></h1>
3
- <%= paginate records, :url => resource.collection_path(:page => '') %>
3
+
4
+
4
5
  <% if records.present? %>
5
- <table class="list_table">
6
- <thead>
7
- <tr>
8
- <% index_fields.each do |field| -%>
9
- <th><%= render_head field %></th>
10
- <% end -%>
11
- <th class="actions">Actions</th>
12
- </tr>
13
- </thead>
14
- <tbody>
15
- <% records.each do |record| -%>
16
- <tr>
17
- <% index_fields.each do |field| -%>
18
- <td><%= render_field field, record %></td>
19
- <% end -%>
20
- <td class="actions">
21
- <%= link_to 'edit', resource.edit_path(record) if update_fields.present? %>
22
- <% controller._members.each do |member| %>
23
- <%= link_to member.label, resource.member_path(record, :action => member.action) if member.display? %>
24
- <% end %>
25
- <%= link_to 'destroy', resource.member_path(record), :confirm => "Are you sure?", :method => :delete if configuration.destroy %>
26
- </td>
27
- </tr>
28
- <% end -%>
29
- </tbody>
30
- </table>
6
+ <div class="rui-paginator" data-paginator="{total: <%= records.num_pages %>, current: <%= params[:page] || 1 %>, link: {href: '<%= resource.collection_path(:page => '%{page}') %>'}}"></div>
7
+
8
+ <%= render :layout => 'table', :locals => {:table_fields => index_fields} do |record| %>
9
+ <%= link_to 'edit', resource.edit_path(record) if update_fields.present? %>
10
+ <% _members.each do |member| %>
11
+ <%= link_to member.label, resource.member_path(record, :action => member.action) if member.display? %>
12
+ <% end %>
13
+ <%= link_to 'destroy', resource.member_path(record), :confirm => "Are you sure?", :method => :delete if configuration.destroy %>
14
+ <% end %>
15
+
16
+ <div class="rui-paginator" data-paginator="{total: <%= records.num_pages %>, current: <%= params[:page] || 1 %>, link: {href: '<%= resource.collection_path(:page => '%{page}') %>'}}"></div>
31
17
  <% else %>
32
18
  <p>Sorry, but there is no records in <%= resource.human %></p>
33
19
  <% end %>
34
- <%= paginate records, :url => resource.collection_path(:page => '') %>
20
+
@@ -12,7 +12,7 @@
12
12
  <% end %>
13
13
  <span class="handle">⇅</span>
14
14
  <% tree_fields.each do |field| -%>
15
- <span><%= render_field field, record %></span>
15
+ <span><%= field.render controller, :tree, :record => record %></span>
16
16
  <% end -%>
17
17
  </dt>
18
18
  <dd class="column">
@@ -0,0 +1,12 @@
1
+ Description:
2
+ Create puffer component
3
+
4
+ Example:
5
+ rails generate puffer:component password
6
+
7
+ This will create:
8
+ app/components/password_component.rb
9
+ app/components/password/index.html.erb
10
+ app/components/password/form.html.erb
11
+ app/components/password/filter.html.erb
12
+ spec/app/components/password_component_spec.rb
@@ -0,0 +1,19 @@
1
+ class Puffer::ComponentGenerator < Rails::Generators::NamedBase
2
+ source_root File.expand_path('../templates', __FILE__)
3
+
4
+ def generate_component
5
+ @name = name.underscore
6
+
7
+ template 'component.rb', "app/components/#{@name}_component.rb"
8
+ template 'component_spec.rb', "spec/app/components/#{@name}_component_spec.rb"
9
+ end
10
+
11
+ def generate_views
12
+ @name = name.underscore
13
+
14
+ create_file "app/components/#{@name}/index.html.erb", "# I'm index"
15
+ create_file "app/components/#{@name}/form.html.erb", "# I'm form"
16
+ create_file "app/components/#{@name}/filter.html.erb", "# I'm filter"
17
+ end
18
+
19
+ end
@@ -0,0 +1,15 @@
1
+ class <%= @name.camelize %>Component < Puffer::Component::Base
2
+
3
+ def index
4
+ render
5
+ end
6
+
7
+ def form
8
+ render
9
+ end
10
+
11
+ def filter
12
+ render
13
+ end
14
+
15
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe <%= @name.camelize %>Component do
4
+
5
+ include RSpec::Rails::RequestExampleGroup
6
+
7
+ context 'index' do
8
+
9
+ it 'should render index component'
10
+
11
+ end
12
+
13
+ context 'form' do
14
+
15
+ it 'should render form component'
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,141 @@
1
+ module Puffer
2
+ module Component
3
+
4
+ # <tt>Puffer::Component::Base</tt> is a base component low-level for puffer
5
+ # fields. It provides all the base functionality for rendering visual fields
6
+ # components.
7
+ # Every component belongs to field by field's type
8
+ # Every component should have some basic actions, based on parent controller
9
+ # fieldsets, so they can be fallbacked as fieldsets.
10
+ #
11
+ # Also, every component can have additional actions for ajax requests
12
+ # handling and component state changing
13
+ class Base < AbstractController::Base
14
+
15
+ module ComponentHelper
16
+ def component_wrap name = :span, options = {}, &block
17
+ content_tag name, options.merge(:id => component_id), &block
18
+ end
19
+
20
+ def clean_content_for name, *args, &block
21
+ @view_flow.set name, ''
22
+ content_for name, *args, &block
23
+ end
24
+
25
+ def paginate(scope, options = {}, &block)
26
+ paginator = Kaminari::Helpers::Paginator.new parent_controller.view_context, options.reverse_merge(:current_page => scope.current_page, :num_pages => scope.num_pages, :per_page => scope.limit_value, :param_name => Kaminari.config.param_name, :remote => false)
27
+ paginator.to_s
28
+ end
29
+ end
30
+
31
+ module SingletonMethods
32
+ def render_component parent_controller, field, context, *args
33
+ klass = "#{field.type}_component".camelize.constantize rescue StringComponent
34
+ component = klass.new field
35
+ component.process parent_controller, context, *args
36
+ end
37
+ end
38
+
39
+ module ClassMethods
40
+ def controller_path
41
+ @controller_path ||= name.sub(/Component$/, '').underscore unless anonymous?
42
+ end
43
+ end
44
+
45
+ abstract!
46
+
47
+ include AbstractController::Rendering
48
+ include AbstractController::Helpers
49
+ include AbstractController::Translation
50
+ include AbstractController::Logger
51
+ include AbstractController::Layouts
52
+
53
+ include ActionController::RequestForgeryProtection
54
+ include ActionController::UrlFor
55
+ include Rails.application.routes.url_helpers
56
+
57
+ extend SingletonMethods
58
+ extend ClassMethods
59
+
60
+ helper ComponentHelper, PufferHelper
61
+
62
+ attr_accessor :parent_controller, :field, :opts, :identifer
63
+ delegate :env, :request, :params, :session, :resource, :_members, :_collections, :to => :parent_controller
64
+ helper_method :params, :session, :resource, :_members, :_collections, :parent_controller, :field, :opts, :identifer, :component_id, :event_url, :event_path, :record, :records
65
+
66
+ def initialize field
67
+ super()
68
+ @field = field
69
+ end
70
+
71
+ def process parent_controller, context, *args
72
+ @parent_controller = parent_controller
73
+ @identifer = params[:identifer] || generate_identifer
74
+ super context, *args
75
+ end
76
+
77
+ def send_action method_name, *args
78
+ @opts = args.extract_options!
79
+ send method_name, *args
80
+ end
81
+
82
+ def render *args, &block
83
+ options = _normalize_render(*args, &block)
84
+ options[:template] = fallback_action(options[:template])
85
+ render_to_body(options).html_safe
86
+ end
87
+
88
+ def replace *args
89
+ javascript_wrap :replace, render(*args)
90
+ end
91
+
92
+ def javascript_wrap type, html
93
+ case type
94
+ when :replace then
95
+ "$('#{component_id}').replace('#{view_context.escape_javascript html}')".html_safe
96
+ else
97
+ html
98
+ end
99
+ end
100
+
101
+ def method_for_action action_name
102
+ fallback_action(action_name) || super
103
+ end
104
+
105
+ def fallback_action action_name
106
+ ((parent_controller._fieldset_fallbacks[action_name] || []).detect {|name| action_method? name.to_s} || action_name).to_s
107
+ end
108
+
109
+ def event_url name, options = {}
110
+ resource.collection_url :event, (options || {}).merge(event_options(name))
111
+ end
112
+
113
+ def event_path name, options = {}
114
+ resource.collection_path :event, (options || {}).merge(event_options(name))
115
+ end
116
+
117
+ def event_options name
118
+ {:event => name, :field => field.to_s, :fieldset => field.field_set.name, :identifer => identifer}
119
+ end
120
+
121
+ def record
122
+ @record || instance_variable_get("@#{resource.model_name}")
123
+ end
124
+
125
+ def records
126
+ @records || instance_variable_get("@#{resource.model_name.pluralize}")
127
+ end
128
+
129
+ def component_id
130
+ @component_id ||= "component_#{identifer}"
131
+ end
132
+
133
+ private
134
+
135
+ def generate_identifer
136
+ Digest::MD5.hexdigest(SecureRandom.uuid)
137
+ end
138
+
139
+ end
140
+ end
141
+ end