Permalink
Browse files

Make Sinatra ERB integration work with Sequel subforms

Unfortunately, there's not a clean way to implement this inside
the Sinatra integration.
  • Loading branch information...
1 parent b42e409 commit 235623974a35195d0e4f485d64cfbf153c97f69f @jeremyevans committed May 1, 2012
Showing with 123 additions and 73 deletions.
  1. +1 −1 CHANGELOG
  2. +16 −1 lib/sequel/plugins/forme.rb
  3. +71 −0 spec/sequel_helper.rb
  4. +3 −71 spec/sequel_plugin_spec.rb
  5. +32 −0 spec/sinatra_integration_spec.rb
View
@@ -1,6 +1,6 @@
=== HEAD
-* Make the Sinatra integration work on templates other than ERB/Erubis (tkellen)
+* Make Sinatra ERB integration work with partials (jeremyevans)
* Add id attributes for association :as=>:radio or :as=>:checkbox fields (jeremyevans)
@@ -84,7 +84,7 @@ def subform(association, opts={}, &block)
options[:legend] = humanize(association)
end
end
- inputs(ins, options, &block)
+ _inputs(ins, options, &block)
else
yield
end
@@ -450,13 +450,28 @@ def standard_input(type)
end
end
+ # Helper module used for Sequel/Sinatra forms. Necessary for
+ # proper subform handling when using such forms with partials.
+ module SinatraSequelForm
+ # Capture the inside of the inputs, injecting it into the template
+ # if a block is given, or returning it as a string if not.
+ def subform(*, &block)
+ if block
+ capture(block){super}
+ else
+ capture{super}
+ end
+ end
+ end
+
module InstanceMethods
# Configure the +form+ with support for <tt>Sequel::Model</tt>
# specific code, such as support for nested attributes.
def forme_config(form)
form.extend(SequelForm)
form.nested_associations = []
form.namespaces = [model.send(:underscore, model.name)]
+ form.extend(SinatraSequelForm) if defined?(::Forme::Sinatra::Form) && form.is_a?(::Forme::Sinatra::Form)
end
# Return <tt>Forme::Input</tt> instance based on the given arguments.
View
@@ -0,0 +1,71 @@
+require 'rubygems'
+require 'sequel/no_core_ext'
+
+DB = Sequel.sqlite
+Sequel.default_timezone = :utc
+DB.create_table(:artists) do
+ primary_key :id
+ String :name
+end
+DB.create_table(:albums) do
+ primary_key :id
+ foreign_key :artist_id, :artists
+ String :name
+ TrueClass :gold
+ TrueClass :platinum, :null=>false, :default=>false
+ Date :release_date
+ DateTime :created_at
+ Integer :copies_sold
+end
+DB.create_table(:album_infos) do
+ primary_key :id
+ foreign_key :album_id, :albums
+ String :info
+end
+DB.create_table(:tracks) do
+ primary_key :id
+ foreign_key :album_id, :albums
+ String :name
+end
+DB.create_table(:tags) do
+ primary_key :id
+ String :name
+end
+DB.create_table(:albums_tags) do
+ foreign_key :album_id, :albums
+ foreign_key :tag_id, :tags
+end
+
+a = DB[:artists].insert(:name=>'a')
+d = DB[:artists].insert(:name=>'d')
+b = DB[:albums].insert(:name=>'b', :artist_id=>a, :gold=>false, :release_date=>Date.new(2011, 6, 5), :created_at=>Date.new(2011, 6, 5), :copies_sold=>10)
+DB[:tracks].insert(:name=>'m', :album_id=>b)
+DB[:tracks].insert(:name=>'n', :album_id=>b)
+c = DB[:albums].insert(:name=>'c', :artist_id=>d, :gold=>true, :platinum=>true)
+DB[:tracks].insert(:name=>'o', :album_id=>c)
+s = DB[:tags].insert(:name=>'s')
+t = DB[:tags].insert(:name=>'t')
+u = DB[:tags].insert(:name=>'u')
+[[b, s], [b, t], [c, t]].each{|k, v| DB[:albums_tags].insert(k, v)}
+
+Sequel::Model.plugin :forme
+class Album < Sequel::Model
+ many_to_one :artist, :order=>:name
+ one_to_one :album_info
+ one_to_many :tracks
+ many_to_many :tags
+
+ def artist_name
+ artist.name if artist
+ end
+end
+class Artist < Sequel::Model
+ one_to_many :albums
+ def idname() "#{id}#{name}" end
+ def name2() "#{name}2" end
+ def name3() "#{name}3" end
+end
+class Track < Sequel::Model; end
+class Tag < Sequel::Model; end
+class AlbumInfo < Sequel::Model; end
+
View
@@ -1,79 +1,11 @@
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
-
-require 'rubygems'
-require 'sequel/no_core_ext'
-
-DB = Sequel.sqlite
-Sequel.default_timezone = :utc
-DB.create_table(:artists) do
- primary_key :id
- String :name
-end
-DB.create_table(:albums) do
- primary_key :id
- foreign_key :artist_id, :artists
- String :name
- TrueClass :gold
- TrueClass :platinum, :null=>false, :default=>false
- Date :release_date
- DateTime :created_at
- Integer :copies_sold
-end
-DB.create_table(:album_infos) do
- primary_key :id
- foreign_key :album_id, :albums
- String :info
-end
-DB.create_table(:tracks) do
- primary_key :id
- foreign_key :album_id, :albums
- String :name
-end
-DB.create_table(:tags) do
- primary_key :id
- String :name
-end
-DB.create_table(:albums_tags) do
- foreign_key :album_id, :albums
- foreign_key :tag_id, :tags
-end
-
-a = DB[:artists].insert(:name=>'a')
-d = DB[:artists].insert(:name=>'d')
-b = DB[:albums].insert(:name=>'b', :artist_id=>a, :gold=>false, :release_date=>Date.new(2011, 6, 5), :created_at=>Date.new(2011, 6, 5), :copies_sold=>10)
-DB[:tracks].insert(:name=>'m', :album_id=>b)
-DB[:tracks].insert(:name=>'n', :album_id=>b)
-c = DB[:albums].insert(:name=>'c', :artist_id=>d, :gold=>true, :platinum=>true)
-DB[:tracks].insert(:name=>'o', :album_id=>c)
-s = DB[:tags].insert(:name=>'s')
-t = DB[:tags].insert(:name=>'t')
-u = DB[:tags].insert(:name=>'u')
-[[b, s], [b, t], [c, t]].each{|k, v| DB[:albums_tags].insert(k, v)}
-
-Sequel::Model.plugin :forme
-class Album < Sequel::Model
- many_to_one :artist, :order=>:name
- one_to_one :album_info
- one_to_many :tracks
- many_to_many :tags
-
- def artist_name
- artist.name if artist
- end
-end
-class Artist < Sequel::Model
- one_to_many :albums
- def idname() "#{id}#{name}" end
-end
-class Track < Sequel::Model; end
-class Tag < Sequel::Model; end
-class AlbumInfo < Sequel::Model; end
+require File.join(File.dirname(File.expand_path(__FILE__)), 'sequel_helper.rb')
describe "Forme Sequel::Model forms" do
before do
- @ab = Album[b]
+ @ab = Album[1]
@b = Forme::Form.new(@ab)
- @ac = Album[c]
+ @ac = Album[2]
@c = Forme::Form.new(@ac)
end
@@ -1,4 +1,5 @@
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
+require File.join(File.dirname(File.expand_path(__FILE__)), 'sequel_helper.rb')
require 'rubygems'
require 'sinatra/base'
@@ -59,6 +60,33 @@ class FormeSinatraTest < Sinatra::Base
END
end
+ get '/nest_seq' do
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
+ @nest = <<END
+ n1
+ <% f.subform(:artist) do %>
+ n2
+ <%= f.input(:name2) %>
+ n3
+ <% end %>
+ n4
+ <%= f.subform(:artist, :inputs=>[:name3], :legend=>'Bar') %>
+ n5
+END
+ erb <<END
+0
+<% form(@album, :action=>'/baz') do |f| %>
+ 1
+ <%= f.subform(:artist, :inputs=>[:name], :legend=>'Foo') %>
+ 2
+ <%= erb(@nest, :locals=>{:f=>f}) %>
+ 3
+<% end %>
+4
+END
+ end
+
get '/hash' do
erb "<% form({:action=>'/baz'}, :obj=>[:foo]) do |f| %> <%= f.input(:first) %> <% end %>"
end
@@ -108,6 +136,10 @@ def o.puts(*) end
sin_get('/nest_sep').should == "0 <form action=\"/baz\"> 1 <p>FBB</p> 2 n1 <div> n2 <input id=\"first\" name=\"first\" type=\"text\" value=\"foo\"/> <input id=\"last\" name=\"last\" type=\"text\" value=\"bar\"/> n3 </div> n4 <fieldset class=\"inputs\"><legend>Foo</legend><input id=\"first\" name=\"first\" type=\"text\" value=\"foo\"/><input id=\"last\" name=\"last\" type=\"text\" value=\"bar\"/></fieldset> n5 3 </form>4"
end
+ specify "#form should correctly handle situation Sequel integration with subforms where multiple templates are used with same form object" do
+ sin_get('/nest_seq').should == "0 <form action=\"/baz\" class=\"forme album\" method=\"post\"> 1 <input id=\"album_artist_attributes_id\" name=\"album[artist_attributes][id]\" type=\"hidden\" value=\"2\"/><fieldset class=\"inputs\"><legend>Foo</legend><label>Name: <input id=\"album_artist_attributes_name\" name=\"album[artist_attributes][name]\" type=\"text\" value=\"A\"/></label></fieldset> 2 n1 <input id=\"album_artist_attributes_id\" name=\"album[artist_attributes][id]\" type=\"hidden\" value=\"2\"/> n2 <label>Name2: <input id=\"album_artist_attributes_name2\" name=\"album[artist_attributes][name2]\" type=\"text\" value=\"A2\"/></label> n3 n4 <input id=\"album_artist_attributes_id\" name=\"album[artist_attributes][id]\" type=\"hidden\" value=\"2\"/><fieldset class=\"inputs\"><legend>Bar</legend><label>Name3: <input id=\"album_artist_attributes_name3\" name=\"album[artist_attributes][name3]\" type=\"text\" value=\"A3\"/></label></fieldset> n5 3 </form>4"
+ end
+
specify "#form should accept two hashes instead of requiring obj as first argument" do
sin_get('/hash').should == '<form action="/baz"> <input id="first" name="first" type="text" value="foo"/> </form>'
end

0 comments on commit 2356239

Please sign in to comment.