I have made an application that has a personsController class, with an action show and new. I also created the Person model this way:
rails generate model Person name:string surname:string partner:references
The partner field should reference another person. In the new action I created a form to insert a new person into the database:
<%= form_for :person , url: persons_path do |f| %>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :surname %>
<%= f.text_field :surname %>
</p>
<p>
<%= f.label :partner %>
<%= f.number_field :partner , value: 0 %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
This is the personsController method create:
def create
#person= Person.new(post_params)
#Person.save
redirect_to #person
private
def post_params
params.require(:post).permit(:partner,:name,:surname);
end
The problem is that I get an error when I submit the form:
Update
I changed the instruction to:
params.require(:person).permit(:partner,:name,:surname);
But I still get an error:
NameError in PersonsController#create
uninitialized constant Person::Partner
Person model:
class Person < ActiveRecord::Base
belongs_to :partner
end
This is the problem here:
From your model post is not a defined attribute
so changed this:
def post_params
params.require(:post).permit(:partner,:name,:surname);
end
to
def post_params
params.require(:person).permit(:partner_id,:name,:surname)
end
EDIT
use partner_id instead of partner for your foreign key
<p>
<%= f.label :partner %>
<%= f.number_field :partner_id, value: 0 %>
</p>
Require person:
params.require(:person).permit(:partner, :name, :surname)
Related
I have the following models:
class Person < ApplicationRecord
has_many :interests, dependent: :destroy
accepts_nested_attributes_for :interests
validates_presence_of :email
validates_inclusion_of :gender, :in => %w(M F), message: "Gender can only be in M or F"
has_secure_password
def name
"#{first_name} #{last_name}"
end
def interests_concatenated
interests.map { |i| i.interest }.join(", ")
end
end
class Interest < ApplicationRecord
belongs_to :person
end
My controller is as follows:
class PeopleController < ApplicationController
def index
#person = Person.all
end
def new
#person = Person.new
#person.interests.build
end
def create
#person = Person.new(people_params)
if #person.save
session[:user_id] = #person.id
redirect_to(people_path)
else
flash = "Email or gender can't be blank!"
render 'new'
end
end
private
def people_params
params.require(:person).permit(:email, :first_name, :last_name, :gender, :password,:password_confirmation, interests_attributes: [:hobby])
end
end
My form is as follows:
<%= form_for #person do |f| %>
<p>
<%= f.label :email %> <br>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :first_name %> <br>
<%= f.text_field :first_name %>
</p>
<p>
<%= f.label :last_name %> <br>
<%= f.text_field :last_name %>
</p>
<p>
<%= f.label :gender %> <br>
<%= f.label(:gender_male, "Male") %>
<%= f.radio_button(:gender, "M") %> <br>
<%= f.label(:gender_female, "Female") %>
<%= f.radio_button(:gender, "F") %> <br>
</p>
<p>
<%= f.label :password %> <br>
<%= f.password_field :password %>
</p>
<p>
<%= f.label :password_confirmation %> <br>
<%= f.password_field :password_confirmation %>
</p>
<p>
<%= f.fields_for :interests do |i| %>
<%= i.label :hobby %>
<%= i.text_field :hobby %>
<% end %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
Here is the byebug console log when I run it:
Very stumped why it's not working. Could it be something to do with the parameters?
Here is the log file when I submit the form:
Instead of:
#interests = #person.interests.new
try
#interests = #person.interests.build
new creates a fresh, clean, completely empty new object... but build is the special Rails association method that will fill it with appropriate defaults (like, eg the right person_id)
I found a working solution by adding this in my interests model:
class Interest < ApplicationRecord
belongs_to :person, **optional: true**
end
Since #person fails to save each time, the biggest clue was in the error message "Interest person must exist", I found this StackOverflow solution to be helpful. Also this blog post on why this is needed was helpful in shedding light on the issue.
Thanks to everyone that weighed in on it!
I am building ecommerce using Rails and I got stuck with this problem:
When I try to create a new item within some category from a browser, the created item doesn't get an id of the category.
http://localhost:3000/categories/1/items/new
In console I can verify that params get the category_id correctly:
Parameters: {"category_id"=>"1"}
After creating the item's category_id equals to nil.
Here's my Item model file:
class Item < ActiveRecord::Base
belongs_to :category
end
Category model:
class Category < ActiveRecord::Base
has_many :items
end
This is my items_controller.rb file where I pass category_id to the Item:
class ItemsController < ApplicationController
# other actions are ommited
def new
#item = Item.new
#item.category_id = params[:category_id]
end
end
Also you can look at the whole app in:
https://github.com/kaneru/estore
Thanks in advance.
Your views/items/_form.html.erb should look as follows:
<div class="row">
<div class="col-lg-4 col-md-offset-4">
<%= simple_form_for #item do |f| %>
<%= f.hidden_field :category_id,value: params[:category_id] %>
<%= f.input :title %>
<%= f.input :price %>
<%= f.input :color %>
<%= f.input :weight %>
<%= f.input :description, as: :text %>
<%= f.input :picture, as: :file %>
<%= f.button :submit, class: "btn btn-primary" %>
<% end %>
<br/>
<%= render "menu" %>
</div>
</div>
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
I have a model Event that has one Payoption, which is a STI model. Payoption could be BankPayoption, CashPayoption etc, each of them has totally different fields.
The models, Payoption just have string attributes:
class Event < ActiveRecord::Base
has_one :payoption
end
class Payoption < ActiveRecord::Base
belongs_to :event
end
class BankPayoption < Payoption
end
class CashPayoption < Payoption
end
Event controller:
class EventsController < ApplicationController
def new
end
def create
#event = Event.new(post_params)
#event.user_id = current_user.id
#event.save
redirect_to #event
end
private
def post_params
params.require(:event).permit(:title, :text, :code)
end
end
This is the new Event view:
<%= form_for :event, url: events_path do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.label :code %><br>
<%= f.text_field :code %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
This code works fine but it's obviously not creating a Payoption association, I'm not sure how to implement this in the current form_for. I want to be able to pick on of the Payoption types with a select element and then the correct fields should show. I know the field show/hide action is done by javascript but the real problem is, how do I make a nested form that creates the chosen subclass and associates that with the event object?
Thanks
very simple do it this way
class EventsController < ApplicationController
def new
#event = Event.new
#event.build_payoption
end
end
<%= form_for(#event) do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.label :code %><br>
<%= f.text_field :code %>
</p>
<%= f.fields_for :payoption do |p| %>
<%= p.label :payoption_type %>
<%= p.select(:payoption_type, Payoption::PAY_OPTION , {:prompt => "Select"}, {class: "payoption"}) %>
<% end %>
<p>
<%= f.submit %>
</p>
<% end %>
class Event < ActiveRecord::Base
has_one :payoption, dependent: :destroy
accepts_nested_attributes_for :payoption
end
class Payoption < ActiveRecord::Base
belongs_to :event
PAY_OPTION = ["option1", "option2", "option3"]
end
m assuming payoption_type is a field in your Payoption model
I have these two models
class Invoice < ActiveRecord::Base
has_many :items
accepts_nested_attributes_for :items
...
end
class Item < ActiveRecord::Base
belongs_to :invoice
def total
price * quantity
end
...
end
and this nested (!) form that posts to both models:
<h1>Add an Invoice</h1>
<%= form_for #invoice do |f| %>
<p>
<%= f.label :recipient %>
<%= f.text_field :recipient %> </p>
<p>
<%= f.label :date %>
<%= f.text_area :date %>
</p>
<h2>Items</h2>
<p>
<%= f.fields_for(:items) do |f| %>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.label :price %>
<%= f.text_field :price %>
<%= f.label :quantity %>
<%= f.text_field :quantity %>
<%= f.label :total %>
<%= f.total %><!-- this method call is not working! -->
<% end %>
</p>
<%= f.submit %>
<% end %>
How can I do calculations on my items within the form?
In my Items model I have this method:
def total
price * quantity
end
However, in the form I can't get it to work with f.total. I keep getting this error:
undefined method `total' for #<ActionView::Helpers::FormBuilder:0x10ec05558>
What am I missing here?
You are calling a method not on your model object, but on f, which is a form helper (ActionView::Helpers::FormBuilder). Error message gives a hint to this.
To call on the item, you need to replace
<%= f.total %>
with
<%= f.object.total %>