Undefined method _path when controllers combined - ruby-on-rails

I have a PokemonBattles controller in which I have methods create, new and update. Everything works fine with new but not with update. The error I get when I try to access the edit view.
undefined method `pokemon_battle_path' for
#<#<Class:0x007f692e7251c0>:0x007f692e7202d8>
Did you mean? pokemon_battles_path
controller/pokemon_battles_controller.rb
def create
pokemon_a = Pokemon.find(params[:pokemon_battle][:pokemon_a_id])
#pokemon_battle = PokemonBattle.create(pokemon_a_id: pokemon_a.id,
match_status: :upcoming,
pokemon_a_hp: pokemon_a.base_experience,
user_a_id: current_user.id)
redirect_to arena_index_path
end
def new
user = User.find(current_user.id)
#pokemons = user.pokemons
#pokemon_battle = PokemonBattle.new
end
def edit
#pokemon_battle = PokemonBattle.find(params[:id])
end
config/routes.rb
resources :pokemon_battles, only: [:new, :create, :edit]
views/pokemon_battles/edit.html.slim
section
= form_for #pokemon_battle do |f|
- #pokemons.each do |pokemon|
= f.radio_button :pokemon_b_id, pokemon.id
= f.label "pokemon_b_id_#{pokemon.id}", pokemon.name
= f.submit 'Choose', class: 'btn btn-primary'

Related

create an instance of a model by clicking a button

I am pretty new to Ruby and I am working on a hangman game .
What I am trying to do is create a new game when the user simply click on a button and I want that "click" to redirect to the show of that game.
Here are my models :
class Game < ApplicationRecord
has_many :guesses
end
class Guess < ApplicationRecord
belongs_to :game
end
Here are my controllers :
class GamesController < ApplicationController
skip_before_action :authenticate_user!
def index
#games = Game.all
end
def create
#game = Game.new(game_params)
#game.save!
redirect_to game_path(#game)
end
def show
#game = Game.new
#game = Game.last
end
def destroy
#game = Game.find(params[:id])
#game.destroy
redirect_to home_path
end
private
words =[
"spokesperson", "firefighter", "headquarters", "confession", "difficulty", "attachment", "mechanical",
"accumulation", "hypothesis", "systematic", "attraction", "distribute", "dependence", "environment",
"jurisdiction", "demonstrator", "constitution", "constraint", "consumption", "presidency", "incredible",
"miscarriage", "foundation", "photography", "constituency", "experienced", "background", "obligation",
"diplomatic", "discrimination", "entertainment", "grandmother", "girlfriend", "conversation", "convulsion",
"constellation", "leadership", "insistence", "projection", "transparent", "researcher", "reasonable","continental",
"excavation", "opposition", "interactive", "pedestrian", "announcement", "charismatic", "strikebreaker",
"resolution", "professional", "commemorate", "disability", "collection", "cooperation", "embarrassment",
"contradiction", "unpleasant", "retirement", "conscience", "satisfaction", "acquaintance", "expression",
"difference", "unfortunate", "accountant", "information", "fastidious", "conglomerate", "shareholder",
"accessible", "advertising", "battlefield", "laboratory", "manufacturer", "acquisition", "operational",
"expenditure", "fashionable", "allocation", "complication", "censorship", "population", "withdrawal",
"sensitivity", "exaggerate", "transmission", "philosophy", "memorandum", "superintendent", "responsibility",
"extraterrestrial", "hypothesize", "ghostwriter", "representative", "rehabilitation", "disappointment",
"understanding", "supplementary", "preoccupation"
]
#word_to_guess = words.sample
#health_bar = 5
#game_status = "Game not started yet"
def game_params
params.require(:game).permit(#word_to_guess, #health_bar, #game_status)
end
end
Here is what I have been trying to do
<%= link_to "nouvelle partie", game_path(game), method: :create %>
but the errors message is :
"undefined local variable or method `game' for #ActionView::Base:0x0000000000d4d0"
POST method won't work with link_to. Try using the to button_to instead of link_to like this:
<%= button_to "nouvelle partie", game_path(game), method: :post %>
I think the bug is due to the variable game not being passed to partial. You have to pass it on like this:
<%= render "game", game: #game %>
And you don't have to pass variables in game_params. You only need to set them in the show method where you will be redirected from the create method. Also, you don't set the current game like this Game.last, you just take id which is contained in the url.
def create
#game = Game.new
#game.save!
redirect_to game_path(#game)
end
def show
#game = Game.find(params[:id])
#word_to_guess = words.sample
#health_bar = 5
#game_status = "Game not started yet"
end
have you tried?
<%= link_to "nouvelle partie", game_path(#game), method: :create %>

Delete Button Not Working - Not Sure What is Wrong

all,
I tried this:
<h9>Thursday</h9>
<% #thursday.each do |chorelist| %><br>
<p2><%= chorelist.name %></p2>
<%= button_to "delete", chorelists_destroy_path(:id, chorelist.id) %>
<% end %>
It won't do the trick, however.
As you can see, I am trying to add a delete button with each iteration. What am I missing here?
I'm still new to Rails, so any help will be most appreciated.
Addendum: I received this error message when using that latter method:
"Couldn't find Chorelist with 'id'={:name=>"Sweep Floors", :day=>"Sunday", :user_id=>2}"
I checked the console, and those parameters are all there.
class SaveListController < ApplicationController
before_filter :authenticate_user!
def index
#chorelist = Chorelist.create(user_id: params[:user_id], chore_id: params[:chore_id], day: params[:day], name: params[:chore_name])
redirect_to pick_chores_path
end
def display
#chorelist = Chorelist.all
#monday = #chorelist.where("day = 'Monday'", user_id: current_user.id)
#tuesday = #chorelist.where("day = 'Tuesday'", user_id: current_user.id)
#wednesday = #chorelist.where("day = 'Wednesday'", user_id: current_user.id)
#thursday = #chorelist.where("day = 'Thursday'", user_id: current_user.id)
#friday = #chorelist.where("day = 'Friday'", user_id: current_user.id)
#saturday = #chorelist.where("day = 'Saturday'", user_id: current_user.id)
#sunday = #chorelist.where("day = 'Sunday'", user_id: current_user.id)
end
def destroy
#chorelist = Chorelist.find(id: params[:id])
#chorelist.destroy
redirect_to show_chores_path
end
end
Rails.application.routes.draw do
resources :chorelists
get 'about' => 'welcome#about'
get 'contact' => 'welcome#contact'
root 'welcome#index'
get 'about' => 'welcome#about'
get 'pick_chores' => 'pick_chores#index'
post 'save_list' => 'save_list#index'
get 'show_chores' => 'save_list#display'
post 'chorelists_destroy' => 'save_list#destroy'
resources :chores
devise_for :users
end
Change :id, chorelist.id to id: chorelist.id
<h9>Thursday</h9>
<% #thursday.each do |chorelist| %><br>
<p2><%= chorelist.name %></p2>
<%= button_to "delete", chorelists_destroy_path(id: chorelist.id) %>
<% end %>
On controller
def destroy
#chorelist = Chorelist.find(params[:id])
#chorelist.destroy
# do your things
end

Rails routes option "as", can't edit resource

In my application I have model "Regulation", form for creating regulations looks like this:
- if %W(edit update).include? action_name
= content_for :heading, t('partners.regulations.edit')
- else
= content_for :heading, t('partners.regulations.new')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation] do |f|
= f.error_notification
%ul.nav.nav-pills
%li
= link_to image_tag("flag_pl.png"), '#PL', class: 'regulation_pl'
%li
= link_to image_tag("flag_en.png"), '#EN', class: 'regulation_en'
.polish_regulation
%h1.page-header
= t('partners.regulations.polish')
= f.input :content_pl, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Pure', width: 750} }, error: false
.english_regulation
%h1.page-header
= t('partners.regulations.english')
= f.input :content_en, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Basic', width: 750} }, error: false
- if %W(edit update).include? action_name
= f.submit t('actions.save_changes'), class: "btn btn-lg btn-default"
- else
= f.submit t('partners.regulations.save'), class: "btn btn-lg btn-default"
In my routes I have:
namespace :partners do
resources :regulations, as: :rental_company_regulation, except: :show
end
My controller looks like this:
module Partners
class RegulationsController < ApplicationController
include Partners::BaseController
load_and_authorize_resource through: :rental_company, singleton: true
before_action :set_breadcrumbs
before_action :set_regulation, only: :new
def new
if #rental_company_regulation
redirect_to edit_partners_rental_company_regulation_path(#rental_company_regulation)
end
add_breadcrumb t('partners.regulations.new')
end
def create
if #regulation.save
flash[:notice] = t('partners.regulations.created')
redirect_to partners_root_path
else
add_breadcrumb t('partners.regulations.new')
render :new
end
end
def edit
add_breadcrumb t('partners.regulations.edit')
end
def update
if #regulation.update(regulation_params)
flash[:notice] = t('partners.regulations.updated')
redirect_to partners_root_path
else
add_breadcrumb t('partners.regulations.edit')
render :edit
end
end
protected
def set_regulation
#rental_company_regulation = Regulation.where(rental_company_id: rental_company).first
end
def set_breadcrumbs
add_breadcrumb current_partner.rental_company.name, :partners_root_path
end
private
def regulation_params
params.require(:regulation).permit(:content_pl, :content_en, :rental_company_id)
end
end
end
Creating resource from scratch works properly. But I went to:
"http://localhost:3000/partners/regulations/4/edit" to edit regulation I have the following error:
undefined method `partners_regulation_path' for #<#<Class:0x0000000242fae8>:0x00000007d9afb0>
I can't solve this problem. What's wrong?
Edit:
Rake routes:
partners_rental_company_regulation_index GET /partners/regulations(.:format) partners/regulations#index
POST /partners/regulations(.:format) partners/regulations#create
new_partners_rental_company_regulation GET /partners/regulations/new(.:format) partners/regulations#new
edit_partners_rental_company_regulation GET /partners/regulations/:id/edit(.:format) partners/regulations#edit
partners_rental_company_regulation PATCH /partners/regulations/:id(.:format) partners/regulations#update
Edit2:
I've changed my form too looks like this:
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_path
Now I can edit exisiting resource but can't create a new one. When I trying to create the new one I have the following error:
No route matches {:action=>"update", :controller=>"partners/regulations"} missing required keys: [:id]
What's wrong?
as
To simplify user2675613's answer, your error is basically caused by using the as argument in your routes
as: basically allows you to "name" the route:
#config/routes.rb
resources :users # -> users_path
resources :users, as: :members # -> members_path
Error
Your error is as follows:
undefined method `partners_regulation_path'
This basically means you're using a path which doesn't exist. This is because you've used the as: option in your routes:
#config/routes.rb
resources :partners do
resources :regulations #-> partners_regulation_path
end
resources :partners do
resources :regulations, as: "test" # -> partners_test_path
end
This is confirmed with your routes:
partners_rental_company_regulation_index
new_partners_rental_company_regulation
edit_partners_rental_company_regulation
partners_rental_company_regulation
Fix
The way to fix this is to remove the as: option from your routes:
#config/routes.rb
resources :partners do
resources :regulations #-> partner_regulations_path
end
Alternatively, if you wanted to keep the custom name for your paths, you'll have to change your path references to parental_company_regulation_path
As you can see you in your rake routes your url to edit a regulation is edit_partners_rental_company_regulation GET /partners/regulations/:id/edit(.:format) and to create a new one the url is new_partners_rental_company_regulation GET /partners/regulations/new(.:format).
You need to change the way you are using your form here. You can create a partial for all the common fields of form but you need to separate the url part in your form to make a create and update requests.
You can make a partial _form.html.haml with contents:
= f.error_notification
%ul.nav.nav-pills
%li
= link_to image_tag("flag_pl.png"), '#PL', class: 'regulation_pl'
%li
= link_to image_tag("flag_en.png"), '#EN', class: 'regulation_en'
.polish_regulation
%h1.page-header
= t('partners.regulations.polish')
= f.input :content_pl, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Pure', width: 750} }, error: false
.english_regulation
%h1.page-header
= t('partners.regulations.english')
= f.input :content_en, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Basic', width: 750} }, error: false
Then inside your edit.html.haml you can have:
= content_for :heading, t('partners.regulations.edit')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_path do |f|
= render :partial => "form", :locals => { :f => f } #you need to pass other required locals too else it'll give error
= f.submit t('actions.save_changes'), class: "btn btn-lg btn-default"
Similarly inside your new.html.haml you can have:
= content_for :heading, t('partners.regulations.new')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_index_path do |f|
= render :partial => "form", :locals => { :f => f } #you need to pass other required locals too else it'll give error
= f.submit t('partners.regulations.save'), class: "btn btn-lg btn-default"

Rails 4 Cannot access hash in nested form (undefined method `[]' for nil:NilClass)

I've build quite complex form which creates one prescription with many realtions. I am using this syntax in view:
- provide(:title, 'Create prescription')
%h1 Add medicines to prescription
.row
.span6.offset3
= form_for #prescription do |f|
= render 'shared/error_prescription_messages'
%p
= f.hidden_field :patient_id, :value => params[:patient_id]
= f.hidden_field :user_id, :value => current_user.id
= f.fields_for :relations do |builder|
= render 'child_form', :f => builder
%p= f.submit "Submit"
chlid_form is quite simple :
- it=f.options[:child_index].to_i
- n= it.to_s
%h2
= "Medicine ##{it+1}"
= f.hidden_field :medicine_id, :id => "my_medicine_id#{it}"
- if params[:prescription].nil? || params[:prescription][:relations_attributes][n.to_sym][:medicine_name].nil?
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path, :id_element => "#my_medicine_id#{it}"
- else
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path, :id_element => "#my_medicine_id#{it}", :value => params[:prescription][:relations_attributes][n.to_sym][:medicine_name]
= f.label :amount, "Amount of medicine boxes"
= f.number_field :amount, :value => 1
= f.label :daily
= f.number_field :daily, :value => 1
= f.label :period_in_days, "Duration of treatment (in days)"
= f.number_field :period_in_days, :value => 1
So as you can see I'm using f.options[:child_index] to get index of child (0,1,2...) cause I generate multiple items with this particular form. I then put it to variable it and sucessfully use it in :id_element => "#my_medicine_id#{it}" which works PERFECTLY fine (creates my_medicine_id0, my_medicine_id1 ....) Although it doesn't work in this line:
:value => params[:prescription][:relations_attributes][n.to_sym][:medicine_name]
where n is just n=it.to_s.
I though somethings wrong in controller but if I change this line to whatever
:value => params[:prescription][:relations_attributes]**[:'0']**[:medicine_name] or any other integer from 0 to 4 everything works great, but I NEED dynamic change in this one. So I got proof that it DOES work because it generates integer fine here "#my_medicine_id#{it}" but won't work in hash! And when I print the whole hash from params I get this:
{"patient_id"=>"7", "user_id"=>"1", "relations_attributes"=>{"0"=>{"medicine_id"=>"13490", "medicine_name"=>"Locacid 500 mcg/g (0,05%) (1 tuba 30 g)", "amount"=>"0", "daily"=>"1", "period_in_days"=>"1"}, "1"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "2"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "3"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "4"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}}}
so to get the values I need it's pretty obvious that
params[:prescription][:relations_attributes][SOME_KIND_OF_INETEGER][:medicine_name] should work, but doesn't.
Controller code:
class PrescriptionsController < ApplicationController
before_action :signed_in_user
before_action :doctor_user, only: [:new, :create]
before_action :pharmacist_user, only: [:update]
def new
#prescription =Prescription.new
5.times { #prescription.relations.build }
end
def create
#prescription = Prescription.new(new_prescription_params)
if #prescription.save
flash[:success] = "Prescription created."
redirect_to #prescription
else
5.times { #prescription.relations.build }
render 'new', :prescription => params[:prescription]
end
end
def show
#prescription = Prescription.find(params[:id])
#medicines = #prescription.medicines.paginate(page: params[:page], :per_page => 10)
end
def update
#prescription = Prescription.find(params[:id])
#patient = Patient.find(params[:patient_id])
if !prescription_expired?(#prescription)
#prescription.realized = 1
if #prescription.save
flash[:success] = "Prescription realized."
redirect_to #patient
else
redirect_to root_url
end
else
flash[:notice] = "Can't realize, prescription expired."
redirect_to #patient
end
end
private
def new_prescription_params
params.require(:prescription).
permit(:patient_id, :user_id, relations_attributes: [:medicine_id, :medicine_name, :amount, :daily, :period_in_days])
end
def doctor_user
redirect_to(root_url) unless current_user.function == "doctor"
end
def pharmacist_user
redirect_to(root_url) unless current_user.function == "pharmacist"
end
def prescription_expired?(presc)
presc.created_at < 1.month.ago
end
def signed_in_user
unless signed_in?
store_location
flash[:notice] = "Please log in."
redirect_to login_url
end
end
end
I run out of ideas so I ask you guys if anyone can help. Thanks.
There is no point in using params in your view since you already assigned those to your models. Also when you rendering your new action, those params doesn't exist as nothing has been send to the server yet. Just get rid of all the values from inputs.
Your partial should look like:
- it=f.options[:child_index].to_i
- n= it.to_s
%h2
= "Medicine ##{it+1}"
= f.hidden_field :medicine_id, :id => "my_medicine_id#{it}"
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path
= f.label :amount, "Amount of medicine boxes"
= f.number_field :amount
= f.label :daily
= f.number_field :daily
= f.label :period_in_days, "Duration of treatment (in days)"
= f.number_field :period_in_days
If you want your fields to have default value, set default value inside your database.

get and post method in controller. Ruby on Rails

I trying rewrite some data in model. Change_settings is GET-method, update_settings is POST. After click SUBMIT happens nothing. Data not change. Help me, please( what's wrong?
controller
def change_settings
#vacation_days = current_company.vacation_days
#illnes_days = current_company.illnes_days
end
def update_settings
current_company.update_attribute(:vacation_days, :illnes_days)
current_company.save
redirect_to account_company_path, notice: t('company.settings_changed')
end
change_settings view
.company_settings
= form_tag update_settings_company_path do
= field_set_tag do
= label_tag 'vacation_days'
= text_field_tag :vacation_days
= label_tag 'illnes_days'
= text_field_tag :illnes_days
%br
= submit_tag t('common.save'), class: 'btn'
= link_to t('common.back'), account_company_path, class: 'btn'
routes
resource :company, only: :all do
get :account
get :change_settings
post :update_settings
end
replace:
current_company.update_attribute(:vacation_days, :illnes_days)
current_company.save
with:
current_company.update_attributes(vacation_days: params[:vacation_days], illnes_days: params[:illnes_days] )
Basically you were not taken data sent from client into account

Resources