Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added tests, forms and form support for Def Entries

  • Loading branch information...
commit 2dac70ab085e82b1ddf5e18904e5b09118a1632c 1 parent 93c96ad
Guy Boertje authored
Showing with 919 additions and 86 deletions.
  1. +19 −11 README
  2. +93 −0 app/controllers/flexifield_def_entries_controller.rb
  3. +103 −0 app/controllers/flexifield_defs_controller.rb
  4. +57 −0 app/models/flexifield.rb
  5. +21 −4 {lib → app/models}/flexifield_def.rb
  6. +61 −0 app/models/flexifield_def_entry.rb
  7. +38 −0 app/views/flexifield_def_entries/_list.html.erb
  8. +33 −0 app/views/flexifield_def_entries/_list.html2.erb
  9. +8 −0 app/views/flexifield_def_entries/index.html.erb
  10. +30 −0 app/views/flexifield_defs/_form.html.erb
  11. +13 −0 app/views/flexifield_defs/_show_one_def.html.erb
  12. +3 −0  app/views/flexifield_defs/edit.html.erb
  13. +29 −0 app/views/flexifield_defs/index-nonoocss.html.erb
  14. +19 −0 app/views/flexifield_defs/index.html.erb
  15. +2 −0  app/views/flexifield_defs/new.html.erb
  16. +5 −0 app/views/flexifield_defs/show.html.erb
  17. +18 −0 app/views/layouts/flexifield_defs.html.erb
  18. +3 −0  config/routes.rb
  19. +0 −21 lib/flexifield.rb
  20. +0 −13 lib/flexifield_def_entry.rb
  21. +6 −22 lib/has/flexible_fields.rb
  22. +17 −0 public/stylesheets/ffoocss/ffoogrids.css
  23. +298 −0 public/stylesheets/ffoocss/ffoostyling.css
  24. +4 −2 test/fixtures/flexifield_def_entries.yml
  25. +28 −6 test/has_flexible_fields_test.rb
  26. +11 −7 test/test_helper.rb
30 README
View
@@ -1,6 +1,10 @@
HasFlexibleFields
=================
+Added: Forms for Flexifield Definition management. Uses nested forms.
+Added: Wrapped Columns for Flexifield Definition Entry, wraps ActiveRecord::ConnectionAdapters::<Adapter>Column in a
+Struct to provide a content attribute and two convenience methods to use in view or form creation
+
The problem:
How does one add fields to a model (usually another project's models) without permanently altering the model structure?
@@ -40,8 +44,8 @@ NOTE: remember the polymorphic nature of the flexifield model, only drop the ff
TODO:
-partials for flexifield definitions forms
-
+DONE: partials for flexifield definitions forms
+DONE: partials for flexifield data entry
NOTE: currently this version requires rails v 2.3.2
@@ -62,26 +66,30 @@ and flexifield_def_entries of:
ffd1e1:
flexifield_def_id: 1
flexifield_name: ffs_01
- flexifield_alias: preparation time
- ordering: 1
+ flexifield_alias: preparation_time
+ flexifield_tooltip: Enter time in decimal hours or minutes
+ flexifield_order: 1
ffd1e2:
flexifield_def_id: 1
flexifield_name: ffs_02
- flexifield_alias: cooking time
- ordering: 2
+ flexifield_alias: cooking_time
+ flexifield_tooltip: Enter time in H hours M minutes
+ flexifield_order: 2
Then this saves the additional content with the main content...
r = Content.create! :title => 'Roast Pork Belly', :body => 'Ingredients: ...'
- r.assign_ff_def 1
- r.assign_ff_value 'preparation time', '25 minutes'
- r.assign_ff_value 'cooking time', '2 hours 30 minutes'
+ r.ff_def= 1
+ r.set_ff_value 'preparation_time', '25 minutes'
+ r.set_ff_value 'cooking_time', '2 hours 30 minutes'
+ r.assign_ff_values {:preparation_time => '25 minutes', :cooking_time => '2 hours 30 minutes'}
+ r.get_ff_value(:preparation_time) # -> '25 minutes'
and
- r.ff_aliases # -> ["preparation time","cooking time"]
+ r.ff_aliases # -> ["preparation_time","cooking_time"]
r.ff_fields # -> ["ffs_01","ffs_02"]
and
r.to_ff_alias 'ffs_01' # -> "preparation time"
- r.to_ff_field 'cooking time' # -> "ffs_02"
+ r.to_ff_field 'cooking_time' # -> "ffs_02"
But forms that save to ffs_NN directly will also work.
93 app/controllers/flexifield_def_entries_controller.rb
View
@@ -0,0 +1,93 @@
+class FlexifieldDefEntriesController < ApplicationController
+
+ before_filter :get_flexifield_def
+ before_filter :find_flexifield_def_entry, :only => %w(show update destroy)
+
+ layout 'flexifield_defs'
+
+ # GET /flexifield_defs/:flexifield_def_id/flexifield_def_entries
+ # GET /flexifield_defs/:flexifield_def_id/flexifield_def_entries.xml
+ def index
+ @flexifield_def_entries = @flexifield_def.flexifield_def_entries.find(:all)
+ respond_to do |format|
+ format.html # index.html.erb
+ format.xml { render :xml => @flexifield_def_entries }
+ end
+ end
+
+ # GET /flexifield_defs/:flexifield_def_id/flexifield_def_entries/1
+ # GET /flexifield_defs/:flexifield_def_id/flexifield_def_entries/1.xml
+ def show
+ respond_to do |format|
+ format.html # show.html.erb
+ format.xml { render :xml => @flexifield_def_entry }
+ end
+ end
+
+ # GET /flexifield_defs/:flexifield_def_id/flexifield_def_entries/new
+ # GET /flexifield_defs/:flexifield_def_id/flexifield_def_entries/new.xml
+ def new
+ @flexifield_def_entry = @flexifield_def.flexifield_def_entries.new
+ respond_to do |format|
+ format.html # new.html.erb
+ format.xml { render :xml => @flexifield_def_entry }
+ end
+ end
+
+ # GET /flexifield_defs/:flexifield_def_id/flexifield_def_entries/1/edit
+ def edit
+ end
+
+ # POST /flexifield_defs/:flexifield_def_id/flexifield_def_entries
+ # POST /flexifield_defs/:flexifield_def_id/flexifield_def_entries.xml
+ def create
+ @flexifield_def_entry = @flexifield_def.flexifield_def_entries.new(params[:flexifield_def_entry])
+ respond_to do |format|
+ if @flexifield_def_entry.save
+ flash[:notice] = 'FlexifieldDefEntry was successfully created.'
+ format.html { redirect_to(@flexifield_def_entry) }
+ format.xml { render :xml => @flexifield_def_entry, :status => :created, :location => @flexifield_def_entry }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @flexifield_def_entry.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT /flexifield_defs/:flexifield_def_id/flexifield_def_entries/1
+ # PUT /flexifield_defs/:flexifield_def_id/flexifield_def_entries/1.xml
+ def update
+ respond_to do |format|
+ if @flexifield_def_entry.update_attributes(params[:flexifield_def_entry])
+ flash[:notice] = 'FlexifieldDefEntry was successfully updated.'
+ format.html { redirect_to(@flexifield_def_entry) }
+ format.xml { head :ok }
+ else
+ format.html { render :action => "edit" }
+ format.xml { render :xml => @flexifield_def_entry.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /flexifield_defs/:flexifield_def_id/flexifield_def_entries/1
+ # DELETE /flexifield_defs/:flexifield_def_id/flexifield_def_entries/1.xml
+ def destroy
+ @flexifield_def_entry.destroy
+ respond_to do |format|
+ format.html { redirect_to(flexifield_def_entries_url) }
+ format.xml { head :ok }
+ end
+ end
+
+ private
+
+ def find_flexifield_def_entry
+ get_flexifield_def unless @flexifield_def
+ @flexifield_def_entry = @flexifield_def.flexifield_def_entries.find(params[:id])
+ end
+
+ def get_flexifield_def
+ @flexifield_def = FlexifieldDef.find(params[:flexifield_def_id])
+ end
+
+end
103 app/controllers/flexifield_defs_controller.rb
View
@@ -0,0 +1,103 @@
+class FlexifieldDefsController < ApplicationController
+
+ before_filter :find_flexifield_def, :only => %w(show edit update destroy)
+
+ helper_method :setup_flexifield_def
+
+ # GET /flexifield_defs
+ # GET /flexifield_defs.xml
+ def index
+ @flexifield_defs = FlexifieldDef.all :include => :flexifield_def_entries
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.xml { render :xml => @flexifield_defs }
+ end
+ end
+
+ # GET /flexifield_defs/1
+ # GET /flexifield_defs/1.xml
+ def show
+ @flexifield_def = FlexifieldDef.find(params[:id], :include => :flexifield_def_entries)
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.xml { render :xml => @flexifield_def }
+ end
+ end
+
+ # GET /flexifield_defs/new
+ # GET /flexifield_defs/new.xml
+ def new
+ @flexifield_def = FlexifieldDef.new
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.xml { render :xml => @flexifield_def }
+ end
+ end
+
+ # GET /flexifield_defs/1/edit
+ def edit
+ end
+
+ # POST /flexifield_defs
+ # POST /flexifield_defs.xml
+ def create
+ @flexifield_def = FlexifieldDef.new(params[:flexifield_def])
+
+ respond_to do |format|
+ if @flexifield_def.save
+ flash[:notice] = 'FlexifieldDef was successfully created.'
+ format.html { redirect_to(@flexifield_def) } #flexifield_defs_url
+ format.xml { render :xml => @flexifield_def, :status => :created, :location => @flexifield_def }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @flexifield_def.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT /flexifield_defs/1
+ # PUT /flexifield_defs/1.xml
+ def update
+ respond_to do |format|
+ if @flexifield_def.update_attributes(params[:flexifield_def])
+ flash[:notice] = 'FlexifieldDef was successfully updated.'
+ format.html { redirect_to(@flexifield_def) }
+ format.xml { head :ok }
+ else
+ format.html { render :action => "edit" }
+ format.xml { render :xml => @flexifield_def.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /flexifield_defs/1
+ # DELETE /flexifield_defs/1.xml
+ def destroy
+ @flexifield_def.destroy
+
+ respond_to do |format|
+ format.html { redirect_to(flexifield_defs_url) }
+ format.xml { head :ok }
+ end
+ end
+
+ def setup_flexifield_def(flexifield_def)
+ returning(flexifield_def) do |ffd|
+ if ffd.flexifield_def_entries.empty?
+ ffd.flexifield_def_entries.build
+ end
+ if !ffd.flexifield_def_entries.last.id.blank? && ffd.flexifield_def_entries.length < Flexifield.flexiblefield_names_count
+ ffd.flexifield_def_entries << FlexifieldDefEntry.new()
+ end
+ end
+ end
+
+ private
+
+ def find_flexifield_def
+ @flexifield_def = FlexifieldDef.find(params[:id], :include => :flexifield_def_entries)
+ end
+end
57 app/models/flexifield.rb
View
@@ -0,0 +1,57 @@
+# To change this template, choose Tools | Templates
+# and open the template in the editor.
+
+class Flexifield < ActiveRecord::Base
+
+ belongs_to :flexifield_set, :polymorphic => true
+ belongs_to :flexifield_def, :include => 'flexifield_def_entries'
+
+ delegate :to_ff_alias, :to_ff_field, :ff_aliases, :ff_fields, :to => :flexifield_def
+
+ def self.flexiblefield_names
+ columns.map(&:name).grep(/ff.+_/)
+ end
+
+ def self.flexiblefield_names_count
+ columns.map(&:name).grep(/ff.+_/).length
+ end
+
+ def ff_def
+ read_attribute :flexifield_def_id
+ end
+
+ def ff_def= ff_def_id
+ write_attribute :flexifield_def_id, ff_def_id
+ save
+ end
+
+ def get_ff_value ff_alias
+ ff_field = to_ff_field ff_alias
+ if ff_field
+ read_attribute ff_field
+ else
+ raise ArgumentError, "Flexifield alias: #{ff_alias} not found in flexifeld def mapping"
+ end
+ end
+
+ def set_ff_value ff_alias, ff_value
+ ff_field = to_ff_field ff_alias
+ if ff_field
+ write_attribute ff_field, ff_value
+ else
+ raise ArgumentError, "Flexifield alias: #{ff_alias} not found in flexifeld def mapping"
+ end
+ end
+
+ def assign_ff_values args_hash
+ unless args_hash.is_a? Hash
+ raise ArgumentError, "Method argument must be a hash"
+ end
+ args_hash.each do |ffalias, ffvalue|
+ set_ff_value ffalias, ffvalue
+ end
+ save
+ end
+
+
+end
25 lib/flexifield_def.rb → app/models/flexifield_def.rb
View
@@ -1,20 +1,27 @@
class FlexifieldDef < ActiveRecord::Base
- has_many :flexifield_def_entries, :class_name => 'FlexifieldDefEntry', :order => 'ordering', :dependent => :destroy
- accepts_nested_attributes_for :flexifield_def_entries
+ has_many :flexifield_def_entries, :class_name => 'FlexifieldDefEntry', :order => 'flexifield_order', :dependent => :destroy
+ accepts_nested_attributes_for :flexifield_def_entries,
+ :reject_if => proc { |attrs| attrs['flexifield_alias'].blank? }
+ validates_presence_of :name
+
+ #after_update :save_entries
+
def to_ff_field ff_alias
idx = nil
+ ffa = "#{ff_alias}"
ff_aliases.each_with_index do |c,i|
- idx = i if c == ff_alias
+ idx = i if c == ffa
end
idx ? flexifield_def_entries[idx].to_ff_field : nil
end
def to_ff_alias ff_field
idx = nil
+ fff = "#{ff_field}" #make sure it is a string
ff_fields.each_with_index do |c,i|
- idx = i if c == ff_field
+ idx = i if c == fff
end
idx ? flexifield_def_entries[idx].to_ff_alias : nil
end
@@ -27,5 +34,15 @@ def ff_fields
flexifield_def_entries.nil? ? [] : flexifield_def_entries.map(&:flexifield_name)
end
+ def unassigned_flexifield_names
+ Flexifield.flexiblefield_names - ff_fields
+ end
+
+ private
+ def save_entries
+ flexifield_def_entries.each do |entry|
+ entry.save false
+ end
+ end
end
61 app/models/flexifield_def_entry.rb
View
@@ -0,0 +1,61 @@
+class FlexifieldDefEntry < ActiveRecord::Base
+ belongs_to :flexifield_def
+ validates_presence_of :flexifield_name, :flexifield_alias, :flexifield_order
+
+ before_save :ensure_alias_is_one_word
+
+ ViewColumn = Struct.new(:object,:content) do
+ def viewname
+ object.name.gsub(/flexifield_/,"").titleize
+ end
+ def field
+ object.name.to_sym
+ end
+ end
+
+ def self.view_columns
+ columns.map{|c| ViewColumn.new(c) if [:integer,:string,:text].member?(c.type) && c.name =~ /flexifield_(?!.+_id)/}.compact
+ end
+
+ def self.wrap_form_columns(form_for)
+ returning view_columns do |a|
+ a.each do |c|
+ case c.field
+ when :flexifield_alias
+ c.content= form_for.text_field(c.field)
+ when :flexifield_name
+ c.content= form_for.select(c.field, Flexifield.flexiblefield_names)
+ when :flexifield_tooltip
+ c.content= form_for.text_area(c.field, :cols => 80, :rows => 6)
+ when :flexifield_order
+ c.content= form_for.select(c.field, (1..32).to_a)
+ end
+ end
+ end
+ end
+
+ def self.wrap_viewable_columns(css, lastcss)
+ returning view_columns do |a|
+ a[0..-2].each do |c|
+ c.content= css
+ end
+ a.last.content= lastcss
+ end
+ end
+
+ def to_ff_field ff_alias = nil
+ (ff_alias.nil? || flexifield_alias == ff_alias) ? flexifield_name : nil
+ end
+ def to_ff_alias ff_field = nil
+ (ff_field.nil? || flexifield_name == ff_field) ? flexifield_alias : nil
+ end
+
+ private
+
+ def ensure_alias_is_one_word
+ flexifield_alias.gsub!(/\s+/,"_")
+ end
+
+
+
+end
38 app/views/flexifield_def_entries/_list.html.erb
View
@@ -0,0 +1,38 @@
+
+<%
+fields = FlexifieldDefEntry.wrap_viewable_columns("unit","lastUnit")
+fdescss_size = "size1of" + (fdelist ? fields.size.succ.to_s : fields.size.to_s)
+%>
+
+ <div class="line">
+ <% if fdelist %>
+ <div class="unit <%= fdescss_size %> shoveR4px"></div>
+ <% end %>
+ <% fields.each do |ffield| %>
+ <div class="<%= ffield.content + " " + fdescss_size %> shoveR4px"><%= ffield.viewname %></div>
+ <% end %>
+ </div>
+ <hr/>
+ <% fdes.each do |fde| %>
+ <div class="line strong afterLine0-25em">
+ <% if fdelist %>
+ <div class="unit <%= fdescss_size %> shoveR4px">
+ <%= link_to 'Edit', edit_flexifield_def_flexifield_def_entry_path(fde.flexifield_def, fde) %>|
+ <%= link_to 'Destroy', [fde.flexifield_def, fde], :confirm => 'Are you sure?', :method => :delete %>
+ </div>
+ <% end %>
+ <% fields.each do |ffield| %>
+ <div class="<%= ffield.content + " " + fdescss_size %> shoveR4px"><%=h fde.send(ffield.field) || ".." %></div>
+ <% end %>
+ </div>
+ <% end %>
+ <% if fdelist %>
+ <hr/>
+ <div class="line">
+ <div class="lastUnit shoveR4px">
+ <%= link_to 'New Flexifield Definition Entry', new_flexifield_def_flexifield_def_entry_path(fd) %>
+ </div>
+ </div>
+ <% end %>
+
+
33 app/views/flexifield_def_entries/_list.html2.erb
View
@@ -0,0 +1,33 @@
+
+<%
+names = FlexifieldDefEntry.viewable_column_names
+%>
+ <table>
+ <tr>
+ <% names.each do |name| %>
+ <th><%= FlexifieldDefEntry.to_displayname(name) %></th>
+ <% end %>
+ </tr>
+ <tbody>
+ <% fdes.each do |fde| %>
+ <tr>
+ <% names.each do |name| %>
+ <td>
+ <%= h fde.send(name) %>
+ </td>
+ <% end %>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+
+ <% if fdelist %>
+ <hr/>
+ <div class="line">
+ <div class="lastUnit shoveR4px">
+ <%= link_to 'New Flexifield Definition Entry', new_flexifield_def_flexifield_def_entry_path(fd) %>
+ </div>
+ </div>
+ <% end %>
+
+
8 app/views/flexifield_def_entries/index.html.erb
View
@@ -0,0 +1,8 @@
+
+<h2>Listing Flexifield Definition Entries</h2>
+<div class="parent_tag rounded">
+<%= render :partial => 'list', :locals => {:fdelist => true, :fdes => @flexifield_def_entries, :fd => @flexifield_def} %>
+</div>
+
+
+
30 app/views/flexifield_defs/_form.html.erb
View
@@ -0,0 +1,30 @@
+<% form_for(setup_flexifield_def(@flexifield_def)) do |def_form| %>
+ <%= def_form.error_messages %>
+ <fieldset class="parent_tag rounded">
+ <legend class="rounded">Flexifield Definition</legend>
+ <ul>
+ <li>
+ <%= def_form.label :name, 'Flexifield Def Name' %>
+ <%= def_form.text_field :name %>
+ </li>
+ <li>
+ <% def_form.fields_for :flexifield_def_entries do |entry_form| %>
+ <fieldset class="child_tag rounded">
+ <legend class="rounded"><%= entry_form.object.new_record? ? 'New Flexifield Definition Entry' : 'Flexifield Definition Entries' %></legend>
+ <ul>
+ <% FlexifieldDefEntry.wrap_form_columns(entry_form).each do |ffield| %>
+ <li>
+ <%= entry_form.label ffield.field, ffield.viewname %>
+ <%= ffield.content %>
+ </li>
+ <% end %>
+ </ul>
+ </fieldset>
+ <% end %>
+ </li>
+ </ul>
+ <div>
+ <%= def_form.submit 'Submit' %>
+ </div>
+ </fieldset>
+<% end %>
13 app/views/flexifield_defs/_show_one_def.html.erb
View
@@ -0,0 +1,13 @@
+<div class="parent_tag rounded">
+ <div class="line">
+ <div class="unit strong size1of5 shoveR8px"><%=h fd.name %></div>
+ <div class="lastUnit size4of5 shoveR8px child_tag rounded">
+ <%= render :partial => 'flexifield_def_entries/list', :locals => {:fdelist => false, :fdes => fd.flexifield_def_entries, :fd => fd} %>
+ </div>
+ </div>
+ <div class="line">
+ <div class="lastUnit shoveR8px">
+ <%= link_to 'Edit', edit_flexifield_def_path(fd) %>|<%= link_to 'Destroy', fd, :confirm => 'Are you sure?', :method => :delete %>
+ </div>
+ </div>
+</div>
3  app/views/flexifield_defs/edit.html.erb
View
@@ -0,0 +1,3 @@
+<%= render :partial => 'form' %>
+<%= link_to 'Show', @flexifield_def %> |
+<%= link_to 'Index', flexifield_defs_path %>
29 app/views/flexifield_defs/index-nonoocss.html.erb
View
@@ -0,0 +1,29 @@
+<%
+# I hope that you are using a Object Oriented CSS
+# and if you are not...
+%>
+
+<h1>Listing Flexifield Definitions</h1>
+
+<table>
+ <tr>
+ <th>Name</th>
+ </tr>
+
+<% @flexifield_defs.each do |fd| %>
+ <tr>
+ <td><%=h fd.name %></td>
+ <td><%= link_to 'Show', post %></td>
+ <td><%= link_to 'Edit', edit_flexifield_def_path(fd) %></td>
+ <td><%= link_to 'Destroy', fd, :confirm => 'Are you sure?', :method => :delete %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New Flexifield Defs', new_flexifield_def_path %>
+
+<%
+#but if you are...
+%>
19 app/views/flexifield_defs/index.html.erb
View
@@ -0,0 +1,19 @@
+<%
+# I hope that you are using a Object Oriented CSS
+# and if you are...
+%>
+
+<h6>Listing Flexifield Definitions</h6>
+<p class="shoveR8px">
+<%= link_to 'New Flexifield Definition', new_flexifield_def_path %>
+</p>
+<div class="line">
+ <div class="lastUnit shoveR8px">Name</div>
+</div>
+
+<% @flexifield_defs.each do |fd| %>
+<%= render :partial => 'show_one_def', :locals => {:fd => fd} %>
+<% end %>
+
+
+
2  app/views/flexifield_defs/new.html.erb
View
@@ -0,0 +1,2 @@
+<%= render :partial => 'form' %>
+<%= link_to 'Index', flexifield_defs_path %>
5 app/views/flexifield_defs/show.html.erb
View
@@ -0,0 +1,5 @@
+<h6>Flexifield Definition</h6>
+<%= render :partial => 'show_one_def', :locals => {:fd => @flexifield_def} %>
+<p>
+ <%= link_to 'Index', flexifield_defs_path %>
+</p>
18 app/views/layouts/flexifield_defs.html.erb
View
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+ <title>Flexifield Definitions: <%= controller.action_name %></title>
+ <%= stylesheet_link_tag 'ffoocss/ffoostyling' %>
+ <%= stylesheet_link_tag 'ffoocss/ffoogrids' %>
+</head>
+<body>
+
+<p style="color: green"><%= flash[:notice] %></p>
+
+<%= yield %>
+
+</body>
+</html>
3  config/routes.rb
View
@@ -0,0 +1,3 @@
+ActionController::Routing::Routes.draw do |map|
+ map.resources :flexifield_defs, :has_many => :flexifield_def_entries
+end
21 lib/flexifield.rb
View
@@ -1,21 +0,0 @@
-# To change this template, choose Tools | Templates
-# and open the template in the editor.
-
-class Flexifield < ActiveRecord::Base
-
- belongs_to :flexifield_set, :polymorphic => true
- belongs_to :flexifield_def, :include => 'flexifield_def_entries'
-
- delegate :to_ff_alias, :to_ff_field, :ff_aliases, :ff_fields, :to => :flexifield_def
-
- def ff_alias_value ff_alias
- ff_field = to_ff_field ff_alias
- if ff_field
- send ff_field
- else
- raise ArgumentError, "Flexifield alias: #{ff_alias} not found in flexifeld def mapping"
- end
-
- end
-
-end
13 lib/flexifield_def_entry.rb
View
@@ -1,13 +0,0 @@
-class FlexifieldDefEntry < ActiveRecord::Base
- belongs_to :flexifield_def
- validates_presence_of :flexifield_name, :flexifield_alias
-
- def to_ff_field ff_alias = nil
- (ff_alias.nil? || flexifield_alias == ff_alias) ? flexifield_name : nil
- end
- def to_ff_alias ff_field = nil
- (ff_field.nil? || flexifield_name == ff_field) ? flexifield_alias : nil
- end
-
-
-end
28 lib/has/flexible_fields.rb
View
@@ -4,9 +4,7 @@
# see README for license
module Has #:nodoc:
module FlexibleFields #:nodoc:
-
-
-
+
def self.included(base) # :nodoc:
base.extend ClassMethods
end
@@ -16,7 +14,7 @@ def has_flexiblefields options = {}
unless includes_flexiblefields?
has_one :flexifield, :as => :flexifield_set, :dependent => :destroy
- delegate :ff_alias_value, :to_ff_alias, :ff_aliases, :to_ff_field, :ff_fields, :to => :flexifield
+ delegate :assign_ff_values, :set_ff_value, :get_ff_value, :ff_def=, :ff_def, :to_ff_alias, :ff_aliases, :to_ff_field, :ff_fields, :to => :flexifield
accepts_nested_attributes_for :flexifield
@@ -56,14 +54,15 @@ def create_ff_tables!
t.integer :flexifield_def_id, :null => false
t.string :flexifield_name, :null => false
t.string :flexifield_alias, :null => false
- t.integer :ordering
+ t.string :flexifield_tooltip
+ t.integer :flexifield_order
t.timestamps
end
self.connection.add_index :flexifields, [:flexifield_set_id, :flexifield_set_type], :name => 'idx_ff_poly'
self.connection.add_index :flexifields, :flexifield_def_id
- self.connection.add_index :flexifield_def_entries, [:flexifield_def_id, :ordering], :name => 'idx_ffde_ordering'
+ self.connection.add_index :flexifield_def_entries, [:flexifield_def_id, :flexifield_order], :name => 'idx_ffde_ordering'
self.connection.add_index :flexifield_def_entries, [:flexifield_def_id, :flexifield_name], :name => 'idx_ffde_onceperdef', :unique => true
end
@@ -78,22 +77,7 @@ def drop_ff_tables!
module InstanceMethods
def has_ff_def?
flexifield.nil? ? false : !flexifield.flexifield_def_id.nil?
- end
-
- def assign_ff_def ff_def_id
- self.flexifield.flexifield_def_id = ff_def_id
- save_flexifield
- end
-
- def assign_ff_value ff_alias, value
- ff_field = to_ff_field ff_alias
- if ff_field
- self.flexifield.send "#{ff_field}=", value
- save_flexifield
- else
- raise ArgumentError, "Flexifield alias: #{ff_alias} not found in flexifeld def mapping"
- end
- end
+ end
protected
17 public/stylesheets/ffoocss/ffoogrids.css
View
@@ -0,0 +1,17 @@
+/* **************** GRIDS ***************** */
+.line, .lastUnit {overflow: hidden;_overflow:visible;_zoom:1; }
+.unit{float:left;_zoom:1;padding-right:0.5em;}
+.unitExt{float:right;}
+.size1of1{float:none;}
+.size1of2{width:50%;}
+.size1of3{width:33.33333%;}
+.size2of3{width:66.66666%;}
+.size1of4{width:25%;}
+.size3of4{width:75%;}
+.size1of5{width:20%;}
+.size2of5{width:40%;}
+.size3of5{width:60%;}
+.size4of5{width:80%;}
+.lastUnit {float:none;_position:relative; _left:-3px; _margin-right: -3px;width:auto;}
+/* extending grids to allow a unit that takes the width of its content */
+.media{width:auto;}
298 public/stylesheets/ffoocss/ffoostyling.css
View
@@ -0,0 +1,298 @@
+body {
+ background-color: #fff;
+ color: #333;
+ width:960px;
+ margin: auto;
+}
+
+body, p, ol, ul, td, input, select {
+ font-family: verdana, arial, helvetica, sans-serif;
+ font-size: 14px;
+ line-height: 20px;
+}
+
+/* ****************** Chrome ************** */
+li{margin-bottom: 0.3333em;}
+
+.em{font-style: italic;}
+.strong{font-weight:bold;}
+
+.txtR{text-align:right;}
+.shoveR4px{padding-left:4px;}
+.shoveR6px{padding-left:6px;}
+.shoveR8px{padding-left:8px;}
+.shoveR12px{padding-left:12px;}
+.shoveR16px{padding-left:16px;}
+.shoveR20px{padding-left:20px;}
+.shoveR24px{padding-left:24px;}
+.afterLine0-25em{margin-bottom: 0.25em;}
+.afterLine0-5em{margin-bottom: 0.5em;}
+.afterLine0-75em{margin-bottom: 0.75em;}
+.afterLine1em{margin-bottom: 1em;}
+
+.rounded {
+ line-height: 1.8em;
+ -moz-border-radius: 0.5em;
+ -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
+}
+
+/* Styles a drop cap on each paragraph with this class */
+p.drop:first-letter{
+ float:left;
+ font-size:3em;
+ margin-top:-0.05em;
+ margin-right:0.1em;
+ margin-bottom:-0.5em;
+}
+
+hr{ color: #CAC8C8;}
+/*HEADINGS
+-------------------------------------------------------- */
+h1{
+ color:#000;
+ font-size:2.2em;
+ margin-bottom:0.6em;
+ font-style:italic;
+ line-height:1.2em;
+}
+h2{
+ color:#000;
+ font-size:2em;
+ margin-bottom:0.9em;
+ line-height:0.9em;
+}
+h3{
+ color:#000;
+ font-size:1.5em;
+ margin-bottom:1.2em;
+ line-height:1.2em;
+ font-variant:small-caps;
+}
+h4{
+ color:#000;
+ font-size:1.2em;
+ margin-bottom:1.5em;
+ line-height:1.5em;
+}
+h5{
+ color:#000;
+ font-size:1em;
+ margin-bottom:1.8em;
+ line-height:1.8em;
+ font-variant:small-caps;
+}
+h6{
+ color:#000;
+ font-size:1em;
+ margin-bottom:1.8em;
+ line-height:1.8em;
+}
+/*LINKS
+-------------------------------------------------------- */
+p a{ color:#000; }
+p a:hover{ text-decoration:none; }
+h1 a{ color:#000; }
+h1 a:hover{ text-decoration:none; }
+li a{ color:#000; }
+li a:hover{ text-decoration:none; }
+
+/*ALL THE TRIMMINGS
+-------------------------------------------------------- */
+blockquote p{
+ font-size:1.2em!important;
+ line-height:1.5em!important;
+ margin-bottom:1.5em!important;
+ font-style:italic;
+ font-weight:bold;
+}
+blockquote p cite{
+ font-style:normal;
+}
+.generic strong{
+ font-variant:small-caps;
+}
+.generic em{
+ font-style:italic;
+ font-weight:inherit;
+}
+.amp{ /* Give those ampersands a right sexy look */
+ font-family:Baskerville, "Goudy Old Style", "Palatino", "Book Antiqua", serif;
+ font-style:italic;
+ font-weight:normal;
+ line-height:inherit;
+}
+abbr{
+ border-bottom:1px dotted #666;
+ border-color:inherit;
+ cursor:help;
+}
+.clear{
+ clear:both;
+}
+.right-float{ /* Float any item to the right */
+ float:right;
+ margin-left:2em;
+ margin-right:0;
+}
+.left-float{ /* Float any item to the left */
+ float:left;
+ margin-right:2em;
+ margin-left:0;
+}
+.code{ /* Styling for and code type items */
+ font-family:Courier, "Courier New", monospace;
+ background:#ddd;
+ font-size:1em;
+}
+/*-------------------------------------------+
+| |
+| IMAGE STYLES |
+| |
++-------------------------------------------*/
+img{
+ font-size:1em;
+}
+img.left-img{ /* Float any image to the LEFT and give it some margin */
+ font-size:1em;
+ float:left;
+ padding:4px;
+ border:1px solid #ccc;
+ margin-bottom:1.8em;
+ margin-right:2em;
+ margin-top:0.3em;
+}
+img.right-img{ /* Float any image to the RIGHT and give it some margin */
+ font-size:1em;
+ float:right;
+ padding:4px;
+ border:1px solid #ccc;
+ margin-bottom:1.8em;
+ margin-left:2em;
+ margin-top:0.3em;
+}
+/*CONTACT FORM STYLES
+-------------------------------------------------------- */
+#contact-form{
+}
+#contact-form label{
+ width:10em;
+ float:left;
+ margin-top:0.6em;
+}
+#name, #form-email, #url, #location{
+ width:42.7em;
+ height:20px;
+ padding:3px;
+ padding-top:5px;
+ border:2px solid #666;
+ margin-bottom:18px;
+ background:#fff !important;
+}
+#comments{
+ width:43.8em;
+ height:10em;
+ padding:3px;
+ border:2px solid #666;
+ margin-bottom:18px;
+ overflow:auto;
+ background:#fff !important;
+}
+#name:active, #form-email:active, #url:active, #location:active, #comments:active, #submit:active, #name:focus, #form-email:focus, #url:focus, #location:focus, #comments:focus, #submit:focus{
+ border:2px solid #000;
+}
+.submit{
+ clear:both;
+ padding:5px;
+ border:2px solid #666;
+ background:#fff !important;
+ cursor:pointer;
+}
+
+#reset{
+ clear:both;
+ padding:3px;
+ border:none;
+ background:#f00 !important;
+ cursor:pointer;
+ float:right;
+ color:#fff;
+ margin-top:-28px;
+}
+
+form {
+ color:#111111;
+ margin:0;
+ padding:0;
+}
+
+fieldset legend {
+ color: #fff;
+ background-color: #000;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+.parent_tag{
+ background-color:#d0fad0;
+ border:1px solid #CAC8C8 !important;
+ margin-top: 4px;
+}
+.child_tag{
+ background-color:#b0dab0;
+ border:1px solid #fff !important;
+ margin-top:0.5em;
+ margin-right: 0.5em;
+}
+
+.fieldWithErrors {
+ display: inline-block;
+}
+
+fieldset ul li label,fieldset ul li div label {
+ display: inline-block;
+ width: 10em;
+}
+
+
+/*-------------------------------------------+
+| |
+| LIST STYLES |
+| |
++-------------------------------------------*/
+fieldset ul {
+ list-style-type: none;
+ margin: 1em 0 1em 1.5em;
+ padding: 0;
+}
+fieldset ul li {
+ margin: 0 0 10px;
+}
+
+ul{
+ margin-bottom:1.8em;
+ list-style:square inside;
+}
+ul li{
+ font-size:1em;
+ line-height:2em;
+}
+ul li.caption{ /* Apply this class to the first list item in a list to give it a caption */
+ font-variant:small-caps;
+ list-style:none;
+ color:#000;
+}
+li > ul, li > ol{
+ margin-bottom:0;
+ margin-left:5em;
+}
+li > ul li, li > ol li{
+ font-size:1em;
+}
+ol{
+ margin-bottom:1.8em;
+ list-style:decimal inside;
+}
+ol li{
+ font-size:1.2em;
+ line-height:1.5em;
+}
6 test/fixtures/flexifield_def_entries.yml
View
@@ -3,10 +3,12 @@ ffde1:
flexifield_def_id: 1
flexifield_name: ffs_01
flexifield_alias: excerpt
- ordering: 1
+ flexifield_tooltip: Enter excerpt
+ flexifield_order: 1
ffde2:
flexifield_def_id: 1
flexifield_name: ffs_02
flexifield_alias: references
- ordering: 2
+ flexifield_tooltip: Enter references
+ flexifield_order: 2
34 test/has_flexible_fields_test.rb
View
@@ -2,16 +2,18 @@
class HasFlexibleFieldsTest < ActiveSupport::TestCase
fixtures :flexifield_defs, :flexifield_def_entries
-
+
#this is so the test rig can have :memory: or file db and self.use_transactional_fixtures = true or false
def get_post assign_def = false
if Post.count > 0
returning Post.last do |post|
- post.assign_ff_def FlexifieldDef.first.id if assign_def
+ post.ff_def= FlexifieldDef.first.id if assign_def
+ yield post if block_given?
end
else
returning Post.create!(:title => 'title1', :body => 'body1') do |post|
- post.assign_ff_def FlexifieldDef.first.id if assign_def
+ post.ff_def= FlexifieldDef.first.id if assign_def
+ yield post if block_given?
end
end
end
@@ -25,8 +27,9 @@ def test_a_new_post_has_no_ff_def
def test_b_new_post_saves_def
post = get_post(true)
assert post.has_ff_def?
+ assert_equal FlexifieldDef.first.id, post.ff_def
end
-
+
def test_c_new_post_ff_aliases
post = get_post(true)
assert_equal ['excerpt','references'], post.ff_aliases
@@ -37,15 +40,34 @@ def test_d_new_post_ff_fields
assert_equal ['ffs_01','ffs_02'], post.ff_fields
end
- def test_c_new_post_to_ff_alias
+ def test_e_new_post_to_ff_alias
post = get_post(true)
assert_equal 'excerpt', post.to_ff_alias('ffs_01')
end
- def test_d_new_post_to_ff_field
+ def test_f_new_post_to_ff_field
post = get_post(true)
assert_equal 'ffs_02', post.to_ff_field('references')
end
+ def test_g_new_post_write_values
+ post = get_post(true)
+ assert post.assign_ff_values({:excerpt => 'Some text', :references => 'Some references'})
+ end
+
+ def test_h_new_post_read_value
+ post = get_post(true) do |p|
+ p.assign_ff_values({:excerpt => 'Some text', :references => 'Some references'})
+ end
+ assert_equal 'Some text', post.get_ff_value(:excerpt)
+ post.set_ff_value('references', "Other refs")
+ assert_equal 'Other refs', post.get_ff_value('references')
+ end
+
+ def test_i_def_entry
+ vcs = FlexifieldDefEntry.view_columns
+ assert_equal FlexifieldDefEntry::ViewColumn, vcs.first.class
+ assert_equal [], vcs.map(&:field) & [:id, :flexifield_def_id]
+ end
end
18 test/test_helper.rb
View
@@ -10,8 +10,12 @@
ENV['RAILS_ENV'] = 'test'
-require dir + '/../lib/has/flexible_fields'
-require dir + '/../init.rb'
+['/..','/../app/models','/fixtures','/db'].each do |lp|
+ $LOAD_PATH << File.expand_path( File.dirname(__FILE__) + lp )
+end
+
+require 'has/flexible_fields'
+require 'init'
#config = { 'test' => { 'adapter' => 'sqlite3', 'dbfile' => dir + '/db/has_flexible_fields.sqlite3.db' } }
config = { 'test' => { 'adapter' => 'sqlite3', 'database' => ':memory:' } }
@@ -20,9 +24,9 @@
ActiveRecord::Base.configurations = config
ActiveRecord::Base.establish_connection(config['test'])
-require dir + '/../lib/flexifield'
-require dir + '/../lib/flexifield_def'
-require dir + '/../lib/flexifield_def_entry'
+require 'flexifield'
+require 'flexifield_def'
+require 'flexifield_def_entry'
class ActiveSupport::TestCase #:nodoc:
include ActiveRecord::TestFixtures
@@ -32,7 +36,7 @@ class ActiveSupport::TestCase #:nodoc:
self.fixture_path = File.dirname(__FILE__) + '/fixtures/'
end
-require dir + '/fixtures/models.rb'
-require dir + '/db/schema.rb' unless Post.table_exists?
+require 'models.rb'
+require 'schema.rb' unless Post.table_exists?
Post.create_ff_tables!
Please sign in to comment.
Something went wrong with that request. Please try again.