Rails 4.0 Nested forms / data not saved - ruby-on-rails

I have following code trying to create a new User with an associated new Shop resource. However, while the user data is saved correctly, no record for the shop is created. What is wrong?
Users controller:
class UsersController < ApplicationController
def new
#user = User.new
#user.shops.build
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "Signed up successfully."
redirect_to root_path
else
flash[:danger] = "Signup failed!"
render 'new'
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation,
shop_attributes: [:name])
end
end
User model:
class User < ActiveRecord::Base
has_many :shops
accepts_nested_attributes_for :shops
end
Shop model:
class Shop < ActiveRecord::Base
belongs_to :user
end
Form:
<%= form_for(#user) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.fields_for :shop do |shop| %>
<%= shop.label :name %>
<%= shop.text_field :name %>
<% end %>
<%= f.submit "Create my account" %>
<% end %>

Check your singular/plural wording (shop_attributes, f.fields_for :shop):
def user_params
params.require(:user).permit(:email, :password, :password_confirmation,
shops_attributes: [:name])
end
and:
<%= f.fields_for :shops do |shop| %>

Related

Cannot get a nested model to save in rails 5

I have a user which is a nested resource of account, and I'm trying to create the account and the user in 1 form. The account is saving correctly, however no user record is being written.
user.rb:
class User < ApplicationRecord
belongs_to :account
validates :email, presence: true
end
account.rb:
class Account < ApplicationRecord
has_many :users, :dependent => :destroy
accepts_nested_attributes_for :users
end
accounts_controller.rb:
class AccountsController < ApplicationController
def new
#account = Account.new
#user = #account.users.build
end
def create
#account = Account.new(account_params)
#account.secret = SecureRandom.uuid
if #account.save
flash[:success] = "You've successfully created your account, now it's time to create your first team."
redirect_to dashboard_path
else
flash[:danger] = "There was a problem creating your account"
redirect_to signup_path
end
end
private
def account_params
params.require(:account).permit(:name, user_attributes: [:first_name, :last_name, :email, :password, :password_confirmation, :secret])
end
end
accounts/new.html.erb:
<h1>Signup</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#account) do |form| %>
<%= form.label "Account name" %>
<%= form.text_field :name, class: "form-control" %>
<%= form.fields_for :user do | f| %>
<%= f.label :first_name %>
<%= f.text_field :first_name, class: "form-control" %>
<%= f.label :last_name %>
<%= f.text_field :last_name, class: "form-control" %>
<%= f.label :email %>
<%= f.text_field :email, class: "form-control" %>
<%= f.label :password %>
<%= f.password_field :password, class: "form-control" %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: "form-control" %>
<% end %>
<%= form.submit "Signup", class: "btn btn-primary" %>
<% end %>
</div>
</div>
When I submit the the form and check my logs, I'm seeing:
Processing by AccountsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"p5+CRICRp3ZilIg1NtehEQG7Gh2amnFFUD5NawtqkICJ4uRDvvJxf2WTbd7+rnfG9zdblT1QWgfJ62NNxcc2RA==", "account"=>{"name"=>"Streame", "user"=>{"first_name"=>"Jeremy", "last_name"=>"Kirkham", "email"=>"jeremy#streame.com.au", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}, "commit"=>"Signup"}
Unpermitted parameter: user
The answer was quite simple in the end - I needed to change the form from
<%= form.fields_for :user do | f| %>
to
<%= form.fields_for :users do | f| %>
(note user -> users), and the controller from
params.require(:account).permit(:name, user_attributes:
to
params.require(:account).permit(:name, users_attributes:
(again note user -> users).
Basically it came down to pluralisation!

nested forms : update child foreign key

I have a nested association:
class User < ActiveRecord::Base
has_many :hostels
accepts_nested_attributes_for :hostels
end
class Hostel < ActiveRecord::Base
belongs_to :user
end
The form :
<%= form_for #user do |f| %>
<%= f.label :email %><br>
<%= f.text_field :email %>
<% f.object.hostels << #hostel -%>
<%= f.fields_for :hostels do |ff| %>
<%= ff.hidden_field :id %>
<% end -%>
<%= f.submit %>
<% end -%>
the controller
def create
#user = User.new(user_params)
raise #user.hostels.inspect
end
private
def user_params
params.require(:user).permit(:email, hostels_attributes: [:id])
end
I would like to relink existing records of hostels to new users by updating hostel foreign key. This way, it definitly don't work.
Tried update_only: true parameter to nested too.
Any ideas about the subject or am I totally wrong about trying to do the operation like that ?
you can use a multiple select for hotels in you form, then in the controller you must require hostel_ids.
Models:
class User < ActiveRecord::Base
has_many :hostels
end
class Hostel < ActiveRecord::Base
belongs_to :user
end
Form: where :name is what you see in your multiple select
<%= form_for #user do |f| %>
<%= f.label :email %><br>
<%= f.text_field :email %>
<%= f.label "Hostels" %><br>
<%= select_tag :hotel_ids, options_for_select(Hostel.all.map{|h| [h.name, h.id]}), { :multiple => true } %>
<%= f.submit %>
<% end %>
Controller:
def create
#user = User.new(user_params)
end
private
def user_params
params.require(:user).permit(:email, hostel_ids)
end
I did not test the code but must work well.

rails How to save a serialized hash

I have a serialized object :address in Hotel model and I don't know how to save it properly in the DB. I have the following:
#model hotel
class Hotel < ActiveRecord::Base
belongs_to :user
serialize :address, Hash
end
...and view 'new'
<%= form_for(#hotel) do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :stars %>
<%= f.text_field :stars %>
<%= f.label :room, "Room description" %>
<%= f.text_area :room, size: "20x10" %>
<%= f.label :price %>
<%= f.number_field :price %>
<%= f.fields_for :address do |o| %>
<%= o.label :country %>
<%= o.text_field :country %>
<%= o.label :state %>
<%= o.text_field :state %>
<%= o.label :city %>
<%= o.text_field :city %>
<%= o.label :street %>
<%= o.text_field :street %>
<% end %>
<%= f.submit "Create hotel", class: "btn btn-large btn-primary" %>
<% end %>
With this code what I get is: hotel address nil...
Okay.. We will go another way. After googling much I came to this code:
# hotel.rb model
class Hotel < ActiveRecord::Base
class Address
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :country, :state, :city, :street
def persisted?; true end
def id; 1 end
def self.load json
obj = self.new
unless json.nil?
attrs = JSON.parse json
obj.country = attrs['country']
obj.state = attrs['state']
obj.city = attrs['city']
obj.street = attrs['street']
end
obj
end
def self.dump obj
obj.to_json if obj
end
end
belongs_to :user
serialize :address, Address
end
and the same view new.html.erb
The result is: Address:0xb0e530c
So, nothing saves in the database... I don't know what to try next, I'll appreciate any help. Didn't know that serialized object will cause so much problems to me.
THANKS!
PS Here's hotels_controller.
class HotelsController < ApplicationController
before_action :signed_in_user, only: [:index, :edit, :update, :destroy]
def new
#hotel = Hotel.new
end
def index
#hotels = Hotel.paginate(page: params[:page])
end
def show
#hotel = Hotel.find(params[:id])
end
def create
#hotel = current_user.hotels.build(hotel_params)
if #hotel.save
flash[:success] = "Hotel created!"
redirect_to #hotel
else
render 'new'
end
end
private
def hotel_params
params.require(:hotel).permit(:title, :stars, :room, :price, :address)
end
end
First thing on your migration file make sure that you are saving your fields as a test like
def self.up
add_column : hotels, : address, :text
end
Then Rails will convert it into YAML / Hash for you (and perform proper serialization).
Wish you the best of luck.
PS take a look at https://stackoverflow.com/a/6702790/1380867

NoMethodError raised following Railscast #250

I'm following the 'Authentication from scratch' railscast but cannot get it to work.
Controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to products_path, notice: 'User created successfully'
else
render 'new'
end
end
end
Model:
class User < ActiveRecord::Base
has_secure_password
attr_accessible :email, :password, :password_confirmation
validates_uniqueness_of :email
end
users#new form:
<h1>Sign up form</h1>
<%= form_for #user do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
<%= f.submit %>
<% end %>
When I try to go to the new user form it throws up a NoMethodError - undefined method 'email' referring to the line that has 'f.text_field :email'.
What am I missing here?
Thanks any help appreciated.
Your users table does not have an email column. Please run a migration to add the column to your users table.

How should I use rails and simple_form for nested resources?

I'm trying to create one resource with another nested resource at the same time. I'm using Rails4 and simple_form 3.0.0rc. Here is my code.
Models:
class User < ActiveRecord::Base
has_one :profile
accepts_nested_attributes_for :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
end
Controller:
class UsersController < ApplicationController
def new
#user = User.new
#user.build_profile
end
def create
user = User.new user_params
user.save
redirect_to root_url
# #par =params
end
private
def user_params
params.require(:user).permit(:email, profile_attributes: [:name])
end
end
View (form for new user)
<%= simple_form_for #user do |f| %>
<%= f.input :email %>
<%= simple_fields_for :profile do |p| %>
<%= p.input :name %>
<% end %>
<%= f.submit %>
<% end %>
When I submit the form, the create action receives this params:
{"utf8"=>"✓",
"authenticity_token"=>"dJAcMcdZnrtTXVIeS2cNBwM+S6dZh7EQEALZx09l8fg=",
"user"=>{"email"=>"vasily.sib#gmail.com"},
"profile"=>{"name"=>"Vasily"},
"commit"=>"Create User",
"action"=>"create",
"controller"=>"users"}
And after calling user_params the only thing that left is
{"email"=>"vasily.sib#gmail.com"}
And, as you can see, there is nothing about profile, so no profile will be created.
What am I doing wrong?
Use f.simple_fields_for instead of simple_fields_for:
<%= f.simple_fields_for :profile do |p| %>
<%= p.input :name %>
<% end %>
In my case I had the object "book" which belongs to "tour" and "tour" has_many "books".
In the "BookController" in the method "new" I find the tour and initialize the book object:
#tour = Tour.find(params[:tour_id])
#book = Book.new
This is the partial form to create a book: _form.html.erb
<%= simple_form_for [#tour, #book] do |f| %>
<%= f.input :name, label: "Name"%>
<%= f.input :NoReservations, label: "Number of Reservations" %>
<%= f.input :email, label: "Email" %>
<h3>Num of available places</h3>
<%= f.button :submit %>
<% end %>

Resources