How do I add a route to a custom controller methods in Rails?
I have the following methods and want to call them via AJAX.
def w_destroy
render json: RHoliday.where(holiday_id: params[:holiday_id].to_s, group_id: params[:group_id].to_s).destroy
end
def w_create
#r_holiday = RHoliday.new(r_holiday_params)
respond_to do |format|
if #r_holiday.save
format.html { redirect_to #r_holiday, notice: 'RHoliday was successfully created.' }
format.json { render action: 'show', status: :created, location: #r_holiday }
else
format.html { render action: 'new' } format.json { render json: #r_holiday.errors, status: :unprocessable_entity }
end
end
end
The question is:
How do I do this? I think I need to edit my routes.rb but I don't know what to add there. I just used resources :r_holidays, but this just creates the default routes.
You can add extra routes out of resources scope in many different ways:
#config/routes.rb
resources :r_holidays do
post :w_create
delete :w_delete
end
Specifically, the resources call basically gives you Rails' standard 7 RESTful routes - you can use a code block to define extra routes as required. You should read the documentation to get some more ideas
Related
I am creating a Rails 4.2.6 /MongoDb app. I created a new action manually called 'calluser', made the change in routes to including it:
resources :companies do
member do
get 'calluser'
end
end
I can see it when I execute the 'rake routes' command:
call_user_company GET /companies/:id/call_user(.:format) companies#call_user
However, When I redirect from the controller:
if #company.save
format.html { redirect_to calluser_company(#company), notice: 'Company was successfully created.' }
format.json { render action: 'show', status: :created, location: #company }
else
format.html { render action: 'new' }
format.json { render json: #company.errors, status: :unprocessable_entity }
end
I receive the following error:
undefined method `calluser_company' for #<CompaniesController:0x007fdd893f3270>
Any Idea why this is happening ? I will appreciate any help.
I read a previous similar problems but they didn't work for me:
Create a new action for existing controller
Route a form to new controller action in Ruby on Rails
Your routes describes:
call_user_company GET /companies/:id/call_user(.:format) companies#call_user
so you can use call_user_company_url(#company) or call_user_company_path(#company) instead of calluser_company(#company)
I've read through the following tutorial and found the curious line:
notice that the create function is written in such a way that there has be a #post before creating a #comment.
You can see the supporting controller code:
Class CommentsController < ApplicationController
----
def create
#post = Post.find(current_post)
#comment = #post.comments.create(post_params) ## 'Essential stuff'
respond_to do |format|
if #comment.save
format.html { redirect_to action: :index, notice: 'Comment was successfully created.' }
format.json { render :show, status: :created, location: #comment }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
----
end
Indeed, "current_post" implies that the post was created BEFORE the comment.
But what if I want both to be created simultaneously? For example, suppose my USER has_many EMAILS, and each EMAIL belongs_to a USER. Then, when creating a new user, I may want to have an expandable form that allows the user to add one, two, three, or twenty emails while creating his account.
How could this be done?
Nested Attributes is the rails way of doing what you want to achieve.
Checkout http://railscasts.com/episodes/196-nested-model-form-part-1
You need to consider using nested form, have a look into this gem, very easy to implement. It will allow the user to add multiple emails as required.
I am trying to use the standard create method created for Ruby/Rails projects and simply pass in an additional form field that tells the method how many objects to create (vs just creating one object). The standard create method looks like so:
def create
#micropost = Micropost.new(micropost_params)
respond_to do |format|
if #micropost.save
format.html { redirect_to #micropost, notice: 'Micropost was successfully created.' }
format.json { render :show, status: :created, location: #micropost }
else
format.html { render :new }
format.json { render json: #micropost.errors, status: :unprocessable_entity }
end
end
end
I want to pass in an additional data (form field called number_to_create) which tells the method how many of the microposts to create. I just added a new form field like this, in addition to the other micropost form field params:
<%= text_field_tag :number_to_create %>
My question is how do I modify the create method code such that it creates N number of micropost objects vs. just one. So if I pass in 3 from the form along with the other micropost attributes, the method creates 3 identical micropost objects, not just one as it currently does.
Thanks in advance for your help on this.
You could use the param as times
#microposts = Micropost.transaction do
[].tap do |microposts|
param[:number_to_create].times do
microposts << Micropost.create(micropost_params)
end
end
end
respond_to do |format|
if #microposts.all? &:persisted?
format.html { redirect_to #micropost, notice: 'Micropost was successfully created.' }
format.json { render :show, status: :created, location: #micropost }
else
format.html { render :new }
format.json { render json: #micropost.errors, status: :unprocessable_entity }
end
end
The transaction block is to make sure that either all of them gets saved, or none of them gets saved, this way you can fix your errors and recreate them without worrying of getting any stray saved objects
The following is a standard posts#create action (app/controllers/posts_controller.rb).
At the controller level, I want to prevent an anonymous user (a user who is not signed in) from being able to save a post. As a secondary objective, I don't even want to execute the Post.new line if the user is not signed in. I want to know what is the best practice for accomplishing this.
Also, as a side note, I am unsure of how to write the json portion of the response. If I am redirecting with an alert message in the HTML context, what would be a good thing to respond with in JSON world?
def create
#posting = Post.new(posting_params)
respond_to do |format|
if #posting.save
format.html { redirect_to #posting, notice: 'Post was successfully created.' }
format.json { render action: 'show', status: :created, location: #posting }
else
format.html { render action: 'new' }
format.json { render json: #posting.errors, status: :unprocessable_entity }
end
end
end
For the time being I have the following line in my code, above the Post.new line:
redirect_to home_path, warning: 'You must be logged in to post.' and return unless user_signed_in?
I suppose another option is something like the following, placed above the if #posting.save line. But really, I am looking to see what other folks would do.
unless user_signed_in?
format.html { redirect_to home_path, alert: 'You must be logged in to post.' and return }
format.json { render json: .....not sure what to put here..... }
end
Your advice is greatly appreciated.
A before_filter is good for this sort of thing:
before_filter :confirm_user_signed_in, only: [:new, :create]
def confirm_user_signed_in
unless user_signed_in?
respond_to do |format|
format.html { redirect_to home_path, alert: 'You must be logged in to post.' and return }
format.json { render json: .....not sure what to put here..... }
end
end
end
As far as what to render in the JSON scenario, you can render nothing at all, but with a 403 (Forbidden) status. You can optionally include some data explaining why the 403 occurred, but there's no standard for how that data will be displayed. Some frameworks (Backbone, I think) will look for a hash containing an errors key, which can be set to the reason.
Something like:
format.json { render json: { errors: ["Login required."] }, status: 403 }
The better practice is to use before filter and mention list of actions like this:
before_filter :require_login, :only => [:new, :create]
Try using the cancan gem. You can not only prevent the unwanted user from posting, also you can do various other permissions, which do not bloat the controller. These permissions are defined by you in a separate file called ability.rb.
cancan Railscast
cancan Github
I have a Rails 3 blog-style application, where I've got an admin namespace for backend purposes and a controllers/admin subfolder containing the respective posts_controller.rb.
So the page's root url is set to "admin/posts#index", and post creation works fine, except when I configure the routes file to redirect the user to root_url if he types "/admin/articles".
This is my routes file:
BlogDos::Application.routes.draw do
# Index
root to: "admin/posts#index"
# If I uncomment these two lines below, the post#create function doesn't work. When I
# submit the "new post" form, the controller just skips the function entirelly and
# redirects me to admin/posts#index without creating the new post.
# match "admin/posts" => redirect("/")
# match "admin/posts/" => redirect("/")
namespace :admin do
resources :cpanel
resources :posts do
resources :comments, :only => [:create, :destroy]
end
root to: "cpanel#index"
end
..
end
And this is my posts_controller.rb
def create
#usuario = current_user
#post = #usuario .posts.create(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to article_dir_path(#post.year, #post.month, #post.slug), notice: 'Article was successfully created.' }
format.json { render json: article_dir_path(#post.year, #post.month, #post.slug), status: :created, location: article_dir_path(#post.year, #post.month, #post.slug) }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
Strangely, this only happens with the Create action, If i edit an article and update it, everything works fine.
I have sorted out almost everything from looking at Rails tutorials and QA websites, except this little problem, I'm sure it is something rather simple, but i'm new to Rails and not very familiar with its routing mechanics yet.
The form that creates the post submits to
/admin/posts
If you redirect that route to the index page, the controller action is never called.