I'm a newbie on rails. My rails version is 4.2.6, simple_form_for version is 3.2.1. I want to redirect to the new page after I validated the params is false. And I get the error message.
undefined method `model_name' for nil:NilClass <%= simple_form_for
[:account, #station] do |f| %>
...
let me show you. This is my routes.rb
namespace :account do
resources :stations, expect: [:index]
end
stations_controller.rb
def new
#lines = Line.where(line_status: 1)
#station = Station.new
end
def create
unless check_post_params post_params
flash[:notice] = "miss params"
render action: :new # not work
# render :new # not work
# render 'new' # not work
# it work for me, but can I use render?
#redirect_to '/account/stations/new'
else
#station = Station.new(post_params)
if #station.save
redirect_to '/account/lines'
else
flash[:notice] = 'failed'
redirect_to 'account/stations/new'
end
end
end
private
def post_params
params.require(:station).permit(...)
end
def check_post_params(post_params)
if ...
return false
else
return true
end
end
_form.html.erb
<%= simple_form_for [:account, #station] do |f| %>
<div class="form-group">
<%= f.label :line_id, t('line.line_name') %>
<%= f.input_field :line_id,
... %>
<% end %>
The original I open the URL is http://localhost:3000/acoount/stations/new. After I click the submit, and I want to render :new, it will redirect to original URL, but I found the URL become http://localhost:3000/account/stations. The URL's /new is disappear. I have guessed it's about my routes.rb config.
And I tried to use rake routes to check my routes.
$ rake routes
...
POST /account/stations(.:format) account/stations#create {:expect=>:index]}
new_account_station GET /account/stations/new(.:format) account/stations#new {:expect=>[:index]}
...
I tried to use render account_stations_new_path and render new_account_station_path, but still not work for me. Thanks your help.
Edit
I know how to modify my code. I should validate my params on my model. And then I should use redirect_to not use render. I will update my code later.
Edit 2
I modified my model.
class Station < ActiveRecord::Base
belongs_to :line
has_many :spot_stations
validates :name, presence: true, uniqueness: { case_sensitive: false }
validates :line_id, presence: true
validates ....
end
And I modified my controller.
def new
# Because this #lines did't exist when I render 'new' on the create method. So I deleted it. And I create a method on the helper.
# #lines = Line.where(line_status: 1)
#station = Station.new
end
def create
#station = Station.new(post_params)
if #station.save
redirect_to '/account/lines'
else
flash[:notice] = 'failed'
render 'new'
end
end
I add a method for getting lines data
module Account::StationsHelper
def get_lines
#lines = Line.where(line_status: 1)
end
end
I will use it on my _form.html.erb
<%= simple_form_for [:account, #station] do |f| %>
<div class="form-group">
<%= f.label :line_id, t('line.line_name') %>
<%= f.input_field :line_id,
collection: get_lines,
label_method: :line_name,
input_html: { class: 'form-control' },
value_method: :id,
prompt: t('common.please_select') %>
</div>
...
<% end %>
This work great for me. Thanks your help.
try this:
if #station.save
redirect_to account_stations
else
flash[:notice] = 'failed'
render 'new'
end
as argument for render method you must pass action name, not url.
Related
I'm trying to make a form object work for new User and edit User actions. The form object creates or updates a User through it's save method, but the form object itself is never persisted so Rails always tries to make a POST even though I'm specifying different routes in the simple_form_for url.
Is there any way to make it work for both actions?
UsersController.rb:
class Admin::UsersController < AdminController
def new
#user_form = UserForm.new(account_id: current_account.id)
end
def create
#user_form = UserForm.new(user_form_params)
if #user = #user_form.save
flash[:success] = "User created"
redirect_to admin_user_path(#user)
else
render "new"
end
end
def edit
#user_form = UserForm.new(existing_user: #user, account_id: current_account.id)
end
def update
if #user.update(user_form_params)
flash[:success] = "User saved"
redirect_to admin_user_path(#user)
else
render "edit"
end
end
end
UserForm.rb
class UserForm
include ActiveModel::Model
include ActiveModel::Validations::Callbacks
attr_accessor :fname, :lname, :email
def initialize(params = {})
super(params)
#account = Account.find(account_id)
#user = existing_user || user
end
def user
#user ||= User.new do |user|
user.fname = fname
user.lname = lname
user.email = email
end
end
def save
#user.save
#user
end
end
_form.html.erb
<%= simple_form_for #user_form, url: (#user.present? ? admin_user_path(#user) : admin_users_path) do |f| %>
<%= f.input :fname %>
<%= f.input :lname %>
<%= f.input :email %>
<%= f.submit %>
end
The new/create flow works fine, but editing an existing User returns
No route matches [POST] "/admin/users/69"
class UserForm
# ...
def to_model
#user
end
end
<%= simple_form_for #user_form, url: [:admin, #user_form] do |f| %>
<%= f.input :fname %>
<%= f.input :lname %>
<%= f.input :email %>
<%= f.submit %>
end
When you pass a record to form_for (which SimpleForm wraps), form_with or link_to the polymorphic routing helpers call to_model.model_name.route_key or singular_route_key depending on if the model is persisted?. Passing [:admin, #user_form] will cause the polymorphic route helpers to use admin_users_path instead of just users_path.
On normal models to_model just returns self.
https://api.rubyonrails.org/v6.1.4/classes/ActionDispatch/Routing/PolymorphicRoutes.html
When i try to create an entry in my application i get
ActionController::ParameterMissing in TodosController#create
param is missing or the value is empty: activity
Expected Source:
def todo_params
params.require(:activity).permit(:name, :due)
end
Here is my request:
{"utf8"=>"✓",
"authenticity_token"=>"mR11T50dN8tm/q+S0fNd+mYYZBR6Xq4it4ujtEOmt/7RmA4TjzTKD//XmFU+UumpbmKcaj9DtG6noHOD2pwk2w==",
"todo"=>{"name"=>"Ezekiel",
"activity"=>"test....an 8th time"},
"commit"=>"Create Todo"}
I am not sure why this is not working as the activity parameter is clearly passed through as it is in the request
Here is the controller:
def create
#todo = Todo.create(todo_params)
end
def todo_params
params.require(:activity).permit(:name, :due)
end
And finally my View:
<div class="reveal" id="ezekielTask" data-reveal>
<%= simple_form_for #todo do |f| %>
<%= f.input :name, :as => :hidden, :input_html => {:value => "Ezekiel"} %>
<%= f.input :activity %>
<%= f.button :submit %>
<% end %>
</div>
This part of my rails application is a todo list, it displays fine, i can add entries through the console, this way just will not work and i have no idea why. it is passing the data correctly just not accepting it.
Controller
def create
#todo = Todo.create(todo_params)
respond_to do |format|
if #todo.save
format.html { redirect_to location_path, notice: 'Todo was successfully created.' }
else
format.html { render :new }
}
end
end
end
Params
def todo_params
params.require(:todo).permit(:name, :activity)
end
You need to change the strong params method to require todo and then accept the :name and :activity params
def todo_params
params.require(:todo).permit(:name, :activity)
end
The reason for that is
{"utf8"=>"✓",
"authenticity_token"=>"mR11T50dN8tm/q+S0fNd+mYYZBR6Xq4it4ujtEOmt/7RmA4TjzTKD//XmFU+UumpbmKcaj9DtG6noHOD2pwk2w==",
"todo"=>{"name"=>"Ezekiel",
"activity"=>"test....an 8th time"},
"commit"=>"Create Todo"}
If you see in the params you are receiving name and activity inside todo
In the require parameter normaly we use the name of the model (todo) and inside permit we use the attributes of that model (:name, :activity)
def todo_params
params.require(:todo).permit(:name, :activity)
end
I am trying to render a new view on an already existing user show page. When trying to submit this view, I get param is missing or the value is empty: user. To be clear this is a skill partial being rendered on the user show page. For some reason it is using the strong params in my User Controller.
The code:
show.html.erb for user
<h4>Create a Skill</h4>
<%= render partial: "skills/form" %>
userscontroller.rb
def show
#user = User.find(params[:id])
#skill = Skill.new
#skills = #user.skills.all
end
private
def user_params
params.require(:user).permit(:username, :password, :avatar_url, :email, :about, :cover_letter, :city, :state)
end
end
SkillsController.rb
class SkillsController < ActionController::Base
def new
user = User.find(params[:user_id])
#skill = user.skills.new
end
def create
user = User.find(params[:user_id])
#skill = user.skills.new(skill_params)
if #skill.save
flash[:message] = "#{#skill.name} skill has been created!"
redirect_to user_path(user)
else
redirect_to new_user_skill_path
end
end
private
def skill_params
params.require(:skill).permit(:name, :level)
end
end
Also, I have Namespaced skills within user. No authentication in place yet.
EDIT: #nickm, here are the contents of skills/_form
<%= simple_form_for(Skill.new, :url => { :action => "create" }) do |f| %>
<%= f.input :name, label: 'Skill Name ' %>
<%= f.input :level, label: "Skill Level ", collection: ["Beginner","Proficient", "Intermediate", "Advanced", "Expert"], include_blank: false, include_hidden: false %>
<%= f.submit %>
<% end %>
The problem is that you aren't passing a user_id through the form. You would have to either add a form input:
<%= f.hidden_field :user_id, some_value %>
Then find the user:
user = User.find(params[:skill][:user_id])
and then make skill_params
def skill_params
params.require(:skill).permit(:name, :level, user_id)
end
Or optionally, set the value of user_id in your controller action. Not sure how you're going to pass that value since you haven't built any authentication yet. If you were using something like devise you could do
current_user.skills.new(skills_params)
...in your create action.
followed a tutorial to help me create instances within a controller. In other words transactions are created on the envelope controller. Like comments on a blog post.
Everything is working perfectly, but I don't know how to edit a transaction now or destroy one. All I need is to find how to edit an existing thing. Let me show you what I have so far:
in views/envelopes/edit (the form code was copied from where you can create new transactions)
<% #envelope.transactions.each do |transaction|%>
<%= form_for [#envelope, #envelope.transactions.build] do |f| %> <!--??? NEED EDIT INSTEAD OF BUILD ???-->
<%= f.text_field :name, "value" => transaction.name %>
<%= f.text_field :cash, "value" => transaction.cash %>
<%= f.submit "Submit" %>
<% end %>
<%= link_to "Remove", root_path %> <!--??? WANT TO REMOVE TRANSACTION ???-->
<% end %>
in routes.rb
resources :envelopes do
resources :transactions
end
in transaction controller
class TransactionsController < ApplicationController
def create
#envelope = Envelope.find(params[:envelope_id])
#transaction = #envelope.transactions.build(transaction_params)#(params[:transaction])
#transaction.save
#envelope.update_attributes :cash => #envelope.cash - #transaction.cash
redirect_to edit_envelope_path(#envelope)
end
def destroy
# ???
end
def update
# ???
end
def transaction_params
params.require(:transaction).permit(:cash, :name, :envelope_id)
end
end
def update
#transaction = #envelope.transactions.find(params[:id])
if #transaction.update(transaction_params)
redirect to #envelope, notice: 'Transaction was successfully updated'
else
redirect_to #envelope, notice: 'Transaction was not updated'
end
end
def destroy
#transaction.destroy
redirect_to #envelope, notice: 'Text here'
end
I have a very basic rails app. I am playing around with validation.
Controller
class PagesController < ApplicationController
def new
#user = User.new
end
def edit
#user = User.new(:state => params[:state], :country => params[:country])
#user.save
end
end
Model
class User < ActiveRecord::Base
validates_presence_of :country
validates_presence_of :state
end
Views/pages/edit.html.erb
<% form_for :user, #user, :url => { :action => "edit" } do |f| %>
<%= f.text_field :country %>
<%= f.text_field :state %>
<%= submit_tag 'Create' %>
<% end %>
All I want to do is click Create when I have not entered anything and then have a validation come up and list the required fields. I've read some tutorials and they make it so simple. Why can't I get this to work? what am i doing wrong? When i create a scaffold then it works ok but that generates a scaffold.css in public/stylesheets. W/out scaffold right now i have no stylesheet in the public folder.
you're sending the form to the "edit" action, which doesn't do any processing. You need it to go to the "create" action, which should look something like this:
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = 'Your user was successfully created.'
redirect_to users_path
else
render :action => 'edit'
end
end
Your form_for line can be short and sweet. Also, you need to call error_messages to get the auto-generated list of errors:
<% form_for #user do |f| %>
<%= f.error_messages %>
...other fields go here...
<% end %>
See Rails conditional validation: if: doesn't working
It seems like you think validates ... if: works differently as it actually does. This line
validates :to_id, presence: true, if: :from_different_to?
translates to validate that the to_id is present if the from_different_to method returns true. When from_different_to evaluates to false then do not validate.