Ruby on Rails - Passing Parameters between methods - ruby-on-rails

Routes File:
resources :tournaments do
resources :game, :only => [:new, :index, :create, :update, :destroy]
end
Rake Routes shows:
new_tournament_game GET /tournaments/:tournament_id/game/new(.:format) game#new
I call:
<td><%= link_to 'Add Game', new_tournament_game_path(tournament) %></td>
Game Model:
Takes me to the view game view with the URL:
http:// local host:3000/tournaments/2/game/new
And view:
<h1>New Game in <%= #tournament.name %> Tournament</h1>
<fieldset>
<%= form_for [:tournament, #game], :url => tournament_game_index_path do |f| %>
<table>
<td>
.... More fields .....
</td>
<div class="form-actions">
<%= f.submit "Create %>
</div>
<% end %>
When create is clicked it yields the error:
undefined method `game_url' for #<GamesController:0xb6131e40>
Questions:
Should I be using nested routes or hidden fields?
Do I need a separate tournament_game controller / view to handle the tournament game calls?
How do I get it to look for the correct create route when clicking the Create button?
When I want to have a relationship between two tables, do I only need the nested resource and the has_many / belongs_to calls or do I still need a foreign key column such as Tournament?
Sorry for all of the questions in one thread. Any help you can offer would be greatly appreciated!
Thank you.
Edit:
The error references line 39 which would be the line for the create controller.
class GamesController < ApplicationController
# GET /game
# GET /game.json
def index
#game = Game.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #game }
end
end
# GET /game/1
# GET /game/1.json
def show
#game = Game.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #game }
end
end
# GET /game/new
# GET /game/new.json
def new
#game = Game.new
#tournament = Tournament.find(params[:tournament_id])
end
# GET /game/1/edit
def edit
#game = Game.find(params[:id])
end
# POST /game
# POST /game.json
def create
#tournament = Tournament.find(params[:tournament_id])
#game = #tournament.game.build(params[:game])
respond_to do |format|
if params[:commit] != 'Cancel'
if #game.save
format.html { redirect_to #game, notice: 'Game was successfully created.' }
format.json { render json: #game, status: :created, location: #game }
format.json { render json: #game }
else
format.html { render action: "new" }
format.json { render json: #game.errors, status: :unprocessable_entity }
end
else
format.html { redirect_to #game, alert: 'Game was not updated.' }
end
end
end
# PUT /game/1
# PUT /game/1.json
def update
#game = Game.find(params[:id])
respond_to do |format|
if params[:commit] != 'Cancel'
if #game.update_attributes(params[:game])
format.html { redirect_to #game, notice: 'Game was successfully updated.' }
format.json { render json: #game }
else
format.html { render action: "edit" }
format.json { render json: #game.errors, status: :unprocessable_entity }
end
else
format.html { redirect_to #game, alert: 'Game was not updated.' }
end
end
end
# DELETE /game/1
# DELETE /game/1.json
def destroy
#game = Game.find(params[:id])
#game.destroy
respond_to do |format|
format.html { redirect_to game_url }
format.json { head :no_content }
end
end
end

Try this:
<%= form_for #game, :url => tournament_games_path(#tournament) do |f| %>
This will call the create method of games controller
Game Controller:
def create
#tournament = Tournament.find(params[:tournament_id])
#game = #tournament.games.build(params[:game])
if #game.save
flash[:success] = "Game created successfully"
redirect_to tournaments_path
else
render new_tournament_game_path
end
end
Routes:
resources :tournaments do
resources :games, :only => [:new, :index, :create, :update, :destroy]
end

Related

Couldn't find Tray with 'id'=

Im creating a garden app that has trays and plants.
tray has_many plants, plant belongs_to tray etc.
Im getting the above error and Im not sure how to assign the tray_id to the new plant being created.
Here is the add plant button in my tray's show view
<%= link_to 'ADD PLANT', new_plant_path(#tray.id), class: "btn btn-raised btn-success hoverable" %>
Here is my plants_controller:
class PlantsController < ApplicationController
before_action :set_plant, only: [:show, :edit, :update, :destroy]
# GET /plants
# GET /plants.json
def index
#plants = Plant.all
end
def show
end
def new
#plant = Plant.new
end
def edit
end
def create
tray = Tray.find(params[:tray_id])
#plant = tray.plants.create(plant_params)
respond_to do |format|
if #plant.save
format.html { redirect_to #plant, notice: 'Plant was successfully created.' }
format.json { render :show, status: :created, location: #plant }
else
format.html { render :new }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #plant.update(plant_params)
format.html { redirect_to #plant, notice: 'Plant was successfully updated.' }
format.json { render :show, status: :ok, location: #plant }
else
format.html { render :edit }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def destroy
#plant.destroy
respond_to do |format|
format.html { redirect_to plants_url, notice: 'Plant was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_plant
#plant = Plant.find(params[:id])
end
def plant_params
params.require(:plant).permit(:title, :notes, :category_id, :tray_id, images_files: [])
end
end
Here is my trays controller
class PlantsController < ApplicationController
before_action :set_plant, only: [:show, :edit, :update, :destroy]
def index
#plants = Plant.all
end
def show
end
def new
#plant = Plant.new
end
def edit
end
def create
tray = Tray.find(params[:tray_id])
#plant = tray.plants.create(plant_params)
respond_to do |format|
if #plant.save
format.html { redirect_to #plant, notice: 'Plant was successfully created.' }
format.json { render :show, status: :created, location: #plant }
else
format.html { render :new }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #plant.update(plant_params)
format.html { redirect_to #plant, notice: 'Plant was successfully updated.' }
format.json { render :show, status: :ok, location: #plant }
else
format.html { render :edit }
format.json { render json: #plant.errors, status: :unprocessable_entity }
end
end
end
def destroy
#plant.destroy
respond_to do |format|
format.html { redirect_to plants_url, notice: 'Plant was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_plant
#plant = Plant.find(params[:id])
end
def plant_params
params.require(:plant).permit(:title, :notes, :category_id, :tray_id, images_files: [])
end
end
Here is my form for creating new plants
<%= form_for(#plant) do |f| %>
<%= f.label 'NAME' %>
<%= f.text_field :title, class: 'form-control', id: 'focusedInput1', placeholder: 'ENTER NAME' %>
etc, etc
<% end %>
What am I doing wrong? Thanks for the help :)
The params[:tray_id] is nil on this line tray = Tray.find(params[:tray_id]) in your Posts controller.
You're also not passing tray_id anywhere in your params. You'll need to properly pass it as a param to your new action:
<%= link_to 'ADD PLANT', new_plant_path(tray_id: #tray.id), class: "btn btn-raised btn-success hoverable" %>
Then add a hidden field to pass :tray_id in your form:
<%= f.hidden_field :tray_id, value: params[:tray_id] %>
Now, you can find tray in your create action using tray = Tray.find(params[:plant][:tray_id]).

Rails How to pass params in cross model system

I am unable to figure out the method to pass params to a link tag. What I want to do is When someone clicks on the Join Group link, the Membership model shall have a new row with group_id as the current group id and the user id as the current user id. The Membership model currently consists of two columns : user_id and group_id that maps users to groups. Can anyone help me with the mistake I am making.
Here is the code
Groups : show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Title:</strong>
<%= #group.title %>
</p>
<p>
<strong>Desc:</strong>
<%= #group.desc %>
</p>
<p>
<strong>Creator:</strong>
<%= #creator.first_name %>
</p>
<%= link_to 'Join Group', memberships_path(:group_id => #group.id, :user_id => current_user.id ), method: :post %>
<%= link_to 'Edit', edit_group_path(#group) %> |
<%= link_to 'Back', groups_path %>
and here is the Memberships controller
class MembershipsController < ApplicationController
before_action :set_membership, only: [:show, :edit, :update, :destroy]
# GET /memberships
# GET /memberships.json
def index
#memberships = Membership.all
end
# GET /memberships/1
# GET /memberships/1.json
def show
#membership = Membership.find(params[:id])
#user = User.find(#membership.user_id)
#group = Group.find(#membership.group_id)
end
# GET /memberships/new
def new
#membership = Membership.new
end
# GET /memberships/1/edit
def edit
end
# POST /memberships
# POST /memberships.json
def create
#membership = Membership.new(membership_params)
respond_to do |format|
if #membership.save
format.html { redirect_to #membership, notice: 'Membership was successfully created.' }
format.json { render :show, status: :created, location: #membership }
else
format.html { render :new }
format.json { render json: #membership.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /memberships/1
# PATCH/PUT /memberships/1.json
def update
respond_to do |format|
if #membership.update(membership_params)
format.html { redirect_to #membership, notice: 'Membership was successfully updated.' }
format.json { render :show, status: :ok, location: #membership }
else
format.html { render :edit }
format.json { render json: #membership.errors, status: :unprocessable_entity }
end
end
end
# DELETE /memberships/1
# DELETE /memberships/1.json
def destroy
#membership.destroy
respond_to do |format|
format.html { redirect_to memberships_url, notice: 'Membership was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_membership
#membership = Membership.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def membership_params
params.require(:membership).permit(:user_id, :group_id)
end
end
You should have a method in your controller that handles adding a user to a group, something like:
class MembershipsController < ApplicationController
...
def join_group
#user = User.find(params[:user]
#user.group_id = params[:group_id].to_i
end
...
end
Then routes.rb needs a path to that controller method:
get 'memberships/join_group' => 'memberships#join_group'
which will result in a path like memberships_join_group_path that you will use in your link_to:
<%= link_to 'Join Group', memberships_join_group_path(:group_id => #group.id, :user_id => current_user.id ) %>
The path you're currently using is sending params to your index method.
try
def create
#member = current_user.members.build(:group_id => params[:group_id])
if #member.save
flash[:notice] = "You have joined this group."
redirect_to members_path
else
flash[:error] = "Unable to join."
redirect_to members_path
end
end
and use memberships instead of members

Undefined local variable in a partial

I'm new to rails and am having a bit of trouble. I am getting an
undefined local variable or method `answer'
error in my _answer.html.erb partial.
Here is my answers_controller.rb:
class AnswersController < ApplicationController
before_action :set_answer, only: [:show, :edit, :update, :destroy]
def index
#question = Question.find params[:question_id]
#question.answers
end
def show
end
def new
#question = Question.find params[:question_id]
end
def edit
end
def create
#question = Question.find(params[:question_id])
#answer = #question.answers.create(answer_params)
respond_to do |format|
if #answer.save
format.html { redirect_to #comment, notice: 'Answer was successfully created.' }
format.json { render action: 'show', status: :created, location: #answer }
else
format.html { render action: 'new' }
format.json { render json: #answer.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #answer.update(answer_params)
format.html { redirect_to #answer, notice: 'Answer was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #answer.errors, status: :unprocessable_entity }
end
end
end
def destroy
#answer.destroy
respond_to do |format|
format.html { redirect_to answers_url }
format.json { head :no_content }
end
end
and my _answer.html.erb file:
<%=div_for(answer) do %>
<div class="questioncontainer">
<p>
<%= answer.body %>
</p>
</div>
<% end %>
If it matters, my resources :answers is nested in resources :questions.
I appreciate any help!
Try using div_for(#answer) instead of answer. When you're communicating between controllers and views, you always do so with #variables. Maybe you should take some time and read this: http://guides.rubyonrails.org/layouts_and_rendering.html

No route matches [PATCH] "/admin/roles.4"

I made model Role with rolify gem.
But controller made to namespace :admin :
class Admin::RolesController < ApplicationController
def index
#roles = Role.all
end
def new
#role = Role.new
end
def create
#role = Role.new(role_params)
respond_to do |format|
if #role.save
format.html { redirect_to admin_role_path(#role), notice: 'Роль создана.' }
format.json { render action: 'show', status: :created, location: #role }
else
format.html { render action: 'new' }
format.json { render json: #role.errors, status: :unprocessable_entity }
end
end
end
def show
#role = Role.find(params[:id])
end
def edit
#role = Role.find(params[:id])
end
def update
respond_to do |format|
if #role.update(role_params)
format.html { redirect_to admin_role_path(#role), notice: 'Роль обновлена.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #role.errors, status: :unprocessable_entity }
end
end
end
def destroy
#role = Role.find(params[:id])
#role.destroy
respond_to do |format|
format.html { redirect_to admin_roles_url }
format.json { head :no_content }
end
end
private
def set_role
#role = Role.find(params[:id])
end
def role_params
params.require(:role).permit(:name)
end
end
When I want to update Role, I open form, edit, click submit and get error:
Routing Error
No route matches [PATCH] "/admin/roles.4"
Please help me.
Based on the form code you pasted above, you'll see that url is pointing to the path used for creates but not updates.
You should be able to update your call to simple_form like so:
= simple_form_for [:admin, #role], :html => { :class => 'form-horizontal' } do |f|
You'll see that you can pass an array with symbolized namespace names and the object instance, and it'll build the URL correctly for both POSTs and PATCHes.
Problem is solved.
In _form I fix url.
= simple_form_for #role, url: admin_role_path(#role), :html => { :class => 'form-horizontal' } do |f|

create new devise user from another non devise controller

I have a users table (Devise) , with a column "admin" (boolean) to qualify my users.
I also have a namespace "Backend".
I would like that my admins users can create new users from the backend namespace.
So I created a Backend::UsersController :
class Backend::UsersController < ApplicationController
layout 'admin'
before_filter :authenticate_user!
def index
#auteurs = User.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #auteurs }
end
end
def new
#auteur = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #auteur }
end
end
def create
#auteur = User.new(params[:auteur])
respond_to do |format|
if #auteur.save
format.html { redirect_to #auteur, notice: 'Article was successfully created.' }
format.json { render json: #auteur, status: :created, location: #auteur }
else
format.html { render action: "new" }
format.json { render json: #auteur.errors, status: :unprocessable_entity }
end
end
end
end
Here's the "_form" partial called in the "new" view :
<%= simple_form_for(#auteur) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :email %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
An here's my routes :
namespace :backend do
resources :articles
root to: "articles#index"
resources :accueil
resources :users
get "users/index"
get "users/create"
get "users/new"
end
devise_for :users
But when I try to access to "backend/users/new", it drives me to this error :
NoMethodError in Backend/users#new
Showing C:/Ruby/acturevue/app/views/backend/users/_form.html.erb where line #1 raised:
undefined method `users_path' for #<#<Class:0x39616b0>:0x416f6d0>
Does somebody have any ideas of the source of the problem ?
Thanks
UPDATE
So, I modified my code like that :
In Backend::UsersController :
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user}
end
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to backend_users_path(#user), notice: 'Article was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
In _form :
<%= simple_form_for(#user) do |f| %>
But I still have the error.
However the backend_users_path exists in y routes :
backend_users GET /backend/users(.:format) backend/users#
index
POST /backend/users(.:format) backend/users#
create
new_backend_user GET /backend/users/new(.:format) backend/users#
new
edit_backend_user GET /backend/users/:id/edit(.:format) backend/users#
edit
backend_user GET /backend/users/:id(.:format) backend/users#
show
PUT /backend/users/:id(.:format) backend/users#
update
DELETE /backend/users/:id(.:format) backend/users#
destroy
You need to use the namespace in your redirect:
redirect_to [:backend, #auteur] #...
See my answer to this question.

Resources