Rails route can't expand model object to get ID - ruby-on-rails

I have a form in one of my views that looks like this:
<% form_for #user, url_for(:controller => :users, :action => :admin_edit, :id => #user.id) do |f| %>
<%= f.select 'Confirmed', [['Yes', true], ['No', false]] %>
<%= f.submit 'Update' %>
<% end %>
The first line of it is raising a TypeError: no implicit conversion of Symbol into Integer. I think this is because the route (below) needs an ID, but isn't finding the ID it needs.
The users#admin_edit method is currently an empty definition. The route that points to it is:
post 'admin/users/:id/edit', to: 'users#admin_edit'
The #user object in question is set using
#user = User.find(params[:id])
so the :id attribute is definitely set; I've verified this with the console.
Given that I've passed the ID explicitly to url_for, why can the route not expand the #user object to get its ID out? Or can it, and the issue is somewhere else entirely?

Try this:
<%= form_for #user, url: {:action => :admin_edit} do |f| %>
<%= f.select 'Confirmed', [['Yes', true], ['No', false]] %>
<%= f.submit 'Update' %>
<% end %>
If you have set your routes as:
post 'admin/users/:id/edit', to: 'users#admin_edit'
Then your form could be as follows:
<%= form_for #user, url: {:controller => ::users, :action => :admin_edit, :id => #user.id}, method: :post do |f| %>
<%= f.select 'Confirmed', [['Yes', true], ['No', false]] %>
<%= f.submit 'Update' %>
<% end %>
Then you can get the id in your UsersController could look as follows:
def admin_edit
#user = User.find_by_id(params[:id])
end

Related

How can I pass input from a text_field as a parameter to create an object?

I want to take the input that the user enters in the text_field below and pass it as a parameter in the button_to that creates the object:
<%= text_field :objects, :object %>
<%= button_to("Comment!", :action => "create", :controller => "comments", :comment => {:user_id => current_user.id, :location_id=> location.id }) %>
How can I do this?
button_to is not the best tool to do what you need.
You need to use a form to receive the text_field on controller. Then you will be able to create a comment object. Example:
<%= form_for #comment do |f| %>
<%= f.text_field :text %>
<%= f.submit "Comment!" %>
<% end %>
Use form_for to create the Comment instead of button_to. The value of you text field will be available to your controller in params.

passing number_field_tag variable to rails controller

Here is my problem. I want to pass the value from number_field_tag to the rails controller through link_to.
here is a view:
<%= number_field_tag :quantity %>
<% link_to "do something", :controller => 'somecontroller', :action => 'dosomething', :pass_value_from_here => 'quantity' %>
and
controller:
def dosomething
#ivar = Model.new(:quantity => :value_passed_from_link_to )
# do somthing
end
Plus,
I am not trying to use form. I have some other params too to be passed through link_to.
for e.g.
<%link_to "do something", :controller => "somecontroller", :action=>'dosomething', :pass_value_from_text_field => 'quantity', :some_other_value_from_some_other_model %>
thank you in advance.
You probably don't want to use link_to here, you'll want to create a form which submits to your somecontroller#dosomething method.
You'll then find params[:quantity] populated with the input provided.
Something like this:
<%= form_tag somecontroller_dosomething_path do %>
<%= text_field_tag :quantity, params[:quantity] %>
<%= submit_tag :quantity %>
<% end %>

Passing model id through rails route in form

I'm calling a custom action with simple_form. I'm having trouble passing the :id parameter to the action.
routes
post '/posts/:id/admin_vote' => 'posts#admin_vote', as: 'admin_vote'
form
<%= simple_form_for :post, url: admin_vote_path(:post_id), :html => {:class => 'form-inline admin-vote-form'} do |f| %>
<%= f.select :vote, 1..20 %>
<%= f.submit 'Vote', :class => 'btn btn-primary btn-xs' %>
<% end %>
partial render
<%= render 'layouts/admin_vote', :locals => { :post => post, :post_id => post.id } %>
For some reason the action receives params[:id] = 'post_id' instead of the actual id.
You're providing :post_id symbol to the admin_vote_path, so it uses that. Change it to:
admin_vote_path(params[:post_id])
or a different parameter depending on the context of your form.
it seems to me your form should be
<%= simple_form_for post, url: admin_vote_path, :html => {:class => 'form-inline admin-vote-form'} do |f| %>
<%= f.select :vote, 1..20 %>
<%= f.submit 'Vote', :class => 'btn btn-primary btn-xs' %>
<% end %>
you should build form based on variable post

form_for calls model method without submit

I have an index page for admin part of my project
<% #reviews.each do |review| %>
<p><%= review.header %></p>
<p><%= review.body %></p>
<%= form_for [:admin, review] do |f| %>
<%= f.hidden_field :approve %>
<%= f.submit "Approve" %>
<% end %>
<%= form_for [:admin, review] do |f| %>
<%= f.hidden_field :reject %>
<%= f.submit "Reject" %>
<% end %>
<% end %>
where :approve and :reject are public instance methods in Review model.
For some reason, when I load this index page, it automatically calls review.reject method which sets corresponding is_rejected field to true. Same behavior applies to form_for with :approve if I remove form_for with :reject bit.
index action from corresponding controller is very simple
def index
#reviews = Review.all
end
I realize this must be normal behavior, but what I would expect is to call reject method only when I submit corresponding form. Is there a way to fix it? Thank you.
UPDATE
Just for the future reference (including my own): it is easier to use button_to helper for things like that
<%= button_to "Approve", { :action => "update", :id => review.id, :review => { :approve => true } }, :method => :put %>
<%= button_to "Reject", { :action => "update", :id => review.id, :review => { :reject => true } }, :method => :put %>
The form builder is calling approve and reject on your model because it's trying to determine what to set the value for the hidden fields to. One way around this would be to not use f.hidden_field and just create a hidden field that's not tied to your model. You can use hidden_field_tag instead.

Difference between :model and #model in form_for?

What is the difference between using form_for the following way:
<% form_for #user do |f| %>
<%= f.label :name %>:
<%= f.text_field :name, :size => 40 %>
...
<% end %>
and:
<% form_for :user, :url => {:action => 'create'} do |f| %>
<%= f.label :name %>:
<%= f.text_field :name, :size => 40 %>
...
<% end %>
Does using #user just automatically use CRUD methods for the URL actions?
If you just give a model instance like #user without specifying an action (as in your first example), Rails automatically uses the appropriate CRUD action for your form:
If #user is a new, unsaved User object, the form will point to your create action.
If #user is an existing User loaded from the database, the update action will be used instead.
This has the advantage that you can reuse the same form for both your edit and new views without changing the :url parameter for your forms.
As usual, the API docs provide more information.
If you give form_for a symbol without an instance variable it looks for an instance variable with the same name.
The documentation says:
For example, if #post is an existing
record you want to edit
<% form_for #post do |f| %>
...
<% end %>
is equivalent to something like:
<% form_for :post, #post, :url => post_path(#post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
...
<% end %>

Resources