#reckoner has_many #shift_requirements and in routes,
resources :reckoners do
resources :shift_requirements
end
In a view under reckoner_controller.rb I have
<%= link_to 'create a shift', [:new, #reckoner, :shift_requirement]%>
... which fires the correct view containing a form helper. Then it throws the error -
undefined method `shift_requirements_path' for #<#<Class:0x007f908e00a458>:0x007f908e8a09c8>
How have I gone wrong?
shift_requirement.rb is -
class ShiftRequirement < ActiveRecord::Base
belongs_to :reckoner
end
reckoner.rb is -
class Reckoner < ActiveRecord::Base
has_many :shift_requirements
end
... and the view in the form is now
<%= form_for(#reckoner, #shift_requirement) do |f| %>
...
<%= f.submit %>
I assume your form has:
<%= form_for(#shift_requirement) do |f| %>
<%= f.submit %>
<% end %>
Because of your nested routes you want
<%= form_for([#reckoner, #shift_requirement]) do |f| %>
<%= f.submit %>
<% end %>
Related
I've followed the Go Rails tutorial below to set up comments with polymorphic associations: https://gorails.com/episodes/comments-with-polymorphic-associations
However, I have a nested situation with two models (movies/parts). It is working with 'movies' but I cannot get it working with child model 'parts'.
Models
class Comment < ApplicationRecord
belongs_to :user
belongs_to :commentable, polymorphic: true
end
class Movie < ApplicationRecord
has_many :parts, dependent: :destroy
has_many :comments, as: :commentable
end
class Part < ApplicationRecord
belongs_to :movie
has_many :comments, as: :commentable
end
config/routes.rb
resources :movies do
resources :comments, module: :movies
resources :parts do
resources :comments, module: :parts
end
end
app/views/movies/show.html.erb
<%= render partial: "comments/comments", locals: {commentable: #movie} %>
<%= render partial: "comments/form", locals: {commentable: #movie} %>
app/views/comments/_comments.html.erb
<h1>Comments</h1>
<% commentable.comments.each do |comment| %>
<div class="well">
<%= comment.summary %> by <i><%= comment.user.email %></i><br><br>
</div>
<% end %>
app/views/comments/_form.html.erb
<%= form_for [commentable, Comment.new] do |form| %>
<% if commentable.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(commentable.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% commentable.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= form.text_area :summary, class: "form-control", placeholder: "Add a comment" %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
Everything above with 'movies' is working well. The problem is with 'parts'.
app/views/parts/show.html.erb
<%= render partial: "comments/comments", locals: {commentable: #part} %>
<%= render partial: "comments/form", locals: {commentable: #part} %>
Error with 'parts'
NoMethodError in Parts#show
undefined method `part_comments_path' for #ActionView::Base:0x0000000003d3b0
Highlighted line of error:
<%= form_for [commentable, Comment.new] do |form| %>
I think I have to pass the movie object with the part object into 'commentable' -- since it is nested -- but don't know how to do it with this set up. Any suggestions are greatly appreciated.
I believe route in the partial meant replacing any references to part_comments_path with movie_part_comments_path.
I have this slim syntax:
= form_for(#influencer.relationships.build(followed_id: #influencer.id)) do |f|
div = f.hidden_field :followed_id
= f.submit "Follow", class: "btn btn-large btn-primary"
This is the erb i came up but it doesn't work.
<%= form_for(#influencer.relationships.build(followed_id: #influencer.id)) do |f| %>
<% f.hidden_field :followed_id %>
<%= f.submit "Follow" %>
<% end %>
<%= form_for #influencer.relationships.build(followed_id: #influencer.id) do |f| %>
<%= f.hidden_field :followed_id %>
<%= f.submit "Follow" %>
<% end %>
Conversely, it's bad practice to build an object out of the controller scope. #influencer.relationships.build(followed_id: #influencer.id) should be done inside the controller:
#app/models/influencer.rb
class Influencer < ActiveRecord::Base
has_many :relationships, foreign_key: :follower_id
end
#app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController
def new
#influencer = Influencer.find params[:influencer_id]
#relationship = #influencer.relationships.build #-> "followed_id" SHOULD be a foreign key in the model. If you have it in the model, you won't need to explicitly define it
end
end
Thus, you'll get:
<%= button_to "Follow", #relationship %>
While delving into ruby's nested models I encountered an issue.
Consider the following scenario,
I have the following models:
Author
Book
With the following specifications:
Author:
class Author < ActiveRecord::Base
attr_accessible :name
has_many :books, dependent: :destroy
accepts_nested_attributes_for :books #I read this is necessary here: http://stackoverflow.com/questions/12300619/models-and-nested-forms
# and some validations...
end
Book:
class Book < ActiveRecord::Base
attr_accessible :author_id, :name, :year
belongs_to :author
#and some more validations...
end
I would like to add a book to an author. Here is my authors_controller:
def new_book
#author = Author.find(params[:id])
end
def create_book
#author = Author.find(params[:id])
if #author.books.create(params[:book]).save
redirect_to action: :show
else
render :new_book
end
end
And this is the form with which I try doing it:
<h1>Add new book to <%= #author.name %>'s collection</h1>
<%= form_for #author, html: { class: "well" } do |f| %>
<%= fields_for :books do |b| %>
<%= b.label :name %>
<%= b.text_field :name %>
<br/>
<%= b.label :year %>
<%= b.number_field :year %>
<% end %>
<br/>
<%= f.submit "Submit", class: "btn btn-primary" %>
<%= f.button "Reset", type: :reset, class: "btn btn-danger" %>
<% end %>
Problem:
When I type in the data and click "submit" it even redirects me to the correct author, but it doesn't save a new record for that author.
After a lot of research I can't seem to find what I am doing wrong here.
Change authors_controller to:
def new_book
#author = Author.find(params[:id])
#book = Book.new
end
Your form to:
<h1>Add new book to <%= #author.name %>'s collection</h1>
<%= form_for ([#author, #book]), html: { class: "well" } do |f| %>
And, routes.rb
resources :authors do
resources :books
end
You're missing a couple of things.
Controller:
...
def new_book
#author = Author.find(params[:id])
#author.books.build
end
...
View, it is f.fields_for and not just fields_for:
<%= f.fields_for :books do |b| %>
<%= b.label :name %>
<%= b.text_field :name %>
<br/>
<%= b.label :year %>
<%= b.number_field :year %>
<% end %>
You also need to add :nested_attributes_for_books on your Author model accessible methods. The create method on you Author controller doesn't need any code additions to get going.
Note: You set the Books controller to render 'books#show' on success. If the app is redirecting you to the author that means the Author controller is handling the creation of the book, unless you set it to redirect to author and not the book.
I saw similar examples here. But it just doesn't work for me.
I want to create/submit an activity for post. There are several days under a post. And an activity is under a specific date. See models below.
Models:
class Post < ActiveRecord::Base
has_many :dayinposts
has_many :activitys, :through => :dayinposts
end
class Dayinpost < ActiveRecord::Base
belongs_to :post
has_many :activitys
end
class Activity < ActiveRecord::Base
belongs_to :dayinpost
end
Routes:
resources :posts do
resources :dayinposts do
resources :activitys
end
end
rake routes
post_dayinpost_activitys GET /posts/:post_id/dayinposts/:dayinpost_id/activitys(.:format) activitys#index
POST /posts/:post_id/dayinposts/:dayinpost_id/activitys(.:format) activitys#create
show.html.erb
<% #post.dayinposts.each do |dayinpost| %>
<% dayinpost.activitys.each do |activity| %>
<p>
<b>Action:</b>
<%= activity.action %>
</p>
<% end %>
<%= form_for([#post, dayinpost, dayinpost.activitys.build]) do |f| %>
<div class="field">
<%= f.label :action %><br />
<%= f.text_field :action %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
error
undefined method `post_dayinpost_activities_path' for #<#<Class:0x40cb6d8>:0x40c9890>
But I have saw it in the rake routes...
thanks in advance!
The correct pluralization for "activity" is "activities".
In your config/routes.rb you have "activitys", which is wrong.
The fields_for block doesn't output in a has_many relationship. This problem came up in a somewhat involved project I was working on. I broke it down to a very simple test case, but it still doesn't work. This question has been asked before and the problem was usually
that the nested object didn't exist. But here, the nested object does appear to exist, as explained in the code comments. I'm pretty new to rails so it could be something obvious.
Here is the simple case model code:
class Parent < ActiveRecord::Base
has_many :children
accepts_nested_attributes_for :children
end
class Child < ActiveRecord::Base
belongs_to :parent
end
Simple case controller:
class ParentController < ApplicationController
def index
#parent = Parent.find_by_id(1)
end
end
Simple case view:
<%= form_for #parent, {:url=>{:action=>:index}} do |f| %>
<!-- this outputs ok -->
<%= f.text_field :name %>
<% f.object.children.each do |c| %>
<!-- this outputs "child1", so the nested object exists -->
<%= c.name %>
<% f.fields_for c do |field| %>
this line does NOT output, nor does the field below
<%= field.text_field :name %>
<% end %>
<% end %>
<% end %>
I also tried this and saw the same result:
<%= form_for #parent, {:url=>{:action=>:index}} do |f| %>
<%= f.text_field :name %>
output here
<% f.fields_for :children do |field| %>
no output here nor the field below
<%= field.text_field :name %>
<% end %>
<% end %>
I also tried with a new #parent object in the controller and a #parent.build_child
(having changed the assoc to a has_one). That still saw the same result.
You've forgotten to put the = sign after <%.
Replace:
<% f.fields_for :children do |field| %>
with:
<%= f.fields_for :children do |field| %>