Rails3 form partial reuse - ruby-on-rails

The following is the Rails std form that works.
<div id="content-form">
<%= form_for #passion, url: passion_path do |f| %>
<%#= render :partial => "form", :f => f %>
<div class="alternate">
<%= f.label "Status" %>
<%= f.text_field :status %>
</div>
<% end %>
</div>
Now I extract the partial to _form.html.erb with the following:
<div class="alternate">
<%= f.label "Status" %>
<%= f.text_field :status %>
</div>
And update the form as:
<div id="content-form">
<%= form_for #passion, url: passion_path do |f| %>
<%= render :partial => "form", :f => f %>
<% end %>
</div>
But now this throws an error complaining about the f variable.
undefined local variable or method `f' for #<#<Class:0x0000012d51d3e8>:0x0000012d796ef8>
Extracted source (around line #2):
1: <div class="alternate">
2: <%= f.label "Status" %>
3: <%= f.text_field :status %>
4: </div>
Why is this? Its pretty Rails basic.
One thing to consider that the resource #passion is singular. i.e. resource :passion (user has_one passion)
Due to that, I've to use explicit url: passion_path in the form_for ....
Btw, using Rails 3.2.9

try this
<div id="content-form">
<%= form_for #passion, url: passion_path do |f| %>
<%= render :partial => "form", :locals=>{:f => f } %>
<% end %>
</div>

You are using the :partial option, which means you have to pass local variables in with :locals:
<%= render :partial => "form", :locals => { :f => f } %>
The less verbose option is:
<%= render "form", :f => f %>

Related

Rails: How to pass a url path to a form_for partial in Rails?

I'm trying to pass a url and variable to a form partial in Rails.
Method #1:
This works, but I'd rather not hardcode post_create_path into the form, so that it can be used for #update as well.
new.html.erb
<%= render partial: 'shared/form', locals: { form: #form } %>
_form.html.erb
<%= form_for form, url: post_create_path do |f| %>
...
<% end %>
Method #2:
This does not work.
new.html.erb
<%= render partial: 'shared/form', locals: { form: #form, url: post_create_path } %>
_form.html.erb
<%= form_for form, url: url do |f| %>
...
<% end %>
Error:
undefined local variable or method `url' for #<#:0x007f8d4d831fd0>
What I've also tried:
Just url instead of url:url but getting the same error.
Following this thread: How to pass url to partial/form?
I've been trying to make this work for a couple hours now and feel like I'm running out of options to try. Any help in pointing out what I'm doing wrong would be super appreciated!
you can use different actions by opening form_for on edit and new view templates and then pass the form object to the partial which contains all the fields of the form that are common to both create and update
new.html.erb
<%= form_for #post, :url => { :action => "create" } do |form| %>
<%= render partial: 'shared/form', locals: { f: form } %>
edit.html.erb
<%= form_for #post, :url => { :action => "update" } do |form| %>
<%= render partial: 'shared/form', locals: { f: form } %>
shared/_form.html.erb
<%= f.text_field :title %>
...
<%= f.submit "Save" %>
<% end %>
Use the locals hash as a form_for argument:
# new.html.erb
<%= render partial: 'shared/form', form: #form, locals: { url: post_create_path, method: :post} %>
# edit.html.erb
<%= render partial: 'shared/form', form: #form, locals: { url: post_update_path, method: :put} %>
# _form.html.erb
<%= form_for form, locals do |f| %>
...
<% end %>
locals is just a hash and you can give it any name (like vars). Then use it consistently in the views and the form.
I had the same challenge when working on a Rails application with namespaced routes, but sa77's answer helped me.
Just to add to it.
My routes file is like this:
Rails.application.routes.draw do
namespace :users do
resources :students
end
end
So my new.html.erb was modified like this:
<h1>New User</h1>
<%= form_with(model: #user, url: users_students_path, local: true) do |form| %>
<%= render partial: 'form', user: #user, locals: { form: form } %>
<% end %>
<%= link_to 'Back', users_students_path %>
And my edit.html.erb was modified like this:
<h1>Editing User</h1>
<%= form_with(model: #user, url: users_student_path(#user), local: true) do |form| %>
<%= render partial: 'form', user: #user, locals: { form: form } %>
<% end %>
<%= link_to 'Show', users_student_path %> |
<%= link_to 'Back', users_students_path %>
And then my _form.html.erb file was modified like this:
<div class="field">
<%= form.label :email %>
<%= form.text_field :email %>
</div>
<div class="field">
<%= form.label :password %>
<%= form.text_field :password %>
</div>
<div class="actions">
<%= form.submit %>
</div>
That's all.
I hope this helps

Rails 4 partial with form not rendering

I have partial file _form.erb.html:
<p>Name: </p><%= f.text_field :name %>
<p>Description: </p><%= f.text_field :description %>
<p>Price: </p><%= f.text_field :price %>
<p>Weight: </p><%= f.text_field :weight %>
and view file items/new.html.erb:
<h1>New item</h1>
<%= form_for #item do |f| %>
<% render partial: 'form', locals: { :f => f} %>
<p><%= f.submit 'Create' %></p>
<% end %>
But, when I go to the 0.0.0.0:3000/items/new I see a page without a form and no errors displayed. What I'm doing wrong?
You are missing the =. It should be <%= render partial: 'form', locals: { :f => f} %>

NoMethodError in Browse#home

I have the following view file in browse/home
<% if current_user %>
<% #post = Post.new %>
<%=render :partial => 'posts/newpost.html.erb'%>
<div id="postsfeed">
<%= render :partial => 'post.html.erb', :locals => { :posts_streams => #posts_streams } %>
</div></br>
<% end %>
posts/newpost.html.erb is
<%= form_for(#post) do |f| %>
<div class="fields">
<%= f.label "Post" %><br />
<%= f.text_field :post %>
</div>
<div class="actions" id="refreshposts">
<%= f.submit("Post") %>
</div>
<% end %>
models/post.rb is as follows
class Post < ActiveRecord::Base
attr_accessible :post, :posted_by, :posted_by_uid
end
logs:
Rendered browse/home.html.erb within layouts/application (42.9ms)
Completed 500 Internal Server Error in 72ms
ActionView::Template::Error (undefined method `post' for #<Post:0x00000003ad7cf0>):
1: <%= form_for(#post) do |f| %>
2: <div class="fields">
3: <%= f.label "Post" %><br />
4: <%= f.text_field :post %>
5: </div>
6: <div class="actions" id="refreshposts">
7: <%= f.submit("Post") %>
app/views/posts/_newpost.html.erb:4:in `block in _app_views_posts__newpost_html_erb__281623928071728826_30583780'
app/views/posts/_newpost.html.erb:1:in `_app_views_posts__newpost_html_erb__281623928071728826_30583780'
app/views/browse/home.html.erb:3:in `_app_views_browse_home_html_erb___3611275753955382446_40484320'
when I initiate the server. It returns NoMethodError in Browse#home. Please suggest a way to resolve this
Thank you
Probably, there should be a post column in posts table in database
Also following points should be noted as per [Rails standards](http://guides.rubyonrails.org/layouts_and_rendering.html#Using Partials):
Avoid to mention extension .html.erb, So change the code from:
<%= render :partial => 'posts/newpost.html.erb'%>
<%= render :partial => 'post.html.erb', :locals => { :posts_streams => #posts_streams } %>
to:
<%= render :partial => 'posts/newpost'%>
<%= render :partial => 'post', :locals => { :posts_streams => #posts_streams } %>
Also the partial begins with an underscore, so place partial in views folder as posts/_newpost.html.erb.
check your routes and add
resources posts
or to add partial take example your file is '_partial.html.erb'
<%= render controller/partial %>
template error is the error which tells you that there is no such page you are rendering to, so do check whether it exists to the same path or not.

partials inside a view undefined method errors

I am adding partials to a show view, but I am getting errors of undefined methods that are inside the partials that are being called. I use the partials in other places and it works fine. I think I need to define a local variable, but I am not sure which one
user/show.html.erb
<h2>Copy To Approve</h2>
<div id="basic_details" class="idea-show-columns">
<%= render :partial => "/ideas/idea_basic_show" %>
<%= render :partial => "/ideas/comments" %>
<%= render :partial => "/ideas/mockups"%>
</div>
<div id="copy_details" class="idea-show-columns">
<%= render :partial => "/ideas/copy_show" %>
</div>
partial: ideas/idea_basic_show.html.erb
<fieldset data-model="idea-basic" class="idea-edit">
<h2>Basic Idea Specs</h2>
<div data-attribute="product_sku" class="edit-field">
<%= label :sku, "Product SKU" %>
<%= f.text_field :sku %>
</div>
<div data-attribute="working_name" class="edit-field">
<%= label :working_name, "Working Name" %>
<%= f.text_field :working_name %>
</div>
<div data-attribute="priority" class="edit-field">
<%= f.label :priority, 'Priority Level' %>
<%= f.select :priority, Idea::PRIORITIES.collect{ |level, label| [label, level]} %>
</div>
<% if current_user.has_overlord_access? %>
<div data-attribute="overlord_id" class="edit-field">
<%= f.label :overlord_id, 'Sign Off' %>
<%= f.select :overlord_id, User.overlords.collect{|o| [o.full_name, o.id]},
:include_blank => true %>
</div>
<% end %>
<br data-clear="all" />
<div data-attribute="working_description" class="edit-field">
<%= label :working_description, "Working Description" %>
<%= f.text_area :working_description %>
</div>
</fieldset>
the errors I am getting in this partial specifically is :
undefined method `sku' for nil:NilClass
Like I said I think I need to define a local in my partial I just don't know the syntax
The locals syntax like this
<%= render :partial => "/ideas/copy_show", :locals => {:f => f} %>
now use f in your partial page

passing variable into partial

I have the following for and partial setup but i keep on getting an error, that the partial does not recognise the variable |builder|.
Form
<%= simple_form_for #firm do |f| %>
<%= f.fields_for :events do |builder| %>
<%= render 'event_fields', :builder => builder %>
<% end %>
<%= end %>
_events_fields partial
<fieldset>
<%= builder.input :name, :collection => ['Applications Open', 'Applications Close', 'Traineeship Starts'] %>
<%= builder.text_field :start_at, :class => 'datepicker' %>
<%= builder.hidden_field :all_day, :value => true %>
<%= link_to "remove", '#', class: "remove_fields" %>
any idea how i should be padding the variable across? or if in fact this is the correct way of doing it? It would be really helpful is someone could help me understand a little more about how and why you need to do this.
You need to tell it that it is a partial view and pass in a hash to the locals option. Like so:
<%= simple_form_for #firm do |f| %>
<%= f.fields_for :events do |builder| %>
<%= render partial: 'event_fields', locals: {builder: builder} %>
<% end %>
<% end %>
If you're using Ruby 1.8 then:
<%= simple_form_for #firm do |f| %>
<%= f.fields_for :events do |builder| %>
<%= render :partial => 'event_fields', :locals => { :builder => builder } %>
<% end %>
<% end %>
partial_name would be replace with actual partial name or partial name with directory name.
We would provide the data_object object to the partial, available under the local variable data_variable in the partial and is equivalent to:
<%= render partial: "partial_name", locals: { data_variable: data_object } %>

Resources