So I'm still a Rails noob so I may be completely going at this wrong but I have two controllers. A Question Controller and an Answer Controller. I am trying to build a grading function that allows an admin user to assign points to essay questions. I am using the /answer/:id to be where the :id is the id of the question and then rendering a partial to iterate through all of the answers for that id. Clear as mud I'm sure...
My problem: Within the partial where the user's answer is displayed, I have a form that allows the admin to fill out the number of points for that answer and submit. Ideally, I'd like it to move to the next page (using will_paginate), but at a minimum, I'd like to stay on the same page. I am able to get the form working but it keeps going to /answers/:id but where :id is the id of the individual answer, so not what I'm hoping.
answers_controller.rb
class AnswersController < ApplicationController
def index
#user = current_user
#questions = Question.all
end
def show
#user = current_user
#question = Question.find(params[:id])
#answers = Answer.where("question_id = ?", #question.id).paginate(:page => params[:page], :per_page => 1)
#answer = Answer.where("question_id =? AND user_id = ?", #question.id, #user.id)
end
def edit
#answer = Answer.find(params[:id])
end
def update
#answer = Answer.find(params[:id])
if #answer.update_attributes(grade_params)
flash[:success] = "Answer Graded"
else
flash[:warning] = "Not Graded"
end
end
private
def grade_params
params.require(:answer).permit(:points_earned)
end
end
_essay_grades.html.erb (partial that is being rendered on the show page that contains the form)
<% #answers.each do |answer| %>
<p>User: <%= answer.user_id %></p>
<%= answer.answer %><br>
<%= #question.value %>
<br>
<%= form_for(answer) do |f| %>
<%#= f.radio_button :points_earned, #question.value %><br>
<%#= f.radio_button :points_earned, 0 %> <br>
<%= f.text_field :points_earned %> Points<br>
<br>
<%= f.submit "Award Points" %>
<% end %>
<% end %>
<br>
<br>
<%= will_paginate #answers, renderer: BootstrapPagination::Rails %>
routes.rb
Rails.application.routes.draw do
resources :admins, :answers, :static_pages, :questions
devise_for :users, :controllers => { registrations: 'registrations' },
:path => '', :path_names =>
{ :sign_in => "login", :sign_up => "register" }
root "static_pages#index"
end
I'm sure there's a simple solution here (or maybe it's changing how I have things set up...). Any help is greatly appreciated!
AFTER FEEDBACK:
Added the grades model and set up a through relationship with questions.
answer_controller.rb
class AnswersController < ApplicationController
def show
#user = current_user
#question = Question.find(params[:id])
#answers = Answer.where("question_id = ?", #question.id).paginate(:page => params[:page], :per_page => 1)
#answer = Answer.where("question_id =? AND user_id = ?", #question.id, #user.id)
end
def update
#user = current_user
#question = Question.find(params[:question_id])
#answer = #question.answers.find(params[:id])
#grade = #question.grades.new(grade_params)
if #grade.save
flash[:success] = "Answer Graded"
redirect_to #question
end
end
private
def grade_params
params.require(:grade).permit(:user_id, :answer_id, :points_earned, :graded_by, :comment)
end
end
_answer.html.erb
<%= answer.user_id %>
<%= form_tag [#question, answer], method: :put do %>
<%= hidden_field_tag :graded_by, current_user.id %>
<%= hidden_field_tag :answer_id, answer.id %>
<%= number_field_tag :points_earned %>
<%= submit_tag "Submit Grade" %>
<% end %>
routes.rb
Rails.application.routes.draw do
resources :questions do
resources :answers, only: [:update]
end
resources :admins, :static_pages
questions/show.html.erb
...
<h3>Show answers</h3>
<%= render #answers, locals: {question: #question} %>
<%= will_paginate #answers, renderer: BootstrapPagination::Rails %>
You will have to use the following in your form so the update does not load a new page, but still submits your update. Use Chrome / Firefox developer tools to view requests / responses.
<%= form_for(answer), :remote => true do |f| %>
Then, alter the update action in the answers controller to load the 'next unrated answer':
def update
rated_answer = Answer.find(params[:id])
if rated_answer.update_attributes(grade_params)
flash[:success] = "Answer Graded"
else
flash[:warning] = "Not Graded"
end
#answer = get_next_unrated_answer(rated_answer.question_id)
end
private
def get_next_unrated_answer(question_id)
# I am making a couple of assumptions on your model here, but get an answer that has not been rated yet for this question
next_answer = Answer.where("question_id = ? and points_earned = ?", question.id, nil)
#returned automatically
end
Then you will have to create app/views/answers/update.js.erb to load the new answer to your page with the following line:
$('#main_div').html('<%= escape_javascript(render partial: 'whatever_partial_you_have_created_to_display_the_next_unrated_answer') %>');
Just go and create a new partial that displays your answer and form correctly for the next unrated answer. Or ideally load your initial 'show.html.erb' with the relevant partials and reuse them.
This is the simple way to do it, but if I were you I would probably rename these new functions to not use 'update' or 'show' but rather call it something like 'rate' and even 'rate_show' so you can use update and show in its original form (for updating and answer or showing an answer) if required later in your project.
From what I understood of your question, I think you'd be best looking into nested routes:
#config/routes.rb
resources :questions do
resources :answers, only: [:update]
end
#app/controllers/questions_controller.rb
class QuestionsController < ApplicationController
def show
#question = Question.find params[:id]
end
end
#app/views/questions/show.html.erb
<%= #question.title %>
<%= render #question.answers, locals: {question: #question} %>
#app/views/questions/_answer.html.erb
<%= answer.title %>
<%= form_tag [question, answer], method: :put do %>
<%= text_field_tag :grade %>
<%= submit_tag %>
<% end %>
The above will give you what you have already (just to clarify your "clearly mad" remark is not the case at all!).
-
The following is where the nested resources come in.
At the moment, it seems you're having a problem associating an answer to a question:
where :id is the id of the individual answer, so not what I'm hoping
A remedy for this is as follows:
#app/controllers/answers_controller.rb
class AnswersController < ApplicationController
def update
#question = Question.find params[:question_id]
#answer = #question.answers.find params[:id]
#grade = #answer.grades.new grade_params
redirect_to #question if #grade.save
end
private
def grade_params
params.permit(:points_earned) #-> will probably have to refactor this
end
end
This will create a new grade (which you should have in an associated model), for that specific answer. Because the answer has been associated to a question, it will allow you to use the nested routes to load both.
In terms of your setup, I'd personally add a Grade model, so that you can have multiple grades per answer. This is against your current schema, but works well to ensure you have the functionality necessary to facilitate multiple grades:
#app/models/grade.rb
class Grade < ActiveRecord::Base
belongs_to :answer
belongs_to :user
end
#app/models/answer.rb
class Answer < ActiveRecord::Base
has_many :grades
end
Related
Currently learning Ruby on Rails and creating a simple blog app with comments. I have a Comment model and an Article model. Comment is polymorphic and both models have many comments.
I'm trying to come up with a destroy method that's able to delete both the comments that belong to Comment and the ones that belong to Article (and that remain as [deleted] without destroying their children, much like in Reddit, although I haven't even gotten to that part).
I have tried different paths but I haven't got it right yet. Nested paths still confuse me a little and I'm not sure on how to pass the params that the path requests when creating the link_to.
These are my files:
routes.rb:
Rails.application.routes.draw do
get 'comments/new'
get 'comments/create'
get 'articles/index'
get 'articles/show'
root 'articles#index'
resources :articles do
resources :comments
end
resources :comments do
resources :comments
end
end
article.rb:
class Article < ApplicationRecord
has_many :comments, as: :commentable
end
comment.rb:
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: :true
has_many :comments, as: :commentable
end
comments_controller.rb:
class CommentsController < ApplicationController
before_action :find_commentable
def new
#comment = Comment.new
end
def create
#comment = #commentable.comments.new(comment_params)
if #comment.save
redirect_back(fallback_location: root_path)
else
redirect_back(fallback_location: root_path)
end
end
def destroy
#comment = #commentable.comments.find(params[:id])
#comment.destroy
redirect_back(fallback_location: root_path)
end
private
def comment_params
params.require(:comment).permit(:body)
end
def find_commentable
if params[:article_id]
#commentable = Article.find_by_id(params[:article_id])
elsif params[:comment_id]
#commentable = Comment.find_by_id(params[:comment_id])
end
end
end
show.html.erb, where the form for commments that belong to Article.rb is:
<h1> <%= #article.title %> </h1>
<p> <%= #article.body %> </p>
<small>Submitted <%= time_ago_in_words(#article.created_at) %> ago </small> <br/>
<h3>Comments</h3>
<%= form_for [#article, Comment.new] do |f| %>
<%= f.text_area :body, placeholder: "Say something!" %> <br/>
<%= f.submit "Submit" %>
<% end %>
<ul class="parent-comment">
<%= render partial: 'comments/comment', collection: #article.comments %>
</ul>
<%= link_to "Index", articles_path %>
And the partial _comment.html.erb , which displays the comments that belong to the article as well as those that belong to other comments, and where I'm trying to integrate the link_to:
<p> <%= comment.body %> </p>
<small>Submitted <%= time_ago_in_words(comment.created_at) %> ago </small> <br/>
<%= form_for [comment, Comment.new] do |f| %>
<%= f.text_area :body, placeholder: "Add a reply!" %><br/>
<%= f.submit "Reply" %>
<%= link_to "Delete", comment_path(comment), method: :delete %>
<% end %>
<ul>
<%= render partial: 'comments/comment', collection: comment.comments %>
</ul>
Whenever I do seem to get the path right, NoMethodError in CommentsController#destroy — undefined method `comments' for nil:NilClass comes up. Why would the controller show it as undefined? It worked in the new method, as far as I can see.
Could you give some guidance as to what I should do or what I should fix? I'm not sure how to delete the parent comments, either, and I haven't managed to find information that suits this case. If you know where to point me to, I'm all eyes.
Thank you.
Because of your design model structure.
Your view
<%= link_to "Delete", comment_path(comment), method: :delete %>
Your find_commentable
elsif params[:comment_id]
#commentable = Comment.find_by_id(params[:comment_id])
end
#commentable will be a Comment class, so it won't have .comments methods as your Article class
check carefully to destroy the method
def destroy
#comment = #commentable.comments.find(params[:id])
#comment.destroy
redirect_back(fallback_location: root_path)
end
use #comment = #commentable.comments.find_by(id: params[:id]) and check whether #comment has some value or not?
just add one condition like this and it won't throw the error:
#comment.destroy if #comment
if #comment is nil and trying to destroy then it will throw the error.
My rails app has a games model, and each game has multiple players. When a game is created, a set number of players are created with a default name like so:
def create
#game = Game.new(game_params)
#game.player_number.times do
#game.players << Player.new(name: 'Santa')
end
if #game.save
redirect_to action: "players", id: #game.id
else
render 'new'
end
end
The redirect takes the user to a page that has a form with inputs for each player's name. The actions associated with this page are:
def players
#game = Game.find(params[:id])
end
def playersUpdate
#game = Game.find(params[:id])
puts player_params
if #game.players.update(player_params)
redirect_to #game
else
render 'players'
end
end
private
def player_params
params.require(players: [:name])
end
The editing page itself is:
<h2> Edit Players </h2>
<%= form_tag({:action => 'playersUpdate'},{:id => #game.id}) do %>
<%= #game.players.count %>
<% #game.players.each.with_index do |player,index| %>
<%= fields_for "players[#{index}]", player do |pl| %>
<div>
<%= pl.label :name %><br>
<%= pl.text_field :name %><br>
<%= pl.hidden_field :id %>
</div>
<% end %>
<% end %>
<div>
<%= submit_tag %>
</div>
<% end %>
Here's the routes.rb:
Rails.application.routes.draw do
get 'welcome/index'
resources :games do
collection do
match "/:id/players" => "games#players", :via => :get
match "/:id/players" => "games#playersUpdate", :via => :post
end
end
root 'welcome#index'
end
I get an error:
param is missing or the value is empty: {:players=>[:name]}
And I'm at a loss for what I could be missing. Any tips?
Here are the parameters being passed in, George is the name I'm trying to edit in, all others default to 'Santa':
Processing by GamesController#playersUpdate as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wNwt9v2ckO/Bl8YGr/a2CDCjSsRec30E51VjZ/Qv2i5BgEnzVbH5M9DsrVfCxdLusS4Ue6Mq+aPSFOiA4K5jJg==", "players"=>{"0"=>{"name"=>"George", "id"=>"122"}, "1"=>{"name"=>"Santa", "id"=>"123"}, "2"=>{"name"=>"Santa", "id"=>"124"}, "3"=>{"name"=>"Santa", "id"=>"125"}}, "commit"=>"Save changes", "id"=>"22"}
You are not breaking any new ground here, and Rails has standard ways to do all of this. But it's easy to get "off the Rails" and make it harder than it needs to be.
Conceptually, stop thinking about updating a bunch of Players, and start thinking about updating a Game that happens to have some Players. The docs are surprisingly helpful here.
Let's go first to your Game model. You'll need to tell it that it's OK to update nested attributes for players, like this:
# models/game.rb
model Game < ApplicationRecord
has_many :players
accepts_nested_attributes_for :players
end
Your view is generating parameters that are not quite standard. Again, let Rails do the work for you. You don't need hidden fields or each_with_index. Since we're in Rails 5, let's use the new form_with helper, and we'll let fields_for do its job without our trying to tell it how to index:
# views/games/edit_players.html.erb
<h2> Edit Players </h2>
<%= form_with(model: game, local: true) do |form| %>
<div>
Game name: <%= form.text_field :name %>
</div>
<%= form.fields_for :players do |player_fields| %>
<div>
Player name: <%= player_fields.text_field :name %><br>
</div>
<% end %>
<div>
<%= form.submit %>
</div>
<% end %>
This will generate params that look something like this:
Parameters: {"game"=>
{"name"=>"Risk",
"players_attributes"=>
{"0"=>{"name"=>"Abel", "id"=>"1"},
"1"=>{"name"=>"Baker", "id"=>"2"},
"2"=>{"name"=>"Charlie", "id"=>"3"}}},
"commit"=>"Update Game",
"id"=>"1"}
Now you don't even need a custom update endpoint. Just use your standard GamesController#update action:
# controllers/games_controller.rb
class GamesController < ApplicationController
...
def edit_players
#game = Game.find(params[:id])
end
def update
#game = Game.find(params[:id])
if #game.update(game_params)
redirect_to #game
else
render :edit
end
end
private
def game_params
params.require(:game).permit(:name, players_attributes: [:id, :name])
end
end
Finally, your routes file is confusing because you are using collection (which doesn't expect an :id) instead of member. The routes file should look something like this:
# routes.rb
Rails.application.routes.draw do
resources :players
resources :games do
member { get :edit_players }
end
end
I'm working on a ROR blog and have encountered some issues along the way. I'm currently learning Rails and just feel completely lost with connecting all the pieces. I've been working on my comments section for days and was finally able to create comments on posts, but I can't edit or delete them. I also referenced the SO questions below but am still running into problems.
Add Comment to User and Post models (Ruby on Rails)
Here's my layout:
Comment model params:
body \ user_id \ post_id
Model associations:
user.rb
has_many :posts
has_many :comments
post.rb
belongs_to :user
has_many :comments
comment.rb
belongs_to :user
belongs_to :post
routes.rb:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
get '/' => 'users#index'
get '/posts' => 'posts#index'
post '/posts/create' => 'posts#new'
post '/posts/edit' => 'posts#edit'
get '/signin' => 'sessions#new', as: :new_session
post '/create-session' => 'sessions#create', as: :create_session
get 'signout' => 'sessions#destroy', as: :destroy_session
resources :users
resources :posts
resources :comments
end
comments controller:
class CommentsController < ApplicationController
def index
#comment = Comment.all
end
def new
user = session[:user_id]
#comment = Comment.new(post_id: params[:post_id])
#post = Post.find(params[:post_id])
end
def create
#comment = Comment.new(comment_params)
#comment.user_id = session[:user_id]
#postid = params[:id]
if #comment.save
flash[:notice] = "comment created."
redirect_to '/posts'
else
flash[:error] = "Error creating comment."
redirect_to '/posts'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#comment = Comment.find_by_id(params[:id])
#comment.update(comment_params)
flash[:notice] = "Comment updated."
redirect_to '/posts'
end
def destroy
#comment = Comment.find(params[:comment_id])
#comment.destroy
redirect_to '/posts'
end
private
def comment_params
params.require(:comment).permit(:body, :user_id, :post_id)
end
end
Posts show.html.erb page in views/posts folder:
<%# show all posts %>
<div id="single-post">
<h1>User - <%= #post.user.username %></h1>
<h2>Post - <%= #post.body %> </h2>
<%= link_to("Edit Post", edit_post_path(#post)) %>
</br>
<%= link_to("Delete Post", #post, method: 'delete') %>
</br>
<%= link_to("Add Comment", new_comment_path(post_id: #post.id)) %>
<%#<%= link_to("Edit Comment", edit_comment_path(post_id: #post.id, comment_id: #comment.id))%>
</div>
<h3><% #post.comments.reverse.each do |c| %> </h3>
<div id="single-comment">
<h4>Comment</h4>
<h5>From - <%= c.user.username %></h5>
<h6><%= c.body %> </h6>
</br>
<%= link_to("Edit Comment", edit_comment_path(#post.id)) %>
</br>
<%= link_to("Delete Comment", comment_path(#post.id), method: :delete) %>
</div>
<% end %>
</div>
new.html.erb form in views/comments folder
<div id="comment-form">
<%= form_for #comment do |f| %>
<%= f.label :body %>
<%= f.text_area :body, class: "text-area" %>
<%= f.hidden_field :post_id %>
<%= f.submit %>
<% end %>
</div>
Again I can add comments to posts. When I hover over the edit tag on the comment I'm seeing this: localhost:3000/comments/72/edit
I see this error when I click on edit
When I hover over the delete button I see this: localhost:3000/comments/72
I see this error when I click on delete
I'm at the point where I'm completely lost and feel I have tried everything possible but nothing seems to work. Please help! Here's the GitHub repo as well: https://github.com/angelr1076/rails-blog
The First argument in form cannot contain nil or be empty is telling you that #comment in <%= form_for #comment do |f| %> is nil. This is because in the edit action of your CommentsController you are setting #post instead of #comment.
Change this to be:
def edit
#comment = Comment.find(params[:id])
end
For deleting a comment, the Couldn't find Comment without an ID is telling you that the value you're passing to find is nil. This is because you're trying to use params[:comment_id] instead of params[:id]. Change the destroy action to:
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
redirect_to '/posts'
end
Update:
Also as per your code, you should change edit and delete links to below
<%= link_to("Edit Comment", edit_comment_path(c)) %>
<%= link_to("Delete Comment", comment_path(c), method: :delete)
You are passing #post.id which is an id of post. Instead you should pass id of the comment using the block variable from your comments.each, noticing that the .id isn't needed here because it can be inferred by Rails.
I have 2 forms in one view one is displayed if the user is a moderator and the other if it is a normal user and they both send the information to 2 different controllers. My problem is that if its a normal user, the form that is displayed for them uses the wrong controller.
Here is the coding
categories/new.html.erb
<% if current_user.mod_of_game? #guide %>
<%= form_for([#guide, #category], url: guide_categories_path) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, "Category name" %>
<%= f.text_field :name %>
<%= f.submit "Next" %>
<% end %>
<% else %>
<%= form_for([#guide, #check_category], url: check_category_post_path) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, "Category name" %>
<%= f.text_field :name %>
<%= f.submit "Next" %>
<% end %>
<% end %>
Categories controller
before_action :mod_checker, only: [:create]
def new
#guide = Guide.friendly.find(params[:guide_id])
#category = Guide.friendly.find(#guide.id).categories.new
#check_category = CheckCategory.new
end
def create
#guide = Guide.friendly.find(params[:guide_id])
#category = Guide.friendly.find(#guide.id).categories.new(category_params)
if ((#category.save) && (current_user.mod_of_game? #guide))
flash[:info] = "guide category added succesfully!"
redirect_to #guide
else
render 'new'
end
end
private
def category_params
params.require(:category).permit(:name)
end
def mod_checker
#guide = Guide.friendly.find(params[:guide_id])
unless current_user.mod_of_game? #guide
flash[:danger] = "Sorry something went wrong!"
redirect_to root_path
end
end
check_categories controller
def new
end
def create
if #check_category.save
flash[:info] = "Game category added successfully. A mod will apporve it shortly."
redirect_to #guide
else
render 'new'
end
end
private
def check_category_params
params.require(:check_category).permit(:name)
end
and the routes
resources :guides do
resources :categories, only: [:new, :create, :edit, :update]
end
resources :check_categories, only: [:new, :edit, :update]
match 'guides/:guide_id/categories/' => 'check_categories#create', :via => :post, as: :check_category_post
sorry the coding is a bit messy, the 4 spaces to put it in a code block was spacing my coding weird.
When i have a non moderator user submit the form, the before action in the categories controller is run and I'm redirected to the homepage. I don't know why it does this because the submit path should go to the check_categories controller for non moderator users, the check_categories controller doesn't have the before filter.
Why does it use the before filter in the controller I'm not using for that form? How can I fix it?
Building this app to learn rails better. So I can only assume lack of rails knowledge is causing me to do something wrong.
Bad practice to have two forms with identical code (apart from the path) - goes against DRY Don't Repeat Yourself.
As mentioned by #Akash, this sounds like a job for authorization.
Further, it also denotes that you have issues with the underlying structure of your code. Specifically, you have an antipattern with CheckCategory (you can put it all into the Category model):
#config/routes.rb
resources :guides do
resources :categories, only: [:new, :create, :edit, :update] do
patch :approve, on: :member
end
end
#app/models/category.rb
class Category < ActiveRecord::Base
before_action :set_guide
def new
#category = current_user.categories.new
flash[:notice] = "Since you are not a moderator, this will have to be approved." unless current_user.mod_of_game? #guide
end
def create
#category = current_user.categories.new category_params
#category.guide = #guide
#category.save
end
def approve
#category = #guide.categories.find params[:id]
#category.approve
end
private
def set_guide
#guide = Guide.find params[:guide_id]
end
end
#app/views/categories/new.html.erb
<%= form_for [#guide, #category] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, "Category name" %>
<%= f.text_field :name %>
<%= f.submit "Next" %>
<% end %>
The above will solve most of your structural issues.
--
To fix the authorization issue, you'll be best denoting whether the category is "approved" in the model:
#app/models/category.rb
class Category < ActiveRecord::Base
enum status: [:pending, :approved]
belongs_to :user
belongs_to :guide
validates :user, :guide presence: true
before_create :set_status
def approve
self.update status: "approved"
end
private
def set_status
self[:status] = "approved" if self.user.mod_of_game? self.guide
end
end
--
If I understand correctly, you want to allow anyone to create a category, but none-mods are to have their categories "checked" by a moderator.
The code above should implement this for you.
You will need to add a gem such as CanCan CanCanCan to implement some authorization:
#app/views/categories/index.html.erb
<% #categories.each do |category| %>
<%= link_to "Approve", guide_category_approve_path(#guide, category) if category.waiting? && can? :update, Category %>
<% end %>
Use "Cancan" Gem and give authorization
I'm building an application that has a Keynote model and a Story model (as well as a User model that I implemented with Devise).
Keynotes have many Stories and a Story belongs to a Keynote.
I'm having problems creating new stories and I get the following error:
ActiveRecord::RecordNotFound in StoriesController#create
Couldn't find Keynote without an ID
The error happens on line 17 of stories_controller.rb which is
#keynote = Keynote.find(params[:keynote_id])
in the create method.
This is part of my stories_controller.rb
class StoriesController < ApplicationController
before_filter :authenticate_user!, :except => [:show, :index]
def index
#keynote = Keynote.find(params[:keynote_id])
#stories = #keynote.stories
end
def new
#keynote = Keynote.find(params[:keynote_id])
#story = #keynote.stories.build
end
def create
if user_signed_in?
#keynote = Keynote.find(params[:keynote_id])
#story = #keynote.current_user.stories.build(params[:story])
if #story.save
flash[:notice] = 'Question submission succeeded'
redirect_to keynote_stories_path
else
render :action => 'new'
end
end
end
This is my keynotes_controller.rb
class KeynotesController < ApplicationController
def index
#keynotes = Keynote.find :all, :order => 'id ASC'
end
def new
#keynote = Keynote.new
end
def show
#keynote = Keynote.find(params[:id])
end
def create
#keynote = Keynote.new(params[:keynote])
if #keynote.save
flash[:notice] = 'Keynote submission succeeded'
redirect_to keynotes_path
else
render :action => 'new'
end
end
end
Any help would be really appreciated.
Edit:
These are the Parameters when I try to create a new Story.
{"utf8"=>"✓",
"authenticity_token"=>"76odSpcfpTlnePxr+WBt36fVdiLD2z+Gnkxt/Eu1/TU=",
"story"=>{"name"=>"as"},
"commit"=>"Send"}
It looks like the ID for the Keynote is not being passed.
This is the view for StoriesController#new
<%= error_messages_for 'story' %>
<%= form_for #story do |f| %>
<p>
Question:<br />
<%= f.text_field :name %>
</p>
<p>
<%= submit_tag "Ask" %>
</p>
<% end %>
This is what I have in my routes.rb file:
get "keynotes/index"
get "users/show"
devise_for :users
get "votes/create"
get "stories/index"
resources :keynotes do
resources :stories
end
resources :stories do
get 'bin', :on => :collection
resources :votes
end
resources :users
root :to => 'keynotes#index'
I think this should do the trick:
<%= form_for #story do |f| %>
<%= hidden_field_tag 'keynote_id', #keynote.id %>
.
rest of the form stuff here
.
<% end %>
PS. Not sure if you will get the keynote_id in params[:keynote_id] or params[:story][:keynote_id] .. check out both.
NB: I think there would be a easier way to do it too, using fields_for or something similar, but I don't have access to a Rails setup at the moment to test that out.