Skipping the New Method in Controller (Go Right to the Create Method) - ruby-on-rails

In Rails, I'd like to skip the "new" method in a controller entirely and go directly to the create method. (I don't need any form data to be submitted, and just want to go directly to creating the object based on data from the currently logged in user.)
In rake routes, I don't see a prefix that allows me to link directly to the controller's create method, so I think I should link to the new method and have that redirect to the create action without accepting any input.
I tried doing this with the following:
def new
create
end
def create
#request = Request.new
#request.requestor_id = current_user.id
#request.status = "S1"
#request.save
respond_with(#request, :location => "/products/findexchanges")
end
When browsing the DB, I can see that this is calling the create action and is adding the record to the db, but after it is done it is redirecting me to new.html.erb rather than the location defined at the end of the create method.

A create action should be triggered by a POST, not GET, which is why there is no specific route for it.

Use button_to instead of link_to. I tried using link_to and even after specifying method: :post, action: :create, it still takes me to index using GET. After using button_to and passing params in ####_path, it directly went to the create method and added data to database. Although I am not sure its correct way or safe way to do this.

Related

How are params passed from the New to Create action in Rails?

I understand that the new action for a rails form normally instantiates a model and provides a view with inputs for permitted params.
def new
#post = Post.new
end
What I don't get is how that same information submitted by the user is carried over to Post.new method inside the create action:
def create
#post = Post.new(post_params)
...
end
How does rails channel these params to create despite the page refresh that occurs?
You are mixing two requests with each other. When you hit the new action, a view that contains your form gets rendered. As it gets rendered, the new action finishes, and now the new action has nothing to do with create action.
You need new action to create a form through form_for method in which you actually pass an object, in your case #post.
The create action is independent, and params it receives, they have nothing to do with new method, those params are received through form rendered in the new.html.erb file of views.
You can also invoke the create method in your controller by sending the data through AJAX or even using cURL or POSTMAN - a chrome extension.
And as you asked:
How does rails channel these params to create despite the page refresh that occurs?
Rails doesn't channel these params, Rails run at back-end, Rails just receives those params. They are sent through an HTML form, and as I said earlier there are other ways to send params as well.

How do I execute a method in a view?

I'm trying to find the best way to execute a method in a Rails application.
I have the following in my model:
class Tweet < ActiveRecord::Base
def self.fetch_all
# do something
end
end
I can go to my Rails console and run Tweet.fetch_all and it executes everything inside this method. However, I'd love to create an link in my application to execute this fetch inside the view. Would I need to create a new action inside my controller to get to this?
Actions are executed by controllers, so you need to define an action in tweets_controller.rb:
def fetch_all
Tweet.fetch_all #what do you want to do with this?
redirect_to :back, notice: 'just called fetch_all'
end
and define a way to get to this action in routes.rb
post 'tweets/fetch_all', to: 'tweets#fetch_all'
Then you can use
<%= link_to 'Fetch all!', fetch_all_tweets_path, method: :post %>
anywhere in your views.
Yes, if you want to create a separate link to execute this function, you will need to first create an action inside the controller for this purpose, and then later, you can create a helper method or simply, use link_to to place the link in your views.
Reason being that, if you add this method inside some other REST action, this fetch will be performed whenever that action is rendered, and this might not be what you intend.
Therefore, you should create another action that specifically executes this code for you, thereby, allowing you to specifically execute this method, whenever the user clicks that link.

Rails Forms for custom actions

I'm trying to link the input of a form to a specific action in my rails app.
Currently if I go to www.myapp.com/check/:idNumber, I'll be able to trigger the action just fine (which means routes is setup properly?). This action is basically a function call to a ruby/rails script with the parameter "idNumber" being passed to it. If the function is successful, it would return a newly created "Person" object and nil otherwise. This is different than the standard new operation as it determines the the attributes based on some information that it obtained from a database somewhere else.
Rake routes does give me the following:
check /check/:idNumber(.:format) person#check {:id=>/\d+/}
What I'm having trouble implementing is the form itself.
<%= form_tag("/check", :method => "get") do %>
<%= text_field_tag(:idNumber) %>
<% end %>
Controller action:
def check
regCheck = RegCheck.new
#person = regCheck.check_id(params[:idNumber])
if #person.name == nil
redirect_to root_path
end
end
submitting the form above would bring me to myapp.com/check?utf8=✓&idNumber=1234 instead. Can someone tell me what am I doing wrong?
I believe that using the check_path helper that is generated from the routes file is your best bet.
The form should look like this then.
<%= form_tag(check_path) do %>
<%= text_field_tag(:idNumber) %>
<% end %>
Rails forms can be finicky, especially when trying to build really customized forms.
This line
= form_for [#object]
Determines where the form goes, as well as the object that is being implemented. If you want to route the form to a different place, you can user the :url option. This options determines the path of the form, however you must keep in mind that the method is determined by the #object. If it is a new object, the method will be POST, an existing object will use a PUT method.
Let's suppose you want to update an existing object, but you want to send in data for a new object belonging to the existing object. That would look like
= form_for [#object], :as => #child_object, :url => my_optional_custom_path do |f|
# etc...
This generates a form sending a PUT request to the custom url (or the update path for #object if no custom url is supplied. The PUT request is sent with the parameter params[:child_object].
Hopefully this helps!
Best,
-Brian
I don't think it's possible the way you're trying.. The URL for the form is created before the user inputs any data.. So you need to remove the :idNumber from your routing..
If you do you get the following route:
check /check(.:format) person#check
Because the regex is removed now, you need to do this in you're controller:
def check
# Make sure ID is digits only
idNumber = params[:idNumber].gsub(/[^\d]/, '')
regCheck = RegCheck.new
#person = regCheck.check_id(idNumber)
if #person.name == nil
redirect_to root_path
end
end
You're form is allright, but you may want to use check_path like TheBinaryhood suggests..
If you really want it to be check/:idNumber you may also be able to submit the form to another action and redirect it to the right path from there..

link_to custom action but wrong method?

all, I'm trying to get a custom action to work with a put method: in the
in _post.html.erb i have a link_to statement:
<%= link_to 'End now', post, :method => :put, :action => endnow %>
routes.rb contains:
resources :posts do
member do
put :endnow
end
and posts_controller.rb looks like:
class PostsController < ApplicationController
helper_method :endnow
[.. code for create, edit, destroy, etc ..]
def endnow
puts params
end
end
rake routes's relevant line looks like:
endnow_post PUT /posts/:id/endnow(.:format) posts#endnow
However, the action endnow helper doesn't run when clicking on this link.
Strangely, it does run with an index action (which i can tell from the puts command.
Of course, eventually the code for endnow will update #post, but for now, it just doesn't run properly.
Maybe i'm going about this the wrong way - all I'm trying to achieve is to update #post upon clicking the link to that post, and before showing it.
Any ideas / Alternatives?
Why not use the route helper method provided to you? Change your link to
<%= link_to 'End now', endnow_post_path(#post), method: :put %>
Things you're doing wrong:
If you want to specify the :action, use the Symbol for the action (you're missing a colon). :action => endnow should be action: :endnow
I will assume you have a #post instance variable you're passing from your controller to your action. You should be using that instead of post (unless you do in fact have a local post variable you're omitting from your code)
You are using endnow as an action; you should remove the helper_method :endnow line in your controller because it's not something you want to/should be accessing from your view.
This can all be avoided by using the route helper (for endnow_post you'd append _path to get the local route path: endnow_post_path), and pass in your #post as an argument.
Because you're trying to do a PUT request, you must make sure you have something like jquery-ujs included in your asset pipeline to convert these links to form submissions behind the scenes; browsers don't support PUT via the click of a link on their own.
As for why you're getting the template error when you get your link_to working, Rails is telling you that you need to create a app/views/posts/endnow.html.erb file. Your action has only puts params which does not terminate execution, leaving Rails to assume you still are trying to render some endnow.html.erb template.
Are there other ways to do what you're trying to do (change a single attribute of a specific model)? Sure. Are there better ways? That's pretty subjective; it may not be the most RESTful way, but it's arguably easier to deal with (if for example there are very specific authorization rules to check before updating the attribute you are modifying in endnow. Does the way you've started fleshing out work? Absolutely.
Finally, as a bump in the right direction, after you fix your link_to and remove the the helper_method as I have described above, your endnow action might look like this:
def endnow
post = Post.find!(params[:id])
post.some_attribute_here = some_new_value_here
post.save
redirect_to :root and return # <- this line sets a redirect back to your homepage and terminates execution, telling rails to do the redirect and **not** to render some endnow.html.erb file
end

Rails, redirect from NEW to CREATE

Hey all, I'm writing an app to handle registration for athletic events. Some of these events have multiple athletes per entry, while some have only a single athlete. I'm currently sending the athlete to the NEW action on BoatsController like so:
<%= link_to 'Register', new_event_boat_path(#event) %>
My question is, if the NEW action sees that the event only requires one user per boat, how can I forward the user directly to the CREATE action? More concisely, how can I generate a POST from within an action?
You dont need to do anything fancy. The create action is just a method in your controller. You can call it just like any other method:
def new
if event_only_requires_one_user_per_boat
create
else
#display new form
end
end
Also, this technique prevents the user from having to make multiple requests since it doesn't make the user redirect.
You could instead create a method that encapsulates most of the code from your create action, and invoke it from create (with params as usual) and from your special case in new (sending in data from your user object).
def new
#assuming boats is an array
if boats.size > 1
redirect_to boats_path(:user => params[:user], :boat => params[:boat]), :method => :post
else
#new stuff
end
end
boats_path or whatever object you are trying to create.

Resources