My scenario: Movies have reviews, reviews have comments.
Movie model:
has_many :reviews
Review model:
has_many :comments
belongs_to :movie
Comment model:
belongs_to :review
Routes:
resources :movies do
resources :reviews do
resources :comments
end
end
Comments controller:
def create
#movie = Movie.find(params[:movie_id])
#review = Review.where(:movie_id => #movie.id)
#comment = #review.comments.create(params[:comment]) // Line 5
redirect_to movie_path(#movie)
end
Comment view:
<%= form_for([#movie, r, r.comments.build]) do |f| %>
<div class="field">
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
The error that I get is:
NoMethodError (undefined method `comments' for #<ActiveRecord::Relation:0x007ff5c5870010>):
app/controllers/comments_controller.rb:5:in `create'
Can somebody please tell me what I'm doing wrong?
Thanks in advance..
Review.where returns a list of reviews, what you want is an instance
#review = Review.where(:movie_id => #movie.id).first
or
#review = Review.find_by_movie_id(#movie.id)
Make sure to handle nil case.
Related
I've some trouble with my Rails application. I have some video tutorials and I want to let the user write some comments. I've created 3 models: comment.rb, user.rb and tutorial.rb. Tutorial has many comments and belongs to user; comment belongs to tutorial and to user; user has many comments and many tutorials. I have the create action in tutorial_controller and it works. When the tutorial has been created, a view with a comment_form is rendered. At this point, the user can write his comment BUT when he submits I got a problem with the create action in the comments_controller.
The message error is
NoMethodError in CommentsController#create
undefined method `comments' for nil:NilClass
Why 'comments' is undefined? Of course the comment is not created.
And now some code...
comment model:
class Comment < ActiveRecord::Base
#content may be tutorial, post etc. Body is the real content of the comment
attr_accessible :writer, :content, :body
belongs_to :user
belongs_to :tutorial
end
Create action in comments controller:
def create
#comment = Comment.new
#comment = #tutorial.comments.build(params[:comment])
if #comment.save
flash[:success] = 'Your comment was successfully added!'
render 'tutorials/show'
else
render 'tutorials/show'
end
end
Comment form:
<%= form_for(#tutorial.comments.build(params[:id])) do |f| %>
<div class="form-group">
<%= f.label :body %>
<%= f.text_area :body, class: 'form-control', required: true %>
</div>
<%= f.submit class: 'btn btn-primary' %>
<% end %>
Show action in tutorials controller:
def show
#shows the page of the single tutorial
#tutorial = Tutorial.find(params[:id])
current_tutorial = #tutorial
end
Thanks!!
I have the following model:
class Contact
attr_accessor :name, :emails, :message
def initialize(attrs = {})
attrs.each do |k, v|
self.send "#{k}=", v
end
end
def persisted?
false
end
end
I am calling to a contact form in my view like so:
<div class="email_form">
<%= render 'form' %>
</div>
Here is the controller:
class ShareController < ApplicationController
layout "marketing_2013"
respond_to :html, :js
def index
#contact = Contact.new
end
end
Here is the Form:
<%= form_for(#contact) do |f| %>
<%= f.label :name, "Your Name" %>
<%= f.text_field :name %>
<%= f.label :text, "Send to (separate emails with a comma)" %>
<%= f.text_field :emails %>
<%= f.label :message, "Email Text" %>
<%= f.text_area :message %>
<%= f.submit %>
<% end %>
For some reason I keep getting this error:
undefined method model_name for Contact:Class
Any reason why what I have currently wouldn't work?
Besides the correct route in your config/routes.rb, you will also need these two instructions on your model:
include ActiveModel::Conversion
extend ActiveModel::Naming
Take a look at this question: form_for without ActiveRecord, form action not updating.
For the route part of these answer, you could add this to your config/routes.rb:
resources :contacts, only: 'create'
This will generate de following route:
contacts POST /contacts(.:format) contacts#create
Then you can use this action (contacts#create) to handle the form submission.
add include ActiveModel::Model to your Contact file
your route probably doesn't go where you think it's going and therefore #contact is probably nill
run "rake routes" and check the new path.. if you are using defaults, the route is
new_contact_path.. and the erb should be in file: app/views/contacts/new.html.erb
def new
#contact = Contact.new
end
I'm rather new to Rails and I'm writing a signup form that includes nested models. When I submit the form, the user is saved just fine, but the nested model does not save anything to the Subscription db, and the console throws no errors.
I sincerely hope I'm not missing something insanely obvious, and I appreciate any tips you can share. Thanks!
Here is the code-
Models:
class Plan < ActiveRecord::Base
attr_accessible :posts, :name, :price
has_many :users
end
class User < ActiveRecord::Base
belongs_to :plan
has_many :events
has_one :subscription, :autosave => true
accepts_nested_attributes_for :subscription
attr_accessible :subscription_attributes
def save_with_payment
if valid?
customer = Stripe::Customer.create(
email:email,
plan: plan_id,
card: stripe_card_token )
self.stripe_customer_token = customer.id
save!
end
rescue Stripe::InvalidRequestError => e
logger.error "Stripe error while creating customer: #{e.message}"
errors.add :base, "There was a problem with your credit card."
false
end
end
class Subscription < ActiveRecord::Base
attr_accessible :plan_id, :status, :user_id
belongs_to :user
end
This is the User controller:
def new
#user = User.new
plan = Plan.find(params[:plan_id])
#user = plan.user
#user.build_subscription
end
def create
#user = User.new(params[:user])
if #user.save_with_payment
sign_in #user
flash[:success] = "Welcome to the SendEvent!"
redirect_to #user
else
render 'new'
end
end
This is the form:
<%= form_for #user, :html => {:class => "form-inline"} do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="control-group">
<%= f.label :name, :class => "control-label" %>
<%= f.text_field :name %>
</div>
# A few more fields here and...
# The nested model:
<%= f.fields_for :subscription do |builder| %>
<%= builder.hidden_field :status, :value => true %>
<% end %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary", id: "submitacct" %>
<% end %>
Sample app from RailsCasts
RailsCasts Episode #196: Nested Model Form (revised)
Maybe help you.
I have a project that contains projects that have todos that have tasks. When I try to create a new task, I get this error when I submit:
No route matches [POST] "/projects/1/todos/19/tasks/new"
Here is my form:
<%= form_for [#todo, #todo.tasks.new], :url => new_project_todo_task_path(#project, #todo) do |f| %>
<div class="field">
<%= f.label :description, "Description" %><br />
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit %> or <%= link_to "Cancel", "#", :id => "cancel_new_task_link" %>
</div>
<% end %>
Here is my controller:
class TasksController < ApplicationController
before_filter :authenticated?
before_filter :get_project_and_todo
respond_to :html, :xml, :json, :js
def new
#task = #todo.tasks.new
end
def create
#task = #todo.tasks.new(params[:task])
if #task.save
respond_with #todo, :location => project_todo_path(#project, #todo)
else
render "new"
end
end
private
def get_project_and_todo
#project = Project.find(params[:project_id])
#todo = #project.todos.find(params[:todo_id])
end
end
Here are my routes:
resources :projects do
resources :todos do
resources :tasks
end
end
Thanks
Your URL should not be new_project_todo_task_path(#project, #todo). You don't need to specify the URL here as Rails will imply it from the parameters passed in to form_for.
If the final object is a new object and not persisted in the database then it will make a POST request to, in this case, /projects/:project_id/todos. You're declaring in your example that you want to make a POST request to /projects/:project_id/todos/new, for which there is no POST route and that is why it's failing.
I have a Member model that belongs to User
class Member < ActiveRecord::Base
attr_accessible :name
belongs_to :user
end
class User < ActiveRecord::Base
attr_accessible :name
has_many :members, :dependent => :destroy
end
In my Members controller I have
class MembersController < ApplicationController
def create
#user = User.find(params[:user_id])
#member = #user.members.build(params[:member])
if #member.save
flash[:success] = "Member created!"
redirect_to root_path
else
render 'pages/home'
end
end
end
In /app/views/users/show.html.erb I have
<%= form_for #member do |f| %>
<div class="field">
<%= f.text_area :name %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
But I get the following error:
undefined method `model_name' for NilClass:Class
Extracted source (around line #18):
15:
16: <h1 class="member">What's up?</h1>
17:
18: <%= form_for #member do |f| %>
My show action in the Users controller is
def show
#user = User.find(params[:id])
#members = Member.new
#title = #user.name
end
Which also contains the 'new' method
I have tried changing :user_id to :id in the MembersController but this does not work either. What am I doing wrong here?
thanks in advance
Try to replace #members = Member.new by #member = Member.new ;-) !
I needed to pass the #user.id as a hidden field in the form, for the association to work!