Undefined Method Error in rails - ruby-on-rails

I'm new in rails and i could use a little help.
I have the following setup in rails
Day has_many Bookings
Booking belongs_to Day
The Booking form in shared/_booking_form is as follows:
<%= form_for Booking.new do |t| %>
<%= render 'shared/error_messages', object: t.object %>
<div class="field">
<%= t.label :start %><br>
<%= t.time_select :start %>
</div>
<div class="field">
<%= t.label :end %><br>
<%= t.time_select :end %>
</div>
<div class="field">
<%= t.label :comentariu %><br>
<%= t.text_area :comentariu, placeholder: "Adauga un comentariu.." %>
</div>
<%= t.submit "Post", class: "btn btn-primary" %>
<% end %>
The bookings controller look like this
def show
#bookings = Booking.all
end
def new
#booking = Booking.new
end
def create
#booking = #day.bookings.build(booking_params)
#booking.save
flash[:success] = "Book created!"
redirect_to root_url
end
def destroy
end
private
def booking_params
params.require(:booking).permit(:start, :end, :comentariu)
end
I get this error and i haven't been able to solve
NoMethodError (undefined method `bookings' for nil:NilClass):
app/controllers/bookings_controller.rb:9:in `create'
Any help would be appreciated.

Related

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

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

Ruby Incorrect link generation redirect_to products_path(#product) generate /products.1 instead of /products/1

I'm trying to add a reviews on my single product page. But when I click Submit - It takes me to the /products.1 page, instead of /products/1
class CommentsController < ApplicationController
def create
#product = Product.find(params[:product_id])
#comment = #product.comments.new(comment_params)
#comment.user = current_user
#comment.save
redirect_to products_path(#product)
end
def destroy
end
private
def comment_params
params.require(:comment).permit(:user_id, :body, :rating)
end
end
and the comment.html.erb
<div class="row">
<div class="col-sm-6">
<% if signed_in? %>
<h4>Add a review:</h4>
<%= form_for([#product, #product.comments.build]) do |f| %>
<p>
<%= f.label :body, "Comment" %><br>
<%= f.text_area :body, class: "form-control" %>
</p>
<p>
<%= f.label :rating %><br>
<%= f.text_field :rating, class: "rating form-control" %>
</p>
<p>
<%= f.submit "Submit", class: "btn" %>
</p>
<% end %>
<% end %>
</div>
</div>
Try redirect_to #product instead of redirect_to products_path(#product).
Did you check your routes.rb under config? Try running rake routes in the terminal and you can debug from there.

Rails 4 - ActiveModel::ForbiddenAttributesError

I have read other issues about it, but still I can't point what is causing the error. I have defined the strong parameters of Rails 4, but it keeps showing the error:
ActiveModel::ForbiddenAttributesError in MessagesController#create
My view is this:
<%= form_for(#message) do |f| %>
<div class="form-group field">
<%= f.label :phrase %>
<br/>
<%= f.text_field :phrase, autofocus: true, class: 'form-control' %>
</div>
<div class="form-group field">
<%= f.label :date %>
<br/>
<%= f.date_field :date, class: 'form-control' %>
</div>
<div class="actions text-center">
<%= f.submit "Submit", class: 'btn btn-default' %>
</div>
<% end %>
My controller:
class MessagesController < ApplicationController
def today
#dates = Message.all()
end
def history
#messages = Message.history_checker
end
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.save
flash[:notice] = "OK"
redirect_to root_path
else
render :action => 'new'
end
end
private
def message_params
params.require(:message).permit(:phrase,:date)
end
end
The error points to line 15 of controller #message = Message.new(params[:message]). Any ideas?
You just need to use message_params instead of params[:message]:
#message = Message.new(message_params)

unable to create or update a belongs_to record in Rails 4

I'm new to Rails and struggling to get my belongs_to association right. I have an app where a painting belongs to an artist and an artist can have_many paintings. I can create and edit my paintings, however I can not edit or create artists except through the console. Through much Googling I feel I have got myself turned around. Any help would be much appreciated!
Here's my routes.rb file:
MuseumApp::Application.routes.draw do
resources :paintings
resources :paintings do
resources :artists
resources :museums
end
root 'paintings#index'
end
Here's my paintings Controller
def show
#painting = Painting.find params[:id]
end
def new
#painting = Painting.new
##artist = Artist.new
end
def create
safe_painting_params = params.require(:painting).permit(:title, :image)
#painting = Painting.new safe_painting_params
if #painting.save
redirect_to #painting
else
render :new
end
end
def destroy
#painting = Painting.find(params[:id])
#painting.destroy
redirect_to action: :index
end
def edit
#painting = Painting.find(params[:id])
end
def update
#painting = Painting.find(params[:id])
if #painting.update_attributes(params[:painting].permit(:title, :image)) #safe_params
redirect_to #painting
else
render :edit
end
end
Here's the form in my paintings view:
<%= form_for(#painting) do |f| %>
<fieldset>
<legend>painting</legend>
<div>
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div>
<%= f.label :image %>
<%= f.text_field :image %>
</div>
<%= form_for([#painting,#painting.create_artist]) do |f| %>
<div>
<%= f.label :Artist %>
<%= f.text_field :name %>
</div>
</fieldset>
<%= f.submit %>
<% end %>
<% end %>
Artists Controller:
class ArtistsController < ApplicationController
def index
#artists = Artist.all
#artists = params[:q] ? Artist.search_for(params[:q]) : Artist.all
end
def show
#artist = Artist.find params[:id]
end
def new
#artist = Artist.new
end
def create
#painting = Painting.find(params[:painting_id])
#artist = #painting.create_artist(artist_params)
redirect_to painting_path(#painting)
end
def destroy
#artist = Artist.find(params[:id])
#Artist.destroy
redirect_to action: :index
end
def edit
#artist = Artist.find(params[:id])
end
def update
#painting = Painting.find(params[:painting_id])
#artist = #artist.update_attributes(artist_params)
redirect_to painting_path(#painting)
end
end
private
def artist_params
params.require(:artist).permit(:name)
end
Index view:
<h1> Hello and Welcome to Museum App</h1>
<h3><%= link_to "+ Add To Your Collection", new_painting_artist_path %></h3>
<%= form_tag '/', method: :get do %>
<%= search_field_tag :q, params[:q] %>
<%= submit_tag "Search" %>
<% end %>
<br>
<div id="paintings">
<ul>
<% #paintings.each do |painting| %>
<li><%= link_to painting.title, {action: :show, id:painting.id} %> by <%= painting.artist_name %></li>
<div id = "img">
<br><%= link_to (image_tag painting.image), painting.image %><br>
</div>
<%= link_to "Edit", edit_painting_path(id: painting.id) %>
||
<%= link_to 'Destroy', {action: :destroy, id: painting.id},method: :delete, data: {confirm: 'Are you sure?'} %>
<% end %>
</ul>
</div>
In your case you should use accepts_nested_attributes_for and fields_for to achieve this.
Artist
has_many :paintings, :dependent => :destroy
accepts_nested_attributes_for :paintings
Painting
belongs_to :artist
And also you should try creating artist with paintings like this
form_for(#artist) do |f| %>
<fieldset>
<legend>Artist</legend>
<%= f.label :Artist %>
<%= f.text_field :name %>
<%= fields_for :paintings, #artist.paintings do |artist_paintings| %>
<%= artist_paintings.label :title %>
<%= artist_paintings.text_field :title %>
<%= artist_paintings.label :image %>
<%= artsist_paintings.text_field :image %>
</fieldset>
<%= f.submit %>
<% end %>
Note:
You should be having your Artist Controller with at least new,create,edit and update methods defined in it to achieve this.
Edit
Try the reverse
Artist
has_many :paintings, :dependent => :destroy
Painting
belongs_to :artist
accepts_nested_attributes_for :paintings
form_for(#painting) do |f| %>
<fieldset>
<legend>Painting</legend>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :image %>
<%= f.text_field :image %>
<%= fields_for :artists, #painting.artists do |ff| %>
<%= ff.label :Artist %>
<%= ff.text_field :name %>
</fieldset>
<%= f.submit %>
<% end %>
Put this form in paintings views.

Resources