I'm writing a little Rails CMS and I'm a little stuck with a routing error. To begin with, I have a basic model called Entry, which other models are inheriting from. When I try to edit an existing model, it returns me an error
No route matches [PATCH] "/admin/posts/entries"
In my routes.rb in CMS plugin I have the following:
Multiflora::Engine.routes.draw do
root "dashboard#index"
scope "/:content_class" do
resources :entries
end
end
and in test app's routes.rb I have
mount Multiflora::Engine, at: '/admin'
In application_controller.rb I also tweaked routes a little:
def content_entries_path
entries_path(content_class: content_class.tableize)
end
helper_method :content_entries_path
def content_entry_path(entry)
entry_path(entry, content_class: content_class.tableize)
end
helper_method :content_entry_path
def new_content_entry_path
new_entry_path(content_class: content_class.tableize)
end
helper_method :new_content_entry_path
def edit_content_entry_path(entry)
edit_entry_path(entry, content_class: content_class.tableize)
end
helper_method :edit_content_entry_path
And in my show.html.erb I have this:
<%= link_to 'Edit', edit_content_entry_path(#entry) %>
When I navigate to edit_content_entry_path, it shows me edit page correctly, but when I try to save edited entry, it returns me an error stated above. When I run rake routes, it returns me the following:
entries GET /:content_class/entries(.:format) multiflora/entries#index
POST /:content_class/entries(.:format) multiflora/entries#create
new_entry GET /:content_class/entries/new(.:format) multiflora/entries#new
edit_entry GET /:content_class/entries/:id/edit(.:format) multiflora/entries#edit
entry GET /:content_class/entries/:id(.:format) multiflora/entries#show
PATCH /:content_class/entries/:id(.:format) multiflora/entries#update
PUT /:content_class/entries/:id(.:format) multiflora/entries#update
DELETE /:content_class/entries/:id(.:format) multiflora/entries#destroy
So, the error was in my edit.html.erb view -- instead of
<%= form_for(#entry, as: :entry, url: content_entry_path(#entry)) do |f| %>
I had
<%= form_for(#entry, as: :entry, url: entries_path do |f| %>
When I rewrote it, everything worked!
Related
I'm new to rails, and I've already learnt how to do CRUD using scaffold and using resource, I wanna know how to Do CRUD without using resource, However what I want to do is create custom methods for CRUD in the controller that will be like the traditional CRUD model. Please help me with this.
Actually, for the action index / new / show / create / edit / update / destroy, this is a convention in Ruby On Rails
If I'm right and if you're trying to change their name using resources in routes.rb (Changing by exemple the new action into def my_restaurant), Rails will render
Unknown action The action 'new' could not be found for
RestaurantsController
Netherless, you can create some methods to perform some particular action into the index, and add them in the "private section" you want to hide them to the public. There is no routes attach to this method.
class RestaurantsController < ApplicationController
def index
#restautants = Restaurant.all
#restaurants.sort_by_name
end
private
def sort_by_name
#some action here
end
end
If you want to create your own name method, you can personnalise it but you can't use resources "shortcut" in the routes.rb
by exemple :
#reviews_controller.rb
class ReviewsController < AplicationController
def index
#reviews = Reviews.all
end
def update
#review = Review.find(review_params[:id])
end
def history
#some action
end
private
def review_params
params.require(:review).permit(:liked, :comment, :id)
end
end
Then add a view
#app/views/reviews/history.html.erb
Don't forget the routes :
Rails.application.routes.draw do
resources :reviews, only: [:index, :update] do
collection do
get :history
end
end
end
I hope this will help you and complete the previous answer.
as for your second question :
I still do have one doubt tho..... Will <%= form_for #post do |f| %>
this form be enough for new_post and edit_post, will it automatically
identify them? If that's not enough can you please tell me the what
comes at new_post.html.erb and edit_post.html.erb....Thanks again for
the help.
If the form is the same for your new_post and edit_post, i may suggest you to put into a partial file. (For this example I used simple_form gem)
#app/views/posts/_form.html.erb
<%= simple_form_for(#post) do |f| %>
<%= f.input :name, label: "post name" %>
<%= f.input :photo, as: :file %>
<%= f.submit "Save", class:"btn btn-small btn-success" %>
<% end %>
and then render the partial in your views new file.
#app/views/posts/new.html.erb
<div>
<h1>New Post</h1>
</div>
<%= render "form" %>
Well I hope I could help you with this answer.
Do not hesitate too to read ruby documention. You may find more information that you're looking for too.
My answer may be redundant but it's the better way for me to clearly explain it...
In oder to use your own custom methods you need to create them in your controller, setup the route and if needed create an view.
# PostsController
def create_post
# Do your create stuff here
end
def read_post
# Do your read stuff here
end
def update_post
# Do your update stuff here
end
def delete_post
# Do your delete stuff here
end
# routes
post '/create_post', to: 'posts#create_post'
get '/read_post/:id', to: 'posts#read_post'
put '/update_post/:id', to: 'posts#update_post'
delete 'delete_post/:id', to: 'posts#delete_post'
With the controller and routes setup you will only need a view for the read_post method. The best way to do that is create the file: views/posts/read_post.html.erb
There is 7 CRUD routes to Create, Read, Update and Delete.
Rails.application.routes.draw do
get "restaurants", to: "restaurants#index"
get "restaurants/new", to: "restaurants#new", as: :new_restaurant
post "restaurants", to: "restaurants#create"
# NB: The `show` route needs to be *after* `new` route.
get "restaurants/:id", to: "restaurants#show", as: :restaurant
get "restaurants/:id/edit", to: "restaurants#edit", as: :edit_restaurant
patch "restaurants/:id", to: "restaurants#update"
delete "restaurants/:id", to: "restaurants#destroy"
end
So once the route create, you can create in the controller, the action that you need
class RestaurantsController < ApplicationController
def index
#restaurants = Restaurant.all
end
end
and the view
app/views/restaurants/index.html.erb.
The best practice is to create only the routes that you will need and to work in silos.
1 route, 1 controller action, 1 view.
Routes:
get 'home/index' => "home#index"
namespace :lawyers do
get 'all/:division/:district' => "profiles#index", as: :division_district_all
get 'all/:speciality/:sub_speciality' => "profiles#index", as: :speciality_subspeciality_all
end
Home controller #Index view:
<% #districts.each do |district| %>
<%= link_to district.name, lawyers_division_district_all_path(district.division.name.parameterize,district.slug) %>
<% end %>
<% #sub_specialities.each do |sub_speciality| %>
<%= link_to sub_speciality.name,lawyers_speciality_subspeciality_all_path(sub_speciality.speciality.name.parameterize,sub_speciality.name.parameterize)%>
<% end %>
Profile Controller #index:
raise params.inspect
Every time I hit with speciality and sub_speciality but this shows division and district value in params. It conflicts because the pattern is similar. How can I get rid of this ?
You are going to need to separate the destination method on the controller and update the routes.
I would recommend this approach:
namespace :lawyers do
get 'division/:division/:district' => "profiles#division", as: :division_district_all
get 'speciality/:speciality/:sub_speciality' => "profiles#speciality", as: :speciality_subspeciality_all
end
Update: Based on strong requirements, you could use query params all/:division/:district?query_by=divison you would only need one route.
get 'all/:primary/:secondary' => "profiles#index", as: :lawyers_all
And then in the controller, manage the logic with something like
def index
case params[:query_by]
when 'division'
# Division logic here
when 'speciality'
# speciality logic here
else
# Error handling here
end
end
Update 2: As you mentioned on the comments, URL cannot change. Still you would need only one route
get 'all/:primary/:secondary' => "profiles#index", as: :lawyers_all
And check existence on db based on the params, this will impact the performance of your app by creating a lot of db requests and also will create the potential issue of matching with the incorrect classes.
def index
if Division.find_by(name: params[:primary]).present?
# Division logic here
elsif Speciality.find_by(name: params[:primary].present?
# speciality logic here
else
# Error handling here
end
end
I am getting an undefined method stripe_managed_accounts_path when trying to create a new resource via typical rails forms. Below is my code, I am dumbfounded, cannot figure it out.
Controller
class StripeManagedAccountsController < ApplicationController
before_action :authenticate_printer!
def new
#stripe_managed_account = StripeManagedAccount.new(printer_id: current_printer.id)
end
end
model
class StripeManagedAccount < ActiveRecord::Base
belongs_to :printer
end
views/new
<h1>Create New Stripe Managed Account</h1>
<%= render 'form' %>
view/form
<h5>inside the form</h5>
<%= form_for #stripe_managed_account do |f| %>
<% end %>
routes
resources :printers, only: [:show, :edit, :update] do
resources :stripe_managed_accounts
end
error
`undefined method 'stripe_managed_accounts_path' for #<#<Class:0x007fc627d342b8>:0x007fc62b36e108>`
routes
printer_stripe_managed_accounts GET /printers/:printer_id/stripe_managed_accounts(.:format) stripe_managed_accounts#index
POST /printers/:printer_id/stripe_managed_accounts(.:format) stripe_managed_accounts#create
new_printer_stripe_managed_account GET /printers/:printer_id/stripe_managed_accounts/new(.:format) stripe_managed_accounts#new
edit_printer_stripe_managed_account GET /printers/:printer_id/stripe_managed_accounts/:id/edit(.:format) stripe_managed_accounts#edit
printer_stripe_managed_account GET /printers/:printer_id/stripe_managed_accounts/:id(.:format) stripe_managed_accounts#show
PATCH /printers/:printer_id/stripe_managed_accounts/:id(.:format) stripe_managed_accounts#update
PUT /printers/:printer_id/stripe_managed_accounts/:id(.:format) stripe_managed_accounts#update
DELETE /printers/:printer_id/stripe_managed_accounts/:id(.:format) stripe_managed_accounts#destroy
and it is highliting this line <%= form_for #stripe_managed_account do |f| %>
I have grepped the entire code base for stripe_managed_accounts_path and it is no where. I am at odds end...
UPDATE:::
If I add that route it disappears??? Why is it looking for that route. Is it becasue of how I named my fodlers, etc??
You're nesting stripe_managed_accounts inside printers on your routes file. If you take a look at the output of rake routes, you can see that there isn't a path for stripe_managed_accounts_path.
You can either use the shallow option on the stripe_managed_accounts resource or adjust your form to include the printer which the managed account will belong to.
#controller
class StripeManagedAccountsController < ApplicationController
before_action :authenticate_printer!
def new
#stripe_managed_account = current_printer.build_stripe_managed_account
end
def create
current_printer.stripe_managed_accounts.create stripe_managed_account_params
# handle response
end
def stripe_managed_account_params
params.require(:stripe_managed_account).permit([list of attributes])
end
end
#form
<h5>inside the form</h5>
<%= form_for [current_printer, #stripe_managed_account] do |f| %>
<% end %>
That will generate the proper url, nesting the stripe_managed_account inside the current printer.
For has_one association reference http://guides.rubyonrails.org/association_basics.html#has-one-association-reference
I am trying to learn RoR.
MY controller is
class SectionController < ApplicationController
def new
if request.post?
u=SectionMst.new( :section_name => params[:section_name])
u.save
redirect_to("/section")
else
render
end
end
def index
#sections = SectionMst.all
end
def destroy
u=SectionMst.destroy(params[:id])
u.save
redirect_to("/section")
end
def edit
#user = SectionMst.find(params[:id])
end
end
and index.html.erb is
<%= link_to "Edit", edit_section_path(section.id), method: :edit %>
rake routes is
section_new POST /section/new(.:format) section#new
POST /section/:id/edit(.:format) section/:id#edit
section_index GET /section(.:format) section#index
POST /section(.:format) section#create
new_section GET /section/new(.:format) section#new
edit_section GET /section/:id/edit(.:format) section#edit
section GET /section/:id(.:format) section#show
PUT /section/:id(.:format) section#update
DELETE /section/:id(.:format) section#destroy
routes.rb is
post "section/new"
post "section/:id/edit"
resources :section
i am getting the
Routing Error
uninitialized constant Section
if i delete the second line of routes.rb
then i get
Routing Error
No route matches [POST] "/section/3/edit"
not able to get why???
Get rid of the first and second lines in your routes.rb. They're redundant. The resources will create these lines automatically.
The resources :section should be written as resources :sections. Notice that it's plural.
In your index.html.erb, you shouldn't mention method: at all. It's automatically set, and :edit as method doesn't exist. Method refers to put or get or delete, but you normally don't have to mention it.
You do not need this lines in your routes.rb
post "section/new"
post "section/:id/edit"
Change the third line to:
resources :sections #plural
If you delete them, you can hit the edit view using
<%= link_to "Edit", edit_section_path(section.id), method: :edit %>
which will hit your app at section/3/edit with a GET request.
In your edit.html.erb, you can then have fields to capture edits and do a PUT to /section/3.
Note that RAILS uses HTTP verbs to define the CRUD operations. Ref here.
Check your controller's file name because it should be plural. It is supposed to match the class name. So, you should rename app/controllers/section_controller.rb to app/controllers/sections_controller.rb.
I have a route like this.
get 'mypage' => 'mypage#browserUpdate'
I added a controller called:
mypage_controller.rb
class MypageController < ApplicationController
def browserUpdate
puts "browser_update controller working"
end
end
In my views folder I have a folder called.
mypage > browserUpdate.html.erb
When i put a link in the application.html.erb
<div><%= link_to 'UPGRADE PATH', mypage_path %></div>
When I click the link I get an error:
Assertion failed: The URL '/mypage' did not match any routes in your
application
Rake routes says. mypage GET /mypage(.:format) mypage#browserUpdate
Anyone know what I'm doing wrong here.
I think your controller should be plural, i.e. it should be mypagescontroller.
routes.rb
get 'mypage' => 'mypage#browserUpdate', as: 'browser_update'
application.html.erb
<%= link_to 'UPGRADE PATH', browser_update_path %>
This should help.