Ruby on Rails/How to Scaffold form link to specific action? - ruby-on-rails

My scaffold model doesn't work well with create action.
I found out that if I press submit button, it is linked to TalksController#index but it should be linked to TalksController#create
I don't know how I can fix it to link to create action. There aren't any codes related to it in _form.html.erb and new.html.erb
Create worked well 2 days ago.
[edit]I post my codes.
I added some codes in addition to the codes scaffold made itself
talks_controller.rb
class TalksController < ApplicationController
before_action :set_talk, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [ :index, :show, :all ]
# GET /talks
# GET /talks.json
def all
#talks = Talk.all
#talks = Talk.order(created_at: :desc)
end
def index
#talks = Talk.all
#talks = Talk.order(created_at: :desc)
#whichboard = params[:whichboard]
#seq = params[:saveit]
#title = params[:savetitle]
end
# GET /talks/1
# GET /talks/1.json
def show
end
# GET /talks/new
def new
#talk = Talk.new
#seq = params[:seq]
#whichboard = params[:whichboard]
end
# GET /talks/1/edit
def edit
authorize_action_for #talk
end
# POST /talks
# POST /talks.json
def create
#talk = Talk.new(talk_params)
#talk.user_id = current_user
#talk.seq = params[:talk][:seq]
#talk.where = params[:talk][:where]
respond_to do |format|
if #talk.save
format.html { redirect_to #talk, notice: 'Talk was successfully created.' }
format.json { render :index, status: :created, location: #talk }
else
format.html { render :new }
format.json { render json: #talk.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /talks/1
# PATCH/PUT /talks/1.json
def update
authorize_action_for #talk
respond_to do |format|
if #talk.update(talk_params)
format.html { redirect_to #talk, notice: 'Talk was successfully updated.' }
format.json { render :show, status: :ok, location: #talk }
else
format.html { render :edit }
format.json { render json: #talk.errors, status: :unprocessable_entity }
end
end
end
# DELETE /talks/1
# DELETE /talks/1.json
def destroy
authorize_action_for #talk
#talk.destroy
respond_to do |format|
format.html { redirect_to talks_url, notice: 'Talk was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_talk
#talk = Talk.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def talk_params
params.require(:talk).permit(:content, :user_id, :seq, :where)
end
end
_form.html.erb
<%= simple_form_for(#talk) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :content %>
<%#= f.association :user %>
<%= f.input :seq, :as => :hidden, :input_html => { :value => #seq } %>
<%= f.input :where, :as => :hidden, :input_html => { :value => #whichboard } %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
new.html.erb
<div class="row">
<div class='col-md-12'>
<p style='text-align:right;'>
created by <%= current_user.name %>, Current Time : <%= Time.now %>, board <%= #whichboard %> seq <%= #seq %>
</p>
</div>
</div>
<%= render 'form' %>
<%= link_to 'Back', talks_path %>
[SECOND EDIT] routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
root 'cpu#index'
post ':controller(/:action(/:id(.:format)))'
get ':controller(/:action(/:id(.:format)))'
resources :talks
end

adjust your routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
root 'cpu#index'
resources :talks
#do you really need these?
post ':controller(/:action(/:id(.:format)))'
get ':controller(/:action(/:id(.:format)))'
end
to put the resources :talks above the default/catchall routes. the routes are processed on first match, so if you need those default/catchalls youcan put them at the bottom. That being said, unless you have a requirement for them most modern rails apps don't require them by default, so you can probably comment out / remove them as another option.

The index and create both refer to the same url or the same route method, the only difference is the method if you use the method as post then, it'll go to create otherwise it goes to index. But, you could implicitly handle this if you pass in the new instance of the object you are trying to create such as #customer = Customer.new then, pass #customer to the form_for method.

With the form_for method, you can specify url of the action you want to be executed or just controller and action like this:
<%= form_for #post, :url => {:controller => "your-controller-name", :action => "your-action-name"} do |f| %>
And in your action ("your-action-name") you can call your parameters like:
post_id = params[:post][:id]
Hope that will help you.

Related

collection_select is not creating the association table

I'm currently trying to add a collection_select of ranches to my staff
And I saw that it's better to create an extra table to make this association.
And I follow some tutorial, but is not working on my side
This is my code :
Staffs/_form :
<%= form_for(#staff) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<%= fields_for(#staff_ranch) do |x| %>
<div class="field">
<%= x.collection_select(:ranch_id, #all_ranch, :id, :name, { }, {:multiple => true}) %>
</div>
<%end%>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My models :
- Ranch :
has_many :ranchstaffs
has_many :staffs, :through => :ranchstaffs
- Staff :
has_many :ranchstaffs
has_many :ranches, :through => :ranchstaffs
-Ranchstaff :
belongs_to :ranch
belongs_to :staff
Staff controller :
class StaffsController < ApplicationController
before_action :set_staff, only: [:show, :edit, :update, :destroy]
# GET /ranches
# GET /ranches.json
def index
#staffs = current_user.staffs
end
# GET /ranches/1
# GET /ranches/1.json
def show
end
# GET /ranches/new
def new
#staff = Staff.new
#all_ranch = current_user.ranches
#staff_ranch = #staff.ranchstaffs.build
end
# GET /ranches/1/edit
def edit
end
# POST /ranches
# POST /ranches.json
def create
#staff = Staff.new(staff_params)
#staff.update(user_id: current_user.id)
respond_to do |format|
if #staff.save
format.html { redirect_to #staff, notice: 'Staff was successfully created.' }
format.json { render :show, status: :created, location: #staff }
else
format.html { render :new }
format.json { render json: #staff.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /ranches/1
# PATCH/PUT /ranches/1.json
def update
respond_to do |format|
if #staff.update(staff_params)
format.html { redirect_to #staff, notice: 'Staff was successfully updated.' }
format.json { render :show, status: :ok, location: #staff }
else
format.html { render :edit }
format.json { render json: #staff.errors, status: :unprocessable_entity }
end
end
end
# DELETE /ranches/1
# DELETE /ranches/1.json
def destroy
#staff.destroy
respond_to do |format|
format.html { redirect_to staffs_url, notice: 'Ranch was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_staff
#staff = Staff.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def staff_params
params.require(:staff).permit(:name, :user_id, :cat, :ranch_id)
end
end
Can you explain me why the model ranchstaff was not created after a creation of a new staff ?
As you are using fields_for you are using nested form but you are not permitting the parameters properly. First make change in your form:
<%= f.fields_for(#staff_ranch) do |x| %>
<div class="field">
<%= x.collection_select(:ranch_id, #all_ranch, :id, :name, { }, {:multiple => true}) %>
</div>
<% end %>
And then in your controller:
def staff_params
params.require(:staff).permit(:name, :user_id, :cat, ranchstaff_attributes: [ranch_id: []])
end
And in your Staff model write:
accepts_nested_attributes_for :ranchstaffs
Then your ranchstaff should be created when the User is being created.
Your ranch_id is coming in an array. So u have to specify that ranch_id would be array in strong parameters.
so your staff_params method would look like this
def staff_params
params.require(:staff).permit(:name, :user_id, :cat, :staff_ranch_attributes =>[:ranch_id => []])
end

Rails, edit link will redirect but update button won't work

In my rails app I have this edit form that does not seem to work properly. If I enter the edit-site through any link, everything will look fine but the form submit button will not work. If I refresh the window it works fine.
Edit.html.erb
<div class="alien-choice">
<h2 class="player_name"><%= current_user.username %></h2>
<p> Choose <span>0</span>/2 Power</p>
<%= form_for [#gameround, #currentplayer] do |f| %>
<% alleflares = #currentplayer.flares %>
<% alleflares.each { |val|
printAlien = Alien.find_by_title(val)
%>
<div class="alien_wrap">
<h3><%= printAlien.title %> <span>[<%= printAlien.expansion.abbr %>]</span></h3>
<label for="<%= printAlien.title %>">
<div class="alien" style="background-image: url(<%= printAlien.avatar.url %>)">
</label>
<%= f.check_box(:aliens, { :multiple => true, :id => printAlien.title, :class => 'choosealiens'}, printAlien.title, nil) %>
</div>
</div>
<% } %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= link_to 'Back', gameround_currentplayers_path %>
The controller
class CurrentplayersController < ApplicationController
before_action :set_currentplayer, only: [:show, :edit, :update]
# GET /currentplayers
# GET /currentplayers.json
def index
#currentplayers = Currentplayer.all
end
# GET /currentplayers/1
# GET /currentplayers/1.json
def show
#gameround = Gameround.find(params[:gameround_id])
#currentplayer = #gameround.currentplayers.find(params[:id])
current_user
end
# GET /currentplayers/new
def new
#gameround = Gameround.find(params[:gameround_id])
#currentplayer = Currentplayer.new
end
# GET /currentplayers/1/edit
def edit
#gameround = Gameround.find(params[:gameround_id])
#currentplayer = #gameround.currentplayers.find(params[:id])
end
# POST /currentplayers
# POST /currentplayers.json
def create
#gameround = Gameround.find(params[:gameround_id])
#currentplayer = #gameround.currentplayers.create(currentplayer_params);
respond_to do |format|
if #currentplayer.save
format.html { redirect_to #gameround, notice: 'Currentplayer was successfully created.' }
format.json { render :show, status: :created, location: #currentplayer }
else
format.html { render :new }
format.json { render json: #currentplayer.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /currentplayers/1
# PATCH/PUT /currentplayers/1.json
def update
#gameround = Gameround.find(params[:gameround_id])
#currentplayer = #gameround.currentplayers.find(params[:id])
if #currentplayer.update(currentplayer_params)
redirect_to gameround_currentplayer_path
else
render 'edit'
end
end
# DELETE /currentplayers/1
# DELETE /currentplayers/1.json
def destroy
#gameround = Gameround.find(params[:gameround_id])
#currentplayer = #gameround.currentplayers.find(params[:id])
#currentplayer.destroy
respond_to do |format|
format.html { redirect_to '/play', notice: 'Currentplayer was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_currentplayer
#currentplayer = Currentplayer.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def currentplayer_params
params.require(:currentplayer).permit(:log_id, :flares, :winner, :bases, :gameround_id, aliens:[])
end
end
config.routes
Rails.application.routes.draw do
resources :gamerounds do
resources :currentplayers
end
I figured it out. It was just because the submit button was outside of the main div. Sorry for the trouble!
You want to create your routes into config/routes.rb as follows:
resources :current_players

Rails : error param is missing or the value is empty : annonce

I want to creat a classified ads website for a project in school and I try to create a form to send a message by email at a member of the website. The email adress is contained in a model which is name "Membre" and this model is link at a model who is name "Annonce" which contained the ad.
But when I try to create that, I have this error :
param is missing or the value is empty: annonce
app/controllers/annonces_controller.rb:104:in `annonce_params'
app/controllers/annonces_controller.rb:29:in `create'
Here the Ad controller :
class AnnoncesController < ApplicationController
before_action :set_annonce, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, :except => [:index]
# GET /annonces
# GET /annonces.json
def index
#annonces = Annonce.all
end
# GET /annonces/1
# GET /annonces/1.json
def show
end
# GET /annonces/new
def new
#annonce = Annonce.new
end
# GET /annonces/1/edit
def edit
end
# POST /annonces
# POST /annonces.json
def create
#annonce = Annonce.new(annonce_params)
#annonce.membre_id = current_membre.id
respond_to do |format|
if #annonce.save
format.html { redirect_to #annonce, notice: t('annonce_cree_succes') }
format.json { render :show, status: :created, location: #annonce }
else
format.html { render :new }
format.json { render json: #annonce.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /annonces/1
# PATCH/PUT /annonces/1.json
def update
respond_to do |format|
if #annonce.update(annonce_params)
format.html { redirect_to #annonce, notice: t('annonce_cree_succes') }
format.json { render :show, status: :ok, location: #annonce }
else
format.html { render :edit }
format.json { render json: #annonce.errors, status: :unprocessable_entity }
end
end
end
# DELETE /annonces/1
# DELETE /annonces/1.json
def destroy
#annonce.destroy
respond_to do |format|
format.html { redirect_to annonces_url, notice: t('annonce_destroy_succes') }
format.json { head :no_content }
end
end
# GET /annonces/contact/1
def contact
#form_contact = FormContact.new
if #form_contact.valid?
#MembreMailer.email_contact(Membre.where(:id => #annonce.membre_id ),current_membre,#annonce,#message)
#annonce = Annonce.find(params[:id])
#recepteur = Membre.where(:id => #annonce.membre_id )
#membre = current_membre
mail(:to => "#{recepteur.pseudo} <#{recepteur.email}>", subject: 'Reponse à l\'une de vos annnonces')
redirect_to root
end
end
# GET /annonces/report/1
def report
#annonce = Annonce.find(params[:id])
end
private
def authenticate_user!
if membre_signed_in?
#super
else
redirect_to login_path, :notice => 'Merci de vous connecter pour effecter cette action'
## if you want render 404 page
## render :file => File.join(Rails.root, 'public/404'), :formats => [:html], :status => 404, :layout => false
end
end
# Use callbacks to share common setup or constraints between actions.
def set_annonce
#annonce = Annonce.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def annonce_params
params.require(:annonce).permit(:id, :titre, :corps, :prix, :membre_id, :categorie, :created_at, :image)
end
Here the view contact :
<div class="col-md-offset-2 col-md-8 well panel panel-default">
<h2 class='panel-heading text-center'><%= t('contacter') %></h2>
<div class="panel-body text-center">
<%= form_for(:form_contact, :url => {:action => :create}) do |f| %>
<div class="field block-center">
<%= f.label "message" %></br>
<%= f.text_area(:message, size: "50x15")%>
</div></br>
<div class="actions form-group col-md-offset-3 col-md-6">
<%= submit_tag t('envoyer'), :class => "btn btn-large btn-block btn-primary" %>
</div>
<% end %>
</div>
</div>
<p class='row'> </p>
And here the FormContact class:
class FormContact < ActiveForm::Base
attr_accessor :message
validates_presence_of :message
def new
#form_contact = FormContact.new(login_form)
end
def index
#form_contact = FormContact.new
end
private
def login_form
params.require(:form_contact).permit(:message)
end
end
How can I fix that ?
Thanks in advance
This is routing error, you should call the create method of FormContactsController, not AnnoncesController create method.
<%= form_for(:form_contact, :url => {:controller => "FormContactsController", :action => :create}) do |f| %>

undefined method `first_name'

Can anyone shed light on this for me?
undefined method `first_name' for #
Here is the show.html
<p id="notice"><%= notice %></p>
<div id="container">
<p>
<b>First name:</b>
<%= #artist.firstname %>
</p>
<p>
<b>Second name:</b>
<%= #artist.surname %>
</p>
<p>
<b>About:</b>
<%= #artist.about %>
</p>
<div id="comments">
<h2>Comments</h2>
<%= render :partial => "shared/comment", :collection => #artist.comments%>
</div
</div>
<%= render :partial => "image", :collection => #artist.images %>
<%= link_to 'Edit', edit_artist_path(#artist) %> |
<%= link_to 'Back', artists_path %>
<%= link_to 'show', images_path %>
Here is the partial
<div class="comment">
<p>
<span class="commentator"><%= comment.commentator.display_name %>
say's</span>
<%= comment.comment %>
</p>
</div
Here is the friend view
class Friends < ActiveRecord::Base
attr_accessible :firstname, :surname
has_many :comments, :as => :commentator, :class_name =>"Commentable"
def display_name
"#{self.firstname} #{self.surname}"
end
end
This is the friends controller
class FriendsController < ApplicationController
# GET /friends
# GET /friends.xml
def index
#friends = Friend.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #friends }
end
end
# GET /friends/1
# GET /friends/1.xml
def show
#friend = Friend.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #friend }
end
end
# GET /friends/new
# GET /friends/new.xml
def new
#friend = Friend.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #friend }
end
end
# GET /friends/1/edit
def edit
#friend = Friend.find(params[:id])
end
# POST /friends
# POST /friends.xml
def create
#friend = Friend.new(params[:friend])
respond_to do |format|
if #friend.save
format.html { redirect_to(#friend, :notice => 'Friend was successfully created.') }
format.xml { render :xml => #friend, :status => :created, :location => #friend }
else
format.html { render :action => "new" }
format.xml { render :xml => #friend.errors, :status => :unprocessable_entity }
end
end
end
# PUT /friends/1
# PUT /friends/1.xml
def update
#friend = Friend.find(params[:id])
respond_to do |format|
if #friend.update_attributes(params[:friend])
format.html { redirect_to(#friend, :notice => 'Friend was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #friend.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /friends/1
# DELETE /friends/1.xml
def destroy
#friend = Friend.find(params[:id])
#friend.destroy
respond_to do |format|
format.html { redirect_to(friends_url) }
format.xml { head :ok }
end
end
end
I am trying to make it so a friend can leave a comment on an artists page but I keep getting the above error.
I am very new to Ruby so I apologise if I have left anything out.
Basically, rails will look at the database to figure out what fields are on a model. So make sure your migrations have been run, and that first_name exists on the db table.
Also, Friends is plural. In rails, your table is plural (friends), your model is singular (Friend), and your controller is plural (FriendsController). It is best not to go against this convention. Try renaming the model and see what happens
This error related to database that first_name don't exist in your db.Run migration carefully.
You need line 2 of the Friend class to be attr_accessible :firstname, :surname so your views have access to the those variables.

rails: "unknown action" message when action is clearly specified

I had hard time to figure out why I've been getting "unknown action" error message when I was do some editing:
Unknown action
No action responded to 11. Actions: bin, create, destroy, edit, index, new, observe_new, show, tag, update, and vote
you can see that Rails did mention each action in the above list - update. And in my form, I did specify action = "update".
I wonder if some friends could kindly help me with the missing links...
here is the code:
edit.rhtml
<h1>Editing tip</h1>
<% form_tag :action => 'update', :id => #tip do %>
<%= render :partial => 'form' %>
<p>
<%= submit_tag_or_cancel 'Save Changes' %>
</p>
<% end %>
_form.rhtml
<%= error_messages_for :tip %>
<p><label>Title<br/>
<%= text_field :tip, :title %></label></p>
<p><label>Categories<br/>
<%= select_tag('categories[]', options_for_select(Category.find(:all).collect {|c| [c.name, c.id] }, #tip.category_ids), :multiple => true ) %></label></p>
<p><label>Abstract:<br/>
<%= text_field_with_auto_complete :tip, :abstract %></label></p>
<p><label>Name: <br/>
<%= text_field :tip, :name %></label></p>
<p><label>Link: <br/>
<%= text_field :tip, :link %></label></p>
<p><label>Content<br/>
<%= text_area :tip, :content, :rows => 5 %></label></p>
<p><label>Tags <span>(space separated)</span><br/>
<%= text_field_tag 'tags', #tip.tag_list, :size => 40 %></label></p>
class TipsController < ApplicationController
before_filter :authenticate, :except => %w(index show)
# GET /tips
# GET /tips.xml
def index
#tips = Tip.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #tips }
end
end
# GET /tips/1
# GET /tips/1.xml
def show
#tip = Tip.find_by_permalink(params[:permalink])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #tip }
end
end
# GET /tips/new
# GET /tips/new.xml
def new
#tip = session[:tip_draft] || current_user.tips.build
end
def create
#tip = current_user.tips.build(params[:tip])
#tipMail=params[:email]
#if tipMail
# TipMailer.deliver_email_friend(params[:email], params[:name], tip)
# flash[:notice] = 'Your friend has been notified about this tip'
#end
#tip = current_user.tips.build(params[:tip])
#tip.categories << Category.find(params[:categories]) unless params[:categories].blank?
#tip.tag_with(params[:tags]) if params[:tags]
if #tip.save
flash[:notice] = 'Tip was successfully created.'
session[:tip_draft] = nil
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def edit
#tip = Tip.find(params[:id])
end
def update
#tip = Tip.find(params[:id])
respond_to do |format|
if #tip.update_attributes(params[:tip])
flash[:notice] = 'Tip was successfully updated.'
format.html { redirect_to(#tip) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #tip.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#tip = Tip.find(params[:id])
#tip.destroy
respond_to do |format|
format.html { redirect_to(tips_url) }
format.xml { head :ok }
end
end
def observe_new
session[:tip_draft] = current_user.tips.build(params[:tip])
render :nothing => true
end
end
the quick answer is that form_tag doesn't support :action as an option, you want to be passing a string as a path in. A slightly longer answer is you shouldn't be using form_tag anyways for a model edit form, you should be using form_for.
what rails are you using? .rhtml is pretty old, rails generators should be giving you .html.erb files. if it is something even remotely recent, you should be able to use
<% form_for #tip do |f| %>
<%= f.label :title, 'Title' %><br />
<%= f.text_field %>
... etc
<% end %>

Resources