Rails form builder with admin namespace - ruby-on-rails

The code below works well to create new transactions on the Invoice show view. It however doesn't work when in admin namespace. i.e /admin/invoices/1/ but works on /invoices/1/
show.html.erb
<%= form_for([#invoice, #invoice.transactions.build]) do |form| %>
....
transactions form input
routes.rb
resources :invoices do
resources :transactions
end

When calling form_for in a namespace route like /admin/invoices/1/, Rails will automatically append admin to your route. In other words, form_for([#invoice, #invoice.transactions.build]) would POST to a route like /admin/invoice/:id/transactions/ rather than /invoice/:id/transactions/.
To fix, explicitly set the URL of the form and use a route helper method to infer the correct route:
form_for(#invoice, url: invoice_transaction_url(#invoice.id))
Note that you may need to replace invoice_transaction_url with the correct route. Use rake routes to find the helper method that corresponds to the desired controller POST action.

Related

Failed to try to use 2 ids on nestes routes in rails

I'm trying to pass 2 ids to the controller within the update action, but it does not stop, I do not recognize the first id, student_id. This is the definition of the route within routes.rb
post 'registers/students/:student_id/notes/:note_id/edit', to: 'registers/students/notes#update', as: :update_registers_student_note
While this is the part of the form_for, using the corresponding helper
<%= form_for #note, url: update_registers_student_note_path(:student_id,:note_id), method: :post do |f| %>
My question is how can I correctly pass the 2 ids of the corresponding resources, since the form only recognizes me note_id, and not student_id
Thank you
The helper should works. You also can use update_registers_student_note_path(student_id: 1, note_id: 12).
But I suggest you to use nested resources in your routes instead.
You can write somethings like that:
namespace :registers do
resources :students do
resources :notes
end
end
The new url helper will be registers_student_note_path(<note_id>, student_id: <student_id>) with method PATCH.
yes, you did put a right thing for url_helpers. You can try to open rails console and try it with these command
include Rails.application.routes.url_helpers
update_registers_student_note_path(1,2)
you will see => "/registers/students/1/notes/2/edit"

Rails no route match POST url on update with single resource

I'm creating a Rails application where there is a resource used as general settings for the whole website. I set everything as follows:
config/routes.rb
authenticate :user do
scope '/admin' do
resource :basics #This is my resource's name, put in singular
# ...
end
end
controllers/basics_controller.rb
private
# Use callbacks to share common setup or constraints between actions.
def set_basic
#basic = Basic.first
end
views/basics/_form.html.erb
<%= form_with(model: #basics, local: true) do |form| %>
Here is what rake routes shows about this resource:
new_basics GET /admin/basics/new(.:format) basics#new
edit_basics GET /admin/basics/edit(.:format) basics#edit
basics GET /admin/basics(.:format) basics#show
PATCH /admin/basics(.:format) basics#update
PUT /admin/basics(.:format) basics#update
DELETE /admin/basics(.:format) basics#destroy
POST /admin/basics(.:format) basics#create
I don't have any trouble making the form show up. However, when I submit it, I get the following error:
No route matches [POST] "/admin/basics/edit"
When I look at the HTML generated form, I can see that it passes "/admin/basics/edit" as an action while it should be just "/admin/basics" in my situation.
What should I do to make this work?
Thank you in advance
It looks like maybe you have the wrong instance variable passed to the form_with method? IIRC, Rails assumes the form action should be the same as the current path if the model argument is nil.
#basics is not defined (at least in the controller code you shared). Replacing it with #basic might work for edits (when Basic.first exists), but not create (if Basic.first doesn't exist).
You could try initializing #basic in your controller like this
def set_basic
#basic = Basic.first_or_initialize
end
Then pass it to form_with
<%= form_with(model: #basic, local: true) do |form| %>

url helper for namespace nested model

I am using the public_activity gem. To use the gem, you do not need to create an activities controller for it. So I did not. However, I do have a comments controller. I want to have the following url helper for the comment's create action:
public_activity_activity_comments_path(#activity)
I have tried two things in my routes and both have failed. First, I tried using a namespace route:
namespace :public_activity do
resources :activity do
resources :comments
end
end
This produces the error:
ActionController::RoutingError - uninitialized constant PublicActivity::CommentsController:
Since I do not have a PublicActivity::Activities controller, I tried this instead:
get '/public_activity/activity/:activity_id/comments/new', to: 'comments#new'
post '/public_activity/activity/:activity_id/comments', to: 'comments#create'
However, this does not seem to produce any url helpers at all, as it gives me the following error:
NoMethodError - undefined method `public_activity_activity_comments_path' for #<#<Class:0x007f868e1b7760>:0x007f868e1afd58>:
The reason why I want a route like that is because in my comments view, the commentable can be any model, so I prefer to have a polymorphic form:
<%= form_for [commentable, Comment.new] do |f| %>
...
Am I out of luck? Will I have to hardcore the url for form_for?
IMHO, you only need to play with your polymorphic association and form, Public_Activity will record the activities if you correctly configure that any model of yours.

Resource not generating helper method for create

I have a model called package, which has a controller package created under a name space admin.
so my resource in my routes is declared as below
namespace :admin do
resources :package
end
when I run rake routes
admin_package_index GET /admin/package(.:format) admin/package#index
POST /admin/package(.:format) admin/package#create
new_admin_package GET /admin/package/new(.:format) admin/package#new
edit_admin_package GET /admin/package/:id/edit(.:format) admin/package#edit
admin_package GET /admin/package/:id(.:format) admin/package#show
PUT /admin/package/:id(.:format) admin/package#update
DELETE /admin/package/:id(.:format) admin/package#destroy
If you see there is no helper method generated for create, which should have been admin_packages_path
controller
#newpackage = Package.new
view.html.erb
form_for [:admin,#newpackage] do |f|
end
is reporting that it is not able to find the admin_packages_path. Can somebody please explain how should we declare this in routes to generate the proper helper method for create ?
Your routes are named incorrectly, you're pairing a plural (resources) with a singular (:package).
If you will be working with multiple packages, you should declare resources :packages - this will generate you correctly named routes for all seven RESTful actions (index, show, new, create, edit, update, destroy).
If you are only working with a single package, you will need to specify the URL as an option for your form manually, eg.
form_for [:admin, #newpackage], url: admin_package_path do |f|
You really need to changes the routes to following:
namespace :admin do
resources :packages
end

Calling a specific action in a form tag

I have an action vote_for in my question controller.
what is the helper that enbales me to call this action from a view?
i tried :
vote_for_question_path(#question)
but this didn't work. ?
Since you've already defined resourceful routes for the Question resource, you should start by adding a member route on your existing resource route:
# config/routes.rb
resources :questions do
member do
get 'vote_for'
end
end
This will create the following route:
vote_for_question GET /questions/:id/vote_for(.:format) questions#vote_for
Next, create a controller action for the resulting route:
# app/controllers/questions_controller.rb
def vote_for
# logic goes here
end
Finally, in your view, you can construct a link to the route by passing the collection path to the link_to helper:
<%= link_to "Vote", vote_for_question_path(#question) %>
UPDATE:
If you'd rather represent the link as an HTML button than an <a> tag (as the OP is proposing in the comments to this answer), you can use the button_to form helper as follows:
<%= button_to "Vote", vote_for_question_path(#question), method: "get" %>
Note that, because you're replacing the link with a button, you should ensure that you're passing the correct HTTP submission method (which is GET in this instance) as an argument.
The path helpers only come when you define them in your routes.rb as a named route. So if you want a named non-RESTful route (which you do), you should add to your routes file:
get 'vote_for_question/:id', to: 'question#vote_for', as: 'vote_for_question'
And then you can call vote_for_question_path(#question.id) in your views and it will generate e.g. /vote_for_question/1.
See http://guides.rubyonrails.org/routing.html#generating-paths-and-urls-from-code for more on this.

Resources