Accessing Model ID inside of rails form helper - ruby-on-rails

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

Related

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| %>

Display fields before dynamically adding with cocoon gem

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

ActionController “No explicit conversion of Symbol into Integer” for new record in Rails 4.2.1

I'm trying to create #booking and #booking.build_passenger in form_for with nested attributes in Rails 4.2.1
The error I get:
As you see in the console at the bottom of the image:
1. params.require(:booking) returns a Hash-like params for #booking
2. params.class returns ActionController::Parameters
As the params seems to behave correctly, IMO the problem hides somewhere in the form:
<%= form_for #booking do |f| %>
<%= f.hidden_field :flight_id, value: params[:flight_id] %>
<%= render 'flights/flight_info' %>
<div class="field">
<b><%= f.label :num_tickets, "Tickets" %></b>
<%= f.select(:num_tickets, #num_tickets) %>
</div><br>
<h4>Passenger info:</h4>
<%= f.fields_for #booking.build_passenger do |pass| %>
<div class="field">
<%= pass.label :name %>
<%= pass.text_field :name %>
</div>
<div class="field">
<%= pass.label :email %>
<%= pass.email_field :email %>
</div>
<% end %>
<%= f.submit 'Book Flight!' %>
<% end %>
Booking model:
class Booking < ActiveRecord::Base
belongs_to :flight
belongs_to :passenger
accepts_nested_attributes_for :passenger
end
Question: Where and how do I have to edit my code for the app to start creating #booking instances + #booking.build_passenger()
Your booking_params needs to be something like:
def booking_params
params.require(:booking).permit(:flight_id, :num_tickets, passenger_attributes: [:id, :name, :email])
end

undefined method `reviews' for nil:NilClass

I'm trying to create a reviews model for company pages. For this I have:
Models
user.rb
has_many :reviews
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :reviews
end
My reviews controller is:
def create
#company = Company.find_by_slug(params[:id])
#review = #company.reviews.create(params[:review])
#review.save
redirect_to company_path(#company)
end
and I have this code in the company show page:
<% #company.reviews.each do |review| %>
<p>
<strong>Title:</strong>
<%= review.title %>
</p>
<p>
<strong>Avantage:</strong>
<%= review.avantage %>
</p>
<p>
<strong>Inconvenient:</strong>
<%= review.inconvenient %>
</p>
<% end %>
</br>
<%= form_for([#company, #company.reviews.build]) do |f| %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :avantage %><br>
<%= f.text_area :avantage %>
</div>
<div class="field">
<%= f.label :inconvenient %><br>
<%= f.text_area :inconvenient %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
However, when I go to a specific company page and try to create a review for this company I'm getting this error message undefined method reviewsfor nil:NilClass
Instead of #company = Company.find_by_slug(params[:id]) use this code #company = Company.friendly.find(params[:company_id])
There are a couple of things you may find useful:
If you're using Rails 4, you may encounter a further problem. In the third line of your create method, you are using unsecure params directly in a .create call. Check out the Rails Guide page on "strong params".
If you implement strong parameters as mentioned above, you should probably deliberately omit the company_id field from the list of permitted params.
Assuming your users are allowed to write a review for any company in your system, it might be simpler for you to embed the company_id as a hidden field in your form. This would allow you to also simplify the controller method. For example:
# _form.html.erb
<%= form_for(#review) do |f| %>
<%= f.hidden_field :company_id, value: #company.id %>
...bla bla bla
<% end %>
Then, in your reviews_controller...
# reviews_controller.rb
def create
#review = Review.new(approved_params)
if #review.save
flash[:success] = 'Review created!'
else
flash[:error] = "Review wasn't saved"
end
#company = #review.company
redirect_to #company
end
def approved_params
params.require(:review).permit(:title, :avantage, :inconvenient, :company_id)
end
In your companies_controller, you should add this to your show method
# companies_controller.rb
def show
#company = Company.find(params[:id]
# add this line below...
#review = Review.new
end
I hope this helps.

Nested model form with collection in Rails 2.3

How can I make this work in Rails 2.3?
class Magazine < ActiveRecord::Base
has_many :magazinepages
end
class Magazinepage < ActiveRecord::Base
belongs_to :magazine
end
and then in the controller:
def new
#magazine = Magazine.new
#magazinepages = #magazine.magazinepages.build
end
and then the form:
<% form_for(#magazine) do |f| %>
<%= error_messages_for :magazine %>
<%= error_messages_for :magazinepages %>
<fieldset>
<legend><%= t('new_magazine') %></legend>
<p>
<%= f.label :title %>
<%= f.text_field :title %>
</p>
<fieldset>
<legend><%= t('new_magazine_pages') %>
<% f.fields_for :magazinepages do |p| %>
<p>
<%= p.label :name %>
<%= p.text_field :name %>
</p>
<p>
<%= p.file_field :filepath %>
</p>
<% end %>
</fieldset>
<p>
<%= f.submit :save %>
</p>
</fieldset>
<% end %>
problem is, if I want to submit a collection of magazinepages, activerecord complaints because it's expected a model and not an array.
create action:
def create
#magazine = Magazine.new params[:magazine]
#magazine.save ? redirect_to(#magazine) : render(:action => 'new')
end
In magazine:
accepts_nested_attributes_for :magazinepages
Magazine.new(params[:magazine]) will then handle the object hierarchy for you automatically
I'm not 100% sure what you're asking, but if you're trying to instantiate a new magazine, with many magazinepages, you'll need to iterate over each magazine page. Something like this:
def create
#magazine = Magazine.new(params[:magazine])
if params[:magazinepages]
params[:magazinepages].each do |page|
#magazine.magazinepages.build(page)
end
end
# Save the model, do your redirection or rendering invalid model etc
end

Resources