Rails 4 Create form to update only one attribute - ruby-on-rails

I have a user model, but I need to create a form to update only one attribute.
EDIT: I added the create_mailbox patch in :users resource but the form throws a undefined methodsettings_create_mailbox_path'` error. Can anyone give me some insight to how this member patch/resource routes work?
Here's the form:
<%= form_for #user, url: settings_create_mailbox_path(#user) do |f| %>
<%= f.text_field :rss_mailbox, autocomplete: 'off'%>
<button type="submit" class="button">Create Mailbox</button>
<% end %>
Here's the Users route:
resources :users, id: /.*/ do
member do
patch :settings_update, controller: :settings
patch :create_mailbox, controller: :settings
patch :view_settings_update, controller: :settings
patch :sharing_services_update, controller: :sharing_services
patch :actions_update, controller: :actions
end
end
And here's the settings route:
get :settings, to: 'settings#settings'
namespace :settings do
get :account
get :billing
get :import_export
get :feeds
get :help
post :update_credit_card
post :mark_favicon_complete
post :update_plan
post :font
post :font_increase
post :font_decrease
post :entry_width
end

It would depend on the attribute and what you're changing it to.
If it's a simple toggling of a boolean field, for example, you could get away with a link that fires off an ajax request, that makes the change and returns some HTML (eg. to update the link you clicked).
If it's something else, eg. a text field or a string or something, a form_for #user would be the typical way. But the form would only have one field, and the controller that processes the form post would have its strong parameters (or attr_accessible for Rails 3) set so that it will only accept data for that one field.

Was using the wrong route name. This was the right one:
create_mailbox_user_path

Rails 4 Use Strong Parameters to determine which attribute is allow to update like so:
def user_param
params.require(:user).permit(:attr)
end

Related

How do I have route helpers use existing params?

Sometimes I won't have to provide a param to a route helper and it automagically pulls it in from the existing params. I can't seem to figure out how to get it to consistently work.
routes.rb:
scope ':admin_id', module: :admin do
resources :roles
end
When rendering a page where the :admin_id is set to 10:
<%= roles_path %> # /10/roles
<%= edit_role_path(my_role, admin_id: 10) %> # /10/roles/15/edit
<%= edit_role_path(my_role) %> # sometimes works
rails
routes:
roles GET /:admin_id/roles(.:format) roles#index
POST /:admin_id/roles(.:format) roles#create
new_role GET /:admin_id/roles/new(.:format) roles#new
edit_role GET /:admin_id/roles/:id/edit(.:format) roles#edit
role GET /:admin_id/roles/:id(.:format) roles#show
PATCH /:admin_id/roles/:id(.:format) roles#update
PUT /:admin_id/roles/:id(.:format) roles#update
DELETE /:admin_id/roles/:id(.:format) roles#destroy
Figured it out!
def default_url_options(options={})
{ admin_id: params[:admin_id] }
end
This will add the param to all of my route helper methods so I don't have to specify it each time.

Unable to create model based forms rails 4

I have model based form:
<h2>Add New Credit Card</h2>
<%= form_for #credit_card do |f| %>
some fields
<% end %>
routes:
resources :credit_card
credit_card_index GET /credit_card(.:format) credit_card#index
POST /credit_card(.:format) credit_card#create
new_credit_card GET /credit_card/new(.:format) credit_card#new
edit_credit_card GET /credit_card/:id/edit(.:format) credit_card#edit
credit_card GET /credit_card/:id(.:format) credit_card#show
PATCH /credit_card/:id(.:format) credit_card#update
PUT /credit_card/:id(.:format) credit_card#update
DELETE /credit_card/:id(.:format) credit_card#destroy
controller:
def new
#credit_card = CreditCard.new
end
When I try to render by form it says:
undefined method `credit_cards_path' for #<#<Class:0x00000004c37680>:0x00000004c34570>
Did you mean? credit_card_path
credit_card_index_path
credit_card_url
Its a model based form, for now I have nothing in model. I just want to render and submit will go to create method
You're using the Singular Resources:
resources :credit_card
Where you have to use Plural Resources:
resources :credit_cards
In your routes, use plural for resources definition.
resources :credit_cards
That will generate your routes like
credit_cards GET /credit_cards/:id(.:format) credit_card#show
Use resources :credit_cards instead of resources :credit_card

Rails - custom action in controller - how to reference in view?

I'm using a custom action to get the id of a project into the session, so that only relevant info for that project is shown in other areas. I've made a custom action in the projects controller, and am having trouble getting a link to work in the view to call that action. I just get an error saying "Couldn't find project without ID". I'm new to rails - I know it's probably an easy question, but help would be much appreciated, thanks!
View Code:
<%= link_to 'Select Project', :action => :select_project %>
Controller Code:
def select_project
#project = Project.find(params[:id])
session[:project_id] = #project.id
end
Routes:
resources :projects do
collection do
get :select_project
end
end
Alternative routes code:
resources :projects do
put 'select_project', on: :member
end
This is untested but I believe it is what you are looking for:
Routes:
resources :projects do
member do
post :set_current
end
end
this should create the following:
Endpoint: /projects/:id/set_current POST
Helper: set_current_project_path
Controller
def set_current
project = Project.find(params[:id])
session[:project_id] = project.id
redirect_to projects_path, :notice => "Current project set to #{project.name}"
end
Views
# index / erb tags excluded for simplicity
#projects.each do |project|
link_to 'Select Project', set_current_project_path(project), :method => :post
end
# show
<%= link_to 'Select Project', set_current_project_path(#project), :method => :post %>
See:
http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
Note also the use of 'post' instead of 'get', since we are changing the state of an object (session)
it is preferred to use a post not a get, otherwise users might pull up an old get request in the address bar
of their browser and set their session to a project unknowingly.
like varatis said - use rake routes or CONTROLLER=projects rake routes to help with determining what your route/path helpers look like and what http verbs they are expecting
And is there a reason why it's project not #project in the controller
The #project creates an instance variable; in a rails controller instance variables are made available to the views. This set_current action will never render a view, so no reason to make an instance variable out of it.
How come you have to set it to member and not collection in the routes
any action where you want to reference params[:id] should be a member route, an alternative would be to leave it as a collection route and pass params[:project_id] and pass that in all of your link_to calls, but in this case member makes more sense.
I believe resources :projects is a short cut for this break down
member do
get :show
get :edit
put :update
delete :destroy
end
collection do
get :index
get :new
post :create
end
hopefully that clarifies your questions some?
I think the route generated would be select_project_projects_path.
Link:
<%= link_to 'Select Project', select_project_projects_path %>
For future reference, run rake routes to see the automatic route helpers generated by Rails.

How can I have multiple forms to update the same model?

I am new to Rails.
I have a User model. I would like a web page that allows users to change their :name and :email, and another web page that allows them to change their password.
Right now, I have a form to edit :name and :email at
/users/1/edit
The form on the page is
<%= form_for(#user) do |f| %>
My routes.rb has
resources :users
This works. Users can edit their :name and :email just fine. How do I now set up another web page with another form that allows them to change their password?
Thank you.
You can set up any actions you like in your controller. The default CRUD operations are there to cover the basics, but there is no inherent limitation to what you can do.
#controller:
def change_password
render :action => "change_password"
end
#routes:
map.resource :users, :member => {:change_password => :get}
#view:
<%= form_for(#user) do |f| %>
The above would create the route:
/users/1/change_password
In the view you simply have the change password fields => the form basically stays the same, submitting to your existing update action.
Per the comment from Sanjay regarding Toby's answer (and to save anyone the few minutes that I took to figure it out) in Rails 3 you would define the routes with:
#routes:
resources :users do
member do
get 'change_password'
end
end

Rails form helper and RESTful routes

I have a form partial current setup like this to make new blog posts
<% form_for([#current_user, #post]) do |f| %>
This works great when editing a post, but when creating a new post I get the following error:
undefined method `user_posts_path' for #<ActionView::Base:0x6158104>
My routes are setup as follows:
map.resources :user do |user|
user.resources :post
end
Is there a better way to setup my partial to handle both new posts and editing current posts?
map.resources :user do |user|
user.resources :posts
end
pluralize your model names in routes declaration. as you can see it says resourc-es, so you must use user-s and post-s too.
Controllers should be named UsersController and PostsController
Models should be named User and Post.
if above example still does not work for you, try a this one
map.resources :users do |u|
u.resources :posts
end

Resources