I have a form for creating new Missions with an Admin account. Each Mission is linked to an account. When I visit admin/missions/new I get an error "ArgumentError in Admin::Missions#new". Can anyone point to what I'm doing wrong?
When I checked the rails console a mission id and name does show up, but I guess I'm missing the Admin for the mission.
Here's my Controller
class Admin::MissionsController < Admin::ApplicationController
def index
#missions = missions
end
def new
#mission = current_account.missions.new(params[:mission])
#mission.save
end
def create
render plain: params[:mission].inspect
end
def edit
#mission = missions.find(params[:id])
end
private
def missions
#missions ||= current_account.missions
end
end
Here's my form
<%= form_with [:admin, #mission] do |f| %>
<div>
<label>Name</label>
<%= f.text_field :name %>
</div>
<div>
</div>
<div>
<%= f.submit %>
</div>
<% end %>
I'm expecting the url admin/missions/new to take me to the form, but I I get the argument error wrong number of arguments (given 1, expected 0)
You don't have params yet in the new action as the view (where the form which has to collect the params is) is rendered after the controller code. The object should be created in the create action:
def create
current_account.missions.create(params[:mission])
end
And the new action should be just:
def new
#mission = current_account.missions.new
end
Check the Binding a Form to an Object section of the Rails guide.
The form code seems also to be wrong, as form_with [:admin, #mission] do |f| is not a valid syntax. It should be:
<%= form_with model: [:admin, #mission] do |form| %>
Check form_with documentation for more details.
Ideally new method is just for creating a new instance and create method is for saving records. Changing to what Ana Maria is suggesting should fix your issue. Thanks.
Related
This is likely an error due to my minimal understanding of Rails and how to use variables across models, so if there is more code needed to answer it or if my terminology is incorrect, let me know and I will gladly update the question.
I have a feed of posts that I want a user to be able to "like." While the following code allows likes to work on an individual post's page - site.com:3000/posts/*post.id* - with the form data being passed of like[liked_post_id]:*post.id*, when I try to submit a like on a profile - site.com:3000/users/*user.id* - which contains a feed of posts, the form data being passed is like[liked_post_id]: (blank value)
How can I pass the post's ID within a feed of posts to the liked_post_id variable in _like.html.erb?
I have noticed that the action of the like form is /likes across the board. Would this will only work when you are on the page site.com:3000/posts/*post.id*? I'm curious if I need to modify the it so that the action of the form is /posts/*post.id*/likes when you are on the page site.com:3000/users/*user.id*
From my post view:
#views/posts/_post.html.erb:
...
<%= render 'posts/like_form' if signed_in? %>
...
Route to proper form:
#views/posts/_like_form.html.erb:
<div id="like_form">
<% if current_user.likes_this?(#post) %>
<%= render "posts/unlike" %>
<% else %>
<%= render "posts/like" %>
<% end %>
</div>
Like from:
#views/posts/_like.html.erb
<%= form_for Like.new, :remote => true do |f| %>
<%= f.hidden_field :liked_post_id, :value => #post.id %>
<%= f.submit "Like" %>
<% end %>
From profile (feed of posts):
#views/users/show.html.erb
...
<%= render #posts %>
...
Likes controller:
#controllers/likes_controller.rb
class LikesController < ApplicationController
before_filter :signed_in_user
def create
#post = Post.find(params[:like][:liked_post_id])
current_user.like!(#post)
respond_to do |format|
format.html { redirect_to root_url }
format.js
end
end
...
User model:
#models/user.rb
...
def like!(post)
likes.create!(liked_post_id: post.id)
end
...
#frank-blizzard has pointed out that my form markup is an issue. On a post's page the generated markup is:
<input id="like_liked_post_id" name="like[liked_post_id]" type="hidden" value="73" />
While on the feed page:
<input id="like_liked_post_id" name="like[liked_post_id]" type="hidden" />
You can do something like this:
<% form_for Like.new, :remote => true do |f| %>
<%= f.hidden_field :post_id, :value => #post.id %>
<%= f.submit %>
<% end %>
The current_user.likes.build(...) part should get out of your view and inside your controller. You are using a current_user.like! method so I guess you have implemented already some method in user model to accomplish this. If not build your like in the create action of LikesController where you can access params[:like].
def create
#post = Post.find(params[:like][:post_id])
current_user.likes.build(#post)
# ...
end
EDiT
You might need to pass your #post variable correctly into your _like_form partials, like so:
#views/posts/_post.html.erb:
...
<% if signed_in? %>
<%= render 'posts/like_form', :post => #post %>
<% end %>
...
This will give you acceess to a post variable inside the partial so you can prepopulate your forms value with its id. See this questions as well Pass a variable into a partial, rails 3? and make sure to read up on how to pass variables correctly to partials. you can debug your views using <%= debug <variablename> %>
I'm using form_for to create a chatroom and when I view the page I get the following error:
NoMethodError in Chatrooms#new
undefined method `chatrooms_path' for #<#<Class:0xa862b94>:0xa5307f0>
Here's the code for the view, located in app/views/chatrooms/new.html.erb:
<div class="center">
<%= form_for(#chatroom) do |f| %>
<%=f.text_field :topic%>
<br>
<%=f.submit "Start a discussion", class: "btn btn-large btn-primary"%>
<% end %>
</div>
Here's the relevant controller:
class ChatroomsController < ApplicationController
def new
#chatroom = Chatroom.new
end
def show
#chatroom = Chatroom.find(params[:id])
end
end
If I change the line
<%= form_for(#chatroom) do |f| %>
to
<%= form_for(:chatroom) do |f| %>
it works fine.
I've searched around for similar questions but none of the solutions have worked for me. Help?
It is because you didn't create route/action for ChatroomsController. When you render new form it is pointing to create action by default, if you want to change handler action, use
form_for #chatroom, :url => some_other_path
In Rails 3.0 I have the standard 'new' form that creates a new record, in this case a patient. It works fine and the validations / error showing also work fine.
The client now wants the form in Spanish.
So, I did this:
Created a new html doc called "newspanish" (Cut / paste code from "patients/new")
Created a new partial called "_form_newspanish" and referenced it where the "form" partial is in "newspanish" (Cut / paste code from view "patients/_form")
Created a controller action in "patients" called "newspanish" and cut/pasted exact code from the "new" action.
I left the "create" action untouched.
Added match "patients/newspanish" to routes.
Translated the english parts to spanish in views/newspanish and views/_form_newspanish. Just the stuff that users read on the page, of course...not the rails code.
And, it works, for perfect submissions.
For submissions that fail validation (like putting 3 digits in as a phone number), the page reverts to the view "patients/new" and shows the errors above the form... in English, of course, because patients/new is in English.
Of course, I want it to revert to "views/newspanish" and also show custom verbage in the validations errors (spanish).
Any thoughts on how I can get the patients/newspanish view to load when error validation it tripped?
Here's my code for "_form_newspanish"
<%= form_for(#patient) do |f| %>
<% if #patient.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#patient.errors.count, "error") %> prohibited this subscriber from being saved:</h2>
<ul>
<% #patient.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p><label for="mobile">Número de teléfono celular o móvil*</label>: <%= f.text_field :mobile %></p>
<br />
<%= f.submit "Inscribirme" %>
</div>
<% end %>
And controller... patients/newspanish
def newspanish
#patient = Patient.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #patient }
end
end
<%= form_for(#patient) do |f| %>
is creating a form whose url is submits to is "/patients" which matches to patients_controller, create action.
That create action probably has a line that says (in my pseudo code)
if #patient.save
redirect to somewhere
else
render :new
end
That line "render :new" is showing the "patients/new" view.
So what you have to figure out is to either
1) detect in patients_controller # create how to tell if its spanish, and render "newspanish"
OR
2) change <%= form_for(#patient) do |f| %> to submit to a new url that just handles the spanish version, and make a new controller or action that just handles the spanish form (and renders "newspanish" if the #patient doesn't save
For #2, you could manually change where the form submits to with
<%= form_for(#patient), :url => spanish_patients_path do |f| %>
and in your routes create
post "patients/spanish" => "patients#create_in_spanish"
and add def create_in_spanish to your patients controller
I try to update my settings through a form but the update function is not called when I submit. It redirects to edit_settings_path when I submit and as per serve log update is not called. Why?
<%= form_tag settings_path, :method => :put do %>
<p>
<%= label_tag :"settings[:default_email]", "System Administrator" %>
<%= text_field_tag :"settings[:default_email]", Settings['default_email'] %>
</p>
<span class="submit"><%= submit_tag "Save settings" %></span>
<% end %>
Controller
class SettingsController < ApplicationController
def update
params[:settings].each do |name, value|
Settings[name] = value
end
redirect_to edit_settings_path, :notice => "Settings have been saved." }
end
end
** Update **
Update is now called properly (edited controller). Server log confirms Settings Load (0.2ms) SELECT "settings".* FROM "settings" WHERE "settings"."thing_type" IS NULL AND "settings"."thing_id" IS NULL AND "settings"."var" = ':default_email' LIMIT 1
UPDATE "settings" SET "value" = '--- 1111aaa2222...', "updated_at" = '2011-12-18 21:03:21.782075' WHERE "settings"."id" = 2
However it doesn't save to the Db and have no clue why. I'm using the Rails-settings gem 'git://github.com/100hz/rails-settings.git'
Don't know where to check since it says it updated record but in fact no.
why are you using the form_tag method?
If you are just trying to make a standard update form, use:
<%= form_for(#settings) do |f| %>
FORM CODE
<%= end %>
Your controller uses the edit method to render the view and the update method for the calback (to interact with the model)
If you insist on using
<%= form_tag setting_path, :method => :put do %>
Normally you would use the singular word if you are working on a member and the plural if you are working on an collection.
fyi: I dont know what your design is like, but i would have a model settings and a model settings_item...
This question is a follow up to this previous question: Ruby on Rails: Custom actions
As a follow up, what would be the syntax to use a custom action in a form_for? For my app, I have a partial called _invite_form.html.erb, and set the form to have a :url specification that I thought would link the form to the invite action on the Users controller:
<div id = "invite_form">
<h1>Invite</h1>
<%= form_for(invited, :url => invite_user_path) do |f| %>
<div class="field">
<%= f.text_field :email, :class => "inputform round", :placeholder => "email" %>
</div>
<div class="actions">
<%= f.submit "Invite", :class => "submit_button round" %>
</div>
<% end %>
</div>
This partial is called on certain pages, and this error is given:
"No route matches {:action=>"invite", :controller=>"users"}"
In my routes.rb file I have included the appropriate lines:
resources :users do
member do
get :invite
post :invite
end
end
Why is it that the route doesn't work? How do I change these files to make the form use the action "Invite" on the Users controller?
** Forgot to mention earlier: I defined invited in the Users helper: users_helper.rb:
module UsersHelper
def invited
#invited = User.new(params[:user])
end
end
As you don't have a persistent User just yet, make this a collection operation by:
Changing invite_user_path to invite_users_path in your controller
Changing member do to collection do in your routes
invite_user_path expects a user as an argument. Try invite_user_path(invited). You will also need to save the user before you can compute a path to it.
To experiment, go into rails console and see the difference between the following:
app.invite_user_path
app.invite_user_path(User.first)
app.invite_user_path(User.new)