Forms with routes in Rails 4.1 - ruby-on-rails

Rails 4.1, reaching the driver knowing edit and use _form.html.erb again. I tried to do the following:
 
<% = Form_for #user, :controller => "admin/users" do | f |%>
<button type='submit'>Guardar</button>
<% end %>
#Controller
===============
def new
#user = User.new
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to admin_users_url, notice: "User ##user.name} was successfully created." }
format.json { render :controller => 'admin/users', action: 'show', status: :created, location: #user }
else
format.html { render :controller => 'admin/users', action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
But it does not work I can not get to the route that is my controller ("admin / users"), if anyone can help me

I assume that you have your admin routes defined in your config/routes.rb like this:
# in config/routes.rb
namespace :admin do
resources :users
end
See: Rails Guide about namespaces in routes
Then this should work for an admin namespaced form in your view:
<%= form_for [:admin, #user] do |f| %>
...
<% end %>
See: Rails Guide about namespaces and form helper
Your controller code looks okay, but please ensure that the controller is namespaced too:
# in app/controllers/admin/users_controller.rb
module Admin
class UsersController
# ...
end
end

Related

change routes of update rails

I have a doubt in changing a route value.
I have this situation:
routes.rb
patch 'supplies/update'
get 'supplies/edit'
get 'supplies/index'
views/supplies/edit.html.erb
<%= form_for #supply , :url => supplies_update_path(id: #supply) do |f| %>
....
i would use in the edit.html.erb file the following code:
<%= form_for #supply do |f| %>
what i have to change in the route to obtain the correct supply_path for this form_for?
thank you.
EDIT:
class SuppliesController < ApplicationController
before_action :set_supply, only: [:show, :edit, :update, :destroy]
load_and_authorize_resource
# GET /supplies/index
def index
#supplies = Supply.includes(:product).all
end
def edit
end
# PATCH/PUT /supplies/1
def update
respond_to do |format|
if #supply.update(supply_params)
format.html { redirect_to supplies_index_path, notice: 'Quantità Aggiornata.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #supply.errors, status: :unprocessable_entity }
end
end
end
private
def set_supply
#supply = Supply.includes(:product).find(params[:id])
rescue ActiveRecord::RecordNotFound
render :template => 'public/404.html'
end
def supply_params
params.require(:supply).permit(:quantity)
end
end
You can simply use <%= form_for #supply do |f| %> for edit.html.erb file. Reason is: When you instantiate #supply in edit method in SuppliesController, Rails will automatically post the form to update method, you do not need to tell it explicitly. Same way, in new.html.erb, you will also use the same: <%= form_for #supply do |f| %>, but now in your new method, you will do #supply = Supply.new, Rails will post this form to create method.
You do need to define routes, but as far as correct path is concerned, Rails will take care of it as long as you provide correct #supply variable in form_for.
Edit:
In your routes file:
resources :supplies

New with Ruby on Rails, how to submit form with ajax in main view

I am new to Ruby on Rails and I can't wrap my head around the routing stuff.
I have a main view (index.html.erb) with a basic subscribe form with main controller, I have a resource named User in routes.rb with an associated user controller.
/app/views/main/index.html.erb
<%= form_for #user, remote: true do |f| %>
<%= f.text_field :email %>
<%= f.submit "Subscribe" %>
<% end %>
/app/controllers/main_controller.rb
class MainController < ApplicationController
def index
#user = Users.new
end
def create
#user = Users.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'Thank you !' }
format.js
else
format.html { render action: "new" }
format.js
end
end
end
end
/config/routes.rb
MyPage::Application.routes.draw do
get "main/index"
root 'main#index'
resources :users
end
UsersController is empty.
I know I need to change something in routes.rb but I don't get it. I get uninitialized constant MainController::Users error. Thanks !
Your problem is your UsersController is being confused as to inherit from MainController
This is either a routing issue or an issue with your system setup:
Routes
#config/routes.rb
root to: 'main#index'
resources :users, :main
View
<%= form_for #user, url: main_create_path, method: :post, remote: true do |f| %>
<%= f.text_field :email %>
<%= f.submit "Subscribe" %>
<% end %>
Controllers
class MainController < ApplicationController
def index
#user = Users.new
end
def create
#user = Users.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'Thank you !' }
format.js
else
format.html { render action: "new" }
format.js
end
end
end
end
class UsersController < ApplicationController
#your_stuff_here
end

simple_form undefined method `model_name' for NilClass:Class

I'm learning Rails, and I would like to use simple_form.
I'm creating a simple app (my first one), and I want to create a signup form.
I used rails g scaffold User username:string password:string to create my model and controller.
I'm using Foundation gem too, if that's matter, and I install simple_form with the right command for Foundation.
I've been looking for answers for two hours, I tried many things, I have no idea of what's wrong with my code.
## app/views/home/index.html.erb ##
<%= simple_form_for #User do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<% end %>
## app/models/user.rb ##
class User < ActiveRecord::Base
end
## app/controllers/users_controller.rb
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:username, :password)
end
end
I'm obviously doing something wrong, and I'm pretty sure I will feel like an idiot, but it's my first app :/
Thanks you.
EDIT: I forgot to say, I tried (desperately) every vars (#user, #users, #User, #Users), any of them doesn't works :/
Get rid of the form from the index.html.erb view (and no, don't put it in show.html.erb either!).
Place this form in the new.html.erb view:
<%= simple_form_for #user do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= f.submit %>
<% end %>
Note that the form should reference #user not #User.
Yep ... in the view you are using the #User instance variable (with uppercase U) but in the controller you assign the model to the #user instance variable (with lowecase u) :)
Put #user in lowcase (not #user)
<%= simple_form_for #user do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<% end %>
And save it as new.html.erb view not index.html.erb!

Setting rails routes to url path

I'm new to rails and having problems with my routes. When a link gets submitted, it should go to 'http://example.com' although it now goes to localhost:3000/links/www.example.com
I am running ruby 3.2.8 and ruby1.9.3p194. Not sure how much info is needed. Here's where it's at.
In my view I have:
<p>
<h1><%= #link.title %></h1>
<%= link_to #link.url, #link.url %><br />
<p>Posted by: <% #link.user %> at <%= #link.created_at %></p>
</p>
My controller is set as:
class LinksController < ApplicationController
def show
#link = Link.find(params[:id])
end
before_filter :authenticate_user!
def new
#link = Link.new
end
def create
#link = Link.new(params[:link])
respond_to do |format|
if #link.save
format.html { redirect_to #link, notice: 'Link was successfully created.' }
format.json { render :json => #link, status: :created, location: #link }
else
format.html { render :action => "new" }
format.json { render :json => #link.errors, :status => :unprocessable_entity }
end
end
end
end
In my development.rb file I have:
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
And my routes are:
resources :pages
resources :links
root :to => "pages#index"
After countless searches, I've had no luck since I am a beginner. Any suggestions for how to reset the link paths greatly appreciated.
There is nothing to do with routes or Rails here.
You need to output http:// in front of your links, if you want to link off-site. Either enter in in the textbox when you submit your link, or modify your code to conditionally prepend it:
<% link_href = #link.url %>
<% link_href = "http://#{link_href}" unless link_href.match(/^https?:\/\//) %>
<%= link_to #link.url, link_href %><br />

form_for tag and nested form - to use custom method from controller

I'm new to Rails and making application where college members (teachers and students) can create posts and comment on them. Later on I wish to add nesting (ancestry) and points system in it.
I have Post, Comment and Member model. The Post model was made via Scaffolding, Member model was made with help of Devise, and Comment is just a model.
In my show page of Post, I'd like to have comments beneath the posts, I've made some progress (thanks to SO I came to know quite a bit) but now I am stuck with a problem that whenever I attempt to post a blank comment, rails was redirecting to the edit page. How to change this so that rails stays only on the show page and display errors?
For this I searched a bit, created a new method 'update_comments' in post_controller.rb and tried modifying the forms_for tag attributes, as in the code below, but now I get routing error on submitting.
app/models/member.rb
class Member < ActiveRecord::Base
#Associations
belongs_to :department
has_one :student, :dependent => :destroy
accepts_nested_attributes_for :student
has_one :nstudent, :dependent => :destroy
accepts_nested_attributes_for :nstudent
has_many :posts, :dependent => :destroy
has_many :comments, :dependent => :destroy
end
app/models/post.rb
class Post < ActiveRecord::Base
#Associations
belongs_to :member
has_many :comments, :dependent => :destroy
accepts_nested_attributes_for :comments
end
app/models/comment.rb
class Comment < ActiveRecord::Base
# Associations
belongs_to :member
belongs_to :post
validates_presence_of :content
end
config/routes.rb
Urdxxx::Application.routes.draw do
devise_for :members
resources :posts do
member do
get 'update_comment'
end
end
root :to => 'posts#index'
app/controllers/posts_controller.rb
class PostsController < ApplicationController
# Devise filter that checks for an authenticated member
before_filter :authenticate_member!
# GET /posts
# GET /posts.json
def index
#posts = Post.find(:all, :order => 'points DESC')
respond_to do |format|
format.html # index.html.erb
format.json { render json: #posts }
end
end
...
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(params[:post])
#post.member_id = current_member.id if #post.member_id.nil?
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PUT /posts/1
# PUT /posts/1.json
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
# Not made by scaffold
def update_comment
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to #post, notice: 'Comment was successfully created.' }
format.json { head :no_content }
else
format.html { render action: "show" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
end
app/views/posts/show.html.erb
<p> Have your say </p>
<%= form_for #post, :url => {:action => 'update_comment'} do |p| %>
<%= p.fields_for :comments do |c| %>
<!-- Following 3 lines saved my life -->
<% if c.object.new_record? %>
<%= c.text_area :content, :rows => 4 %>
<%= c.hidden_field :member_id, value: current_member.id %>
<% end %>
<% end %>
<%= p.submit "Reply" %>
<% end %>
image of my show page:
http://i.stack.imgur.com/TBgKy.png
on making a comment:
http://i.stack.imgur.com/JlWeR.png
Update:
Looked back and made changes here, following what Ken said. I don't know how but it works for now.
app/controllers/posts_controller.rb
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
elsif :comments
format.html { render action: "show" }
format.json { render json: #post.errors, status: :unprocessable_entity }
else
format.html { render action: "edit" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
You don't need a custom method. It is not very RESTful. See, e.g., http://www.sitepoint.com/restful-rails-part-i/ for info on REST. This is not a case where there is justification to use a custom method.
Whenever you find yourself adding custom methods you should think long and hard about whether it's necessary. Usually if you need custom methods what you actually need is another controller (or a different set of controllers).
The update method here is all you need. If you really want to go to the show method after a failed update (though I don't know why) then change the render edit call in the block in the update method after the update fails.
It seems like your real problem is the edit view isn't showing errors. Although the scaffold generated view should do that so maybe you changed it.
In case you missed it you may also benefit from this screencast:
http://railscasts.com/episodes/196-nested-model-form-part-1
You need to update the method type in route and also needs to sets the form post method to your new action, also when you submit a form its an post request not a get request.
Urdxxx::Application.routes.draw do
devise_for :members
resources :posts do
collection do
post :update_comment
end
end
root :to => 'posts#index'
<p> Have your say </p>
<%= form_for :post, :url => {:action => 'update_comment'} do |p| %>
<%= p.fields_for :comments do |c| %>
<!-- Following 3 lines saved my life -->
<% if c.object.new_record? %>
<%= c.text_area :content, :rows => 4 %>
<%= c.hidden_field :member_id, value: current_member.id %>
<% end %>
<% end %>
<%= p.submit "Reply" %>
<% end %>

Resources