Display fields before dynamically adding with cocoon gem - ruby-on-rails

I have a form and i am using cocoon gem to add extra fields if the user requires. As it stands, its displays add educations link and then the fields appear, I would like to have the fields present in the form and then if required, users clicks add education link to render the fields. Other than that its all working fine, the models are all set up properly, but can't figure this out.
new.html.erb
<%= form_for #profile do |f| %>
<%= f.label :bio %>
<%= f.text_area :bio %>
<%= f.label :university %>
<%= f.text_field :university %> <br>
<%= f.label :course %>
<%= f.text_field :course %> <br>
<%= f.label :finishedDate %>
<%= f.text_field :finishedDate %> <br>
<div id="educations">
<%= f.fields_for :educations do |education| %>
<% render 'education_fields', f: education %>
<% end %>
<div class="links">
<%= link_to_add_association 'add education', f, :educations %>
</div>
</div>
<%= f.button :submit %>
<% end %>
_education_fields.html.erb
<div class="nested-fields">
<%= f.label :university %>
<%= f.text_field :university %> <br>
<%= f.label :course %>
<%= f.text_field :course %> <br>
<%= f.label :finishedDate %>
<%= f.text_field :finishedDate %> <br>
<%= link_to_remove_association "remove education", f %>
</div>
profiles_controller.rb
class ProfilesController < ApplicationController
def index
#profiles = Profile.all
end
def new
#profile = Profile.new
#profile = educations.build
end
def create
#profile = Profile.create(profile_params)
redirect_to profiles_path
end
def show
#profile = Profile.find(params[:id])
end
def edit
#profile = Profile.find(params[:id])
end
def update
#profile = Profile.find(params[:id])
#profile.update(profile_params)
redirect_to(profiles_path(#profile))
end
private
def profile_params
params.require(:profile).permit(:bio, educations_attributes:[:id, :university, :course, :finishedDate, :destroy])
end
end

The form shows a profile, with all it's existing educations. So if you want to show the fields for an education by default, add an education before rendering the form.
So, in your controller, where you do something like
#profile = Profile.new
you can build an initial education so it will show up in the form:
#profile = Profile.new
#profile.educations.build

Related

has_many join form with collection checkboxes not saving more than one checkbox value

I am working on a form for a editorial calendar app. I have two things going out that are pretty similar and not working.
Working with 3 models: Platforms, Posts and Calendars. They are join tables. Platform <=> Post, Post <=> Calendars
Post/new & Post/edit form:
<div class="container">
<div class="form-field">
<%= form_for #post do |f| %>
<%= f.label :title %>
<%= f.text_field :title, required: true %> <br>
Title is required.
</div>
<div class="form-field">
<%= f.label :content%>
<%= f.text_area :content%>
</div>
<div class="form-field">
<%= f.label :link %>
<%= f.text_field :link %>
</div>
<div class="file-field">
<%= f.label :picture%>
<%= f.file_field :picture, id: :post_picture%>
</div>
<div class="file-field">
<%= f.label :finalized %>
<%= f.radio_button :finalized , true%>
<%= f.label :finalized, "Yes" %>
<%= f.radio_button :finalized, false %>
<%= f.label :finalized, "No" %>
</div>
<%= f.hidden_field :user_id %> <br>
<div class="form-field">
<%= f.fields_for :platform_attributes do |platform| %>
<%= platform.label :platform, "Social Platforms"%>
<%= platform.collection_check_boxes :platform_ids, Platform.all, :id, :name %> <br> <br>
</div>
<div>
<h4> Or Create a new platform: </h4>
<%= platform.label :platform, 'New Platform'%>
<%= platform.text_field :name%> <br> <br>
</div>
<% end %>
<%= f.submit%>
<% end %>
</div>
My post controller is handling the checkboxes issue, and the "schedule post" issue. It will only allow me to schedule for one calendar, and it does not save the updates and add additional calendars.
Posts Controller:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :schedule_post, :destroy]
def new
#posts = current_user.posts.select {|p| p.persisted?}
#post = current_user.posts.build
#platforms = Platform.all
end
def edit
#calendars = current_user.calendars
#platforms = Platform.all
end
def create
#post = current_user.posts.build(post_params)
if #post.save
redirect_to post_path(#post)
else
redirect_to new_post_path
end
end
def update
#post.update(post_params)
if #post.save
redirect_to post_path(#post), notice: 'Your post has been updated.'
else
redirect_to edit_post_path(#post)
end
end
def schedule_post
#calendar_post = CalendarPost.new(calendar_post_params)
if #calendar_post.save
binding.pry
redirect_to post_path(#post)
else
render 'show'
end
end
private
def set_post
#post = Post.find(params[:id])
end
def set_calendars
#calendars = current_user.calendars
end
def post_params
params.require(:post).permit(:title, :content, :link, :finalized, :picture, :user_id, :platform_attributes => [:platform_ids, :name])
end
def calendar_post_params
params.require(:calendar_post).permit(:post_id, :calendar_id, :date, :time)
end
end
I want the user to be able to add a post to multiple platforms and multiple calendars because of the versatility of what someone may need.
I also have my setter in my Post model.
class Post < ApplicationRecord
has_many :calendar_posts
has_many :calendars, through: :calendar_posts
has_many :platform_posts
has_many :platforms, through: :platform_posts
belongs_to :user
def platform_attributes=(platform_attributes)
if platform_attributes['platform_ids']
platform_attributes.platform_ids.each do |id|
platform = Platform.find(id: id)
self.platforms << platform
end
end
if platform_attributes['name'] != ""
platform = Platform.find_or_create_by(name: platform_attributes['name'])
self.platforms << platform
end
end
thoughts? why are they not saving to more than one calendar or more than one platform if they choose to have more than one?
Here is the updated code... and more of what I know about these changes and what is happening.
My submit button is not working for some odd reason on my form, so I'm trying to get the params submitted but it won't even route to give me params even if I raise them, nothing is happening.
On the form you can choose checkboxes or add in a platform. If you add in a platform it creates that one but it does not also save the other ones you selected. If you go to edit the post, and click submit with changes, no page loads at all and nothing is happening in log. It's just idle.
<%= f.fields_for :platform_attributes do |platform| %>
assumes you are creating one platform... it says "these are the fields for this platform"
but platform_ids is intended to be a selection of a set of platforms... and probably should be outside of the fields_for section (which should only surround the name field).
try something like the following:
<div class="form-field">
<%= f.label :platform_ids, "Social Platforms"%>
<%= f.collection_check_boxes :platform_ids, Platform.all, :id, :name %> <br> <br>
</div>
<div>
<%= f.fields_for :platform_attributes do |platform| %>
<h4> Or Create a new platform: </h4>
<%= platform.label :name, 'New Platform'%>
<%= platform.text_field :name%> <br> <br>
<% end %>
<%# end fields_for %>
</div>
Also you'll need to update permit/require appropriately eg
def post_params
params.require(:post).permit(:title, :content, :link, :finalized, :picture, :user_id, :platform_ids, :platform_attributes => [:name])
end
Note: not tested - bugs are left as an exercise for the reader ;)

rails 4 - param is missing or the value is empty: projecttype

A newby to rails (I am building an app to learn rails) and run in to an issue I can't find a solution to (while following the getting started guide). I have studied the guides and similar questions
This is my code:
class ProjecttypesController < ApplicationController
def index
#projecttypes = Projecttype.all
end
def show
#projecttype = Projecttype.find(params[:id])
end
def new
end
def create
#projecttype = Projecttype.new(projecttype_params)
#projecttype.save
redirect_to #projecttype
end
private
def projecttype_params
params.require(:projecttype).permit(:name, :image, :url)
end
end
The form:
<%= form_for :projecttypes, url: projecttypes_path do |f| %>
<p>
<%= f.label 'Project type' %>
<%= f.text_field :projecttype %>
</p>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :image %>
<%= f.file_field :image %>
</p>
<p>
<%= f.label :url %>
<%= f.url_field :url %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
What am I doing wrong?
Perhaps important... when I use this...
def create
render plain: params[:projecttype].inspect
end
It returns 'nil'.
Thanks for your help
Your code should be like this
def new
#projecttype = Projecttype.new
end
def create
#projecttype = Projecttype.create(projecttype_params)
redirect_to #projecttype
end
and use this for form
<%= form_for #projecttype do |f| %>
In your
controller file
def new
#projecttype = Projecttype.new
end
and then in your form
<%= form_for #projecttype do |f| %>

How do i make one form for two related models?

I want to write data for 2 different models that are related to each other like this:
class Post < ActiveRecord::Base
has_many :roads
accepts_nested_attributes_for :roads, :allow_destroy => true
end
class Road < ActiveRecord::Base
belongs_to :post
end
Of course de roads table has a "post_id column". My form_for in the post view looks like this
<%= form_for #post do |f| %>
<div class="form-group">
<%= f.label :Tu_Nombre %>
<%= f.text_field :creador, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :año %> (Cuando fue tu experiencia?)
<%= f.text_field :año, class: "form-control" %>
</div>
<div class="form-group">
<%= fields_for :roads do |r| %>
<%= r.label :principio %> (desde?)
<%= r.text_field :principio, class: "form-control" %>
<%= r.label :final %> (hasta?)
<%= r.text_field :final, class: "form-control" %>
<% end %>
</div>
<div class="form-group">
<%= f.label :historia %> (Cuentanos la historia de tu viaje!)
<%= f.text_area :historia, class: "form-control", size: "50x15" %>
</div>
<div>
<%= f.submit class: "btn btn-success" %>
</div>
<% end %>
Finally my posts_controller create method
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post, notice: 'Post was successfully created.'
else
render :new
end
end
with the private
def post_params
params.require(:post).permit(:historia, roads_attributes: [:pricipio, :final, :post_id])
end
The post is submitted and if i check the console all the atributes for post has been saved but the ones for road, has not. How can i use just one form two make records for these two models and that the post_id gets registered so i can relate the tables?
Thanks a lot!!
Update your posts_controller new method to include .build
def new
#post = Post.new
#post.roads.build
end
Please read the Nested Forms in Form Helpers chapter of Rails Guide. You could use fields_for to build the nested attributes form for your roads and permit nested attributes like the example. Below is an example from rails guide, you could try and figure it out yourself.
_form.html.erb
<%= form_for #person do |f| %>
Addresses:
<ul>
<%= f.fields_for :addresses do |addresses_form| %>
<li>
<%= addresses_form.label :kind %>
<%= addresses_form.text_field :kind %>
<%= addresses_form.label :street %>
<%= addresses_form.text_field :street %>
...
</li>
<% end %>
</ul>
<% end %>
permit nested attributes in people_controller.rb
def person_params
params.require(:person).permit(:name, addresses_attributes: [:id, :kind, :street])
end
Attach your fields_for to the parent form builder like so:
<%= f.fields_for :roads do |r| %>

Accessing Model ID inside of rails form helper

First off I'm new to rails, I have a join table Menus_orders which I'm trying to load ID's into on create.
I have this form helper which has access to Order.new(:id, :name) fields and fields_for Menus_order(:menu_id, :order_id). I can insert the menu_id from a select but I can't for the life of me figure out how to populate a hidden input with the current order_id which the form holds in #order.
look at ORDER_ID HERE
<div class="form">
<h1>Create a new order</h1>
<%= form_for #order do |f| %>
<%= f.label :name%><br>
<%= f.text_field :name%><br>
<h3>Select meals</h3>
<%= fields_for(#menus_order) do |i| %>
<div class="field">
<%= i.select :menu_id, options_for_select(Menu.all.pluck(:id)) %>
<%= i.hidden_field :order_id, :value => ORDER_ID HERE %>
</div>
<% end %>
<br>
<%= f.submit "Create"%><br>
<% end %>
</div>
Thanks, DW
You should use nested attributes for order model just apply
the conventions right & it will be handled, you can achieve this by
following example :
order.rb should be like :
class Order < ActiveRecord::Base
has_many :menu_orders
accepts_nested_attributes_for :menu_orders
end
menu_order.rb be like :
class MenuOrder < ActiveRecord::Base
belongs_to :order
end
orders/new.html
<div class="form">
<h1>Create a new order</h1>
<%= form_for #order do |f| %>
<%= f.label :name%><br>
<%= f.text_field :name%><br>
<h3>Select meals</h3>
<%= f.fields_for :menu_orders do |i| %>
<div class="field">
<%= i.select :menu_id, options_for_select(Menu.all.pluck(:id)) %>
</div>
<% end %>
<br>
<%= f.submit "Create"%><br>
<% end %>
</div>
OrdersController
class OrdersController < ApplicationController
def new
#order = Order.new
#order.menu_orders.build
end
def create
#order = Order.new(order_params)
if #order.save
redirect_to orders_path
flash[:success] = "Order created"
else
render 'new'
end
end
private
def order_params
params.require(:order).permit(:name, menu_orders_attributes: [ :menu_id, :order_id ])
end
end

params.require().permit does not work as expected

I have this controller
class PeopleController < ApplicationController
def new
#person = Person.new
#person.phones.new
end
# this is the action that gets called by the form
def create
render text: person_params.inspect
# #person = Person.new(person_params)
# #person.save
# redirect_to people_path
end
def index
#person = Person.all
end
private
def person_params
params.require(:person).permit(:name, phones_attributes: [ :id, :phone_number ])
end
end
and this view
<%= form_for :person, url: people_path do |f| %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<%= f.fields_for :phones do |f_phone| %>
<div class="field">
<p>
<%= f_phone.label :phone_number %><br />
<%= f_phone.text_field :phone_number %>
</p>
</div>
<% end %>
<p>
<%= f.submit %>
</p>
<% end %>
When I fill out both form fields and hit "Save Person" I only get {"name"=>"foo"} - the phone number seems to vanish.
However, when I change phones_attributes to phones I get {"name"=>"foo", "phones"=>{"phone_number"=>"123"}} (this would however cause problems with the create function.
What's wrong here?
Please note that this question is strongly related to that one: accepts_nested_attributes_for: What am I doing wrong as well as to this posting: https://groups.google.com/forum/#!topic/rubyonrails-talk/4RF_CFChua0
You don't have #phones defined in the controller:
def new
#person = Person.new
#phones = #person.phones.new
end
Finally found the problem. In the view there should be
<%= form_for #person, url: people_path do |f| %>
Instead of
<%= form_for :person, url: people_path do |f| %>
#phron said that already here:
accepts_nested_attributes_for: What am I doing wrong

Resources