Comments (5)
From @dariocravero on September 9, 2014 16:32
@fgarcia I know it might be a bit confusing and that probably the whole form builders section needs to be redone. I'll get started using your example here :).
First of all, the form builder helpers expect the symbol you use to be either an instance variable available to the view or an object it can instantiate on the fly.
Having said that, you can still force the name of the field by using the as: :model
in fields_for
as in: fields_for :model, as: :model
.
Here's a sample app that should work with it:
# app/app.rb
module Issue1760
class App < Padrino::Application
register Padrino::Helpers
enable :sessions
get :index do
render :index
end
end
end
# app/views/index.slim
= form_for :model, '/some/specific/path' do |f|
= f.label :email
= f.text_field :email
#models/model.rb
class Model
end
It should render:
<form action="/form/posted" accept-charset="UTF-8" method="post">
<label for="model_email" value="">Email: </label>
<input type="text" name="model[email]" value="" id="model_email">
</form>
Notice how I've merged the usage of form_tag
and fields_for
in form_for
.
Now, let's jump into nested models/data structures. The issue you're facing there is that you're trying to use an association that doesn't exist or isn't explicitly declared. The helper is only trying to access model.inside
and inside
is undefined for your current model
object. Let's extend the app above to support associations:
# app/views/index.slim
= form_for :model, '/some/specific/path' do |f|
= f.label :email
= f.text_field :email
= f.fields_for :inside do |fi|
= fi.label :name
= fi.text_field :name
# models/model.rb
class Model
def inside
Inside.new
end
end
# models/inside.rb
class Inside
end
That would render something like:
<form action="/form/posted" accept-charset="UTF-8" method="post">
<label for="model_email" value="">Email: </label>
<input type="text" name="model[email]" value="" id="model_email">
<label for="model_inside_attributes_name" value="">Name: </label>
<input type="text" name="model[inside_attributes][name]" value="" id="model_inside_attributes_name">
</form>
That would be the case of a one to one association in a relational db. If you were to return an array of elements, it would then render as many as you return. So, say we modify `models/model.rb to look like this:
# models/model.rb
class Model
def inside
[Inside.new, Inside.new]
end
end
It should output:
<form action="/form/posted" accept-charset="UTF-8" method="post">
<label for="model_email" value="">Email: </label>
<input type="text" name="model[email]" value="" id="model_email">
<label for="model_inside_attributes_0_name" value="">Name: </label>
<input type="text" name="model[inside_attributes][0][name]" value="" id="model_inside_attributes_0_name">
<label for="model_inside_attributes_1_name" value="">Name: </label>
<input type="text" name="model[inside_attributes][1][name]" value="" id="model_inside_attributes_1_name">
</form>
If we were to add an ORM like, say Sequel, and name the models Parent
and Child
with a one parent to many children relationship, we would end up with something along the lines of:
# app/views/index.slim
= form_for :parent, url(:parents, :index) do |f|
= f.label :email
= f.text_field :email
= f.fields_for :children do |fi|
= fi.label :name
= fi.text_field :name
= f.submit
# app/controllers.rb
Issue1760::App.controllers :parents do
get :new do
@parent = Parent.new
@parent.children << Child.new
render :index
end
get :view, with: :id do
@parent = Parent[params[:id]]
render :index
end
post :index do
parent = Parent.create(email: params['parent']['email'])
params['parent']['children_attributes'].each do |i, child_data|
Child.create(parent_id: parent.id, name: child_data['name'])
end
redirect url(:parents, :view, parent.id)
end
end
# models/parent.rb
class Parent < Sequel::Model
one_to_many :children
end
# models/child.rb
class Child < Sequel::Model
many_to_one :parent
end
And that's kind of how the whole relations thing would go when you layered up to using ORM models together with the form builder.
Hope this helped clarify things a bit and if not, let me know and we'll look at it in more depth. Here's the demo app.
:)
from padrino-docs.
From @dariocravero on September 9, 2014 16:32
@padrino/core-members should we update the guides with something along the lines of this?
from padrino-docs.
From @fgarcia on September 9, 2014 17:0
That was more exhaustive than I expected! Thanks a lot
I downloaded your example, played with it and verified one thing... when you mentioned instantiate on the fly
we made different assumptions. Somewhere in the doc I also read that and thought about instantiate without a model
Your example uses form_for which I thought could achieve the result I wanted using a real model. Now it is so much clear!
However in my example I used form_tag because I wanted to use the helpers without an existing model. My assumption was that the helpers behaved like in Rails. I've just tested this quickly in Rails:
<%= form_tag do %>
Form contents
<%= text_field_tag(:outside) %>
<%= fields_for :model do |f| %>
<%= f.text_field(:inside) %>
<%= f.fields_for :again do |ff| %>
<%= ff.text_field(:deeper) %>
<% end %>
<% end %>
<% end %>
The last line is rendered as:
<input id="model_again_deeper" name="model[again][deeper]" type="text">
That was my expectation when combining fields_for with form_tag
It is my fault misunderstanding since I assumed that if fields_for could be used within form_tag an no prefixed model, then I expected that no model at all was required :-(
thanks for the lesson!
from padrino-docs.
From @dariocravero on September 9, 2014 17:31
I get your pain point and I agree that it should probably work without an explicit model too, e.g., what if you need to create a form for a service you don't manage in the same app but you know the structure of? Perhaps we could try to mimic that behaviour @padrino/core-members thoughts?
from padrino-docs.
From @halfdan on November 6, 2015 11:54
It'd also be great if it would allow to render an "Add" button that adds additional nested elements on the fly (in the DOM, using javascript).
from padrino-docs.
Related Issues (20)
- Issue with heroku part of Blog tutorial HOT 2
- New feature for mailer HOT 2
- Document how to mock out helper methods with rack-test
- How to localize your app suggests Padrino.before_load but app locales are not loaded yet HOT 4
- New example
- Add lumen example
- Blog Tutorial Improvements HOT 2
- Docs on caching are out of date HOT 4
- New example HOT 1
- Publish Updated Docs HOT 2
- Add new example page HOT 2
- Release notes for 0.14 version
- Update development commands
- sampleblog template is broken
- Awesome Padrino page
- Deployment section
- Document dev-docs for Padrino
- Prepare 0.14.2 release notes
- Video about Padrino at Ruby Kaigi 2015
- Get rid of "Asynchronous Concurrency" page
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from padrino-docs.