Rails4 new template .erb creation Not Happening - ruby-on-rails

I have generated scaffold and created a view called "appointment"
I wanted to added a template .erb file called inbox_mail.html.erb in appointment folder.
I did setting like this.
route.rb
get '/appointments/inbox_mail'
In appointment controller
class AppointmentsController < ApplicationController
def inbox_mail
end
end
Now running the link 3000/appointments/inbox_mail
but giving rise error as,
Mongoid::Errors::DocumentNotFound in AppointmentsController#show
Problem: Document(s) not found for class Appointment with id(s) delete_appointment. Summary: When calling Appointment.find with an id or array of ids, each parameter must match a document in the database or this error will be raised. The search was for the id(s): delete_appointment ... (1 total) and the following ids were not found: delete_appointment. Resolution: Search for an id that is in the database or set the Mongoid.raise_not_found_error configuration option to false, which will cause a nil to be returned instead of raising this error when searching for a single id, or only the matched documents when searching for multiples.
Help me in Rails4...!!!!
May be this is b'z of
def set_appointment
#appointment = Appointment.find(params[:id])
end

Yes, it is because of set_appointment method. I guess you should add :id segment to your route, like
match '/appointments/delete_appointment/:id', to: 'appointments#delete_appointment', via: :get
and this should work.

Delete something shouldn't be done through GET, you should use the DELETE method. So, when you create the link with "link_to" you should do:
link_to 'Delete appointment', delete_appointment_path(#appointment.id), method: :delete
you need a route like:
delete '/appointments/delete_appointment/:id', to: 'appointments#delete_appointment'
Then rails will take care of that and do a DELETE request with the appointment's id, then on your controller you can use #appointment = Appointment.find(params[:id])
You may want some kind of validation to render a "not found" template:
def delete_appointment
unless #appointment = Appointment.find(params[:id])
redirect_to appointment_not_found_path #something_like_that
end
end
EDIT: it looks like some before_filter is messing up there too, you talked about "delete_appointment", the error say the action called is "show" and you copied the code for the action/before_filter "set_appointment", check that first
EDIT 2: you say you are not doing any delete, then use get, the important part is the :id on the url if you need to find an appointment by an ID you need that on the url. If you don't need the ID then check your before filters, I guess you have something like
before_filter :set_appointment
you may want to skip that filter on delete_appointment
before_filter :set_appointment, except: :delete_appointment

Related

NoMethodError in Rails while saving data

Checks_controller
class Checkscontroller < ApplicationController
def show
#check= Tester.find(params[:id])
end
def new
end
def create
#check = Tester.new(check_params)
#check.save
redirect_to #check
end
def check_params
params.require(:check).permit(:title, :description)
end
end
I am trying to save the data in 'checks' controller to 'Tester' model, getting "NoMethodError in ChecksController#create", undefined method tester_url' for#` while trying to save the data to my DB. There seems to be some issue on this line: "redirect_to #check".
Routes.rb
Rails.application.routes.draw do
get 'home/screen'
resources :checks
root 'home#screen'
end
EDIT: I see this answer got accepted. To anyone else looking at this: PLEASE DO NOT DO THIS WITHOUT A REALLY GOOD REASON.
Ok, so since you want to use the ChecksController for your Tester model, you'll have to add this to your routes: note that I'm assuming that you do not have a Check model, since I don't see it anywhere and youre using Tester as a check?
resources :testers, as: 'checks' controller: 'checks'
This line will make it so that /checks/1 goes to a Tester object with ID: 1, and use the ChecksController show method to show it
Old answer, for posterity
You're getting this error because you're missing routes for your Tester model in your routes.rb file.
You could add resources :testers to it and it will work. Of course you also already need AT LEAST your TestersController to exist with a show action
This error is occurring because when you redirect_to #check, Rails knows it's a Tester object and expects a route called tester to route to TestersController#show. It's attempting to use a helper method that rails creates for routes, called tester_url

Possible to Change Rails Routing Convention?

I'm wondering if it's possible to edit the default Rails routing convention to fetch a specific record based on a field that is not the ID?
For instance, instead of retrieving a specific record based on ID, with the verb/url combination:
GET /users/:id
Retrieve a specific record based on username, with the verb/url combination:
GET /users/:username
I don't see why this would be a problem theoretically, as long as usernames were required to be unique, but I'm having trouble understanding how to implement it based on the Rails Routing Guide.
I have gathered that I will need to add a line to my routes.rb file, to define a singular resource, just prior to:
resources :users
However, I'm having trouble understanding the syntax to accomplish this. Any help in understanding this would be greatly appreciated.
Yes it is possible and they are called Non Restful Routes in the rails documentation
A trivial example is doing the below in your routes.rb
get ':users/:show/:username', controller: "users", action: "show"
and in your UsersController you have a show action that looks like this:
def show
if params[:id].present?
#user = User.find(params[:id])
elsif params[:username].present?
#user = User.find_by(username: params[:username])
end
end
This way you support showing by id and username, if you want do disable support for either of them, modify the if clause as you wish
I think you are looking to change the to_param method like so:
class User < ActiveRecord::Base
def to_param
"#{id} #{name}".parameterize
end
end
This would give the url as: /user/id-name. If you want to get rid of the id before the name it gets a little more complicated. If you were just to remove it, it will more than likely break since ActiveRecord needs the id first for finds.
To get around this I would suggest using FriendlyId gem: https://github.com/norman/friendly_id
There is also a RailsCast showing how to use Friendly_id but its pretty straight forward.
The routes does not care if it is an ID or username.
It is really how you find it in the controller.
Just in the user show controller:
def show
#user = User.find_by_username params[:id]
end

StackOverflow Style Routes with Smart Redirects

StackOverflow seems to have this style of routes for questions:
/questions/:id/*slug
Which is easy enough to achieve, both in routes and to_param.
However, StackOverflow seems to also redirect to that path when just an ID is passed.
Example:
stackoverflow.com/questions/6841333
redirects to:
stackoverflow.com/questions/6841333/why-is-subtracting-these-two-times-in-1927-giving-a-strange-result/
Same goes for any variation of the slug
stackoverflow.com/questions/6841333/some-random-stuff
Will still redirect to the same URL.
My question is: Is this type of redirection typically handled in the controller (comparing the request to the route) or is there a way to do this in routes.rb?
The reason I wouldn't think this possible in the routes.rb file is that typically, you don't have access to the object (so you couldn't get the slug based off the ID, right?)
For anyone interested, Rails 3.2.13 and also using FriendlyID
Ok, so I think I've got this.
I was looking into doing something with middleware, but then decided that's probably not the place for this type of functionality (since we need to access ActiveRecord).
So I ended up building a service object, known as a PathCheck. The service looks like this:
class PathCheck
def initialize(model, request)
#model = model
#request = request
end
# Says if we are already where we need to be
# /:id/*slug
def at_proper_path?
#request.fullpath == proper_path
end
# Returns what the proper path is
def proper_path
Rails.application.routes.url_helpers.send(path_name, #model)
end
private
def path_name
return "edit_#{model_lowercase_name}_path" if #request.filtered_parameters["action"] == "edit"
"#{model_lowercase_name}_path"
end
def model_lowercase_name
#model.class.name.underscore
end
end
This is easy enough to implement into my controller:
def show
#post = Post.find params[:post_id] || params[:id]
check_path
end
private
def check_path
path_check = PathCheck.new #post, request
redirect_to path_check.proper_path if !path_check.at_proper_path?
end
My || in my find method is because in order to maintain resourceful routes, I did something like...
resources :posts do
get '*id' => 'posts#show'
end
Which will make a routes like: /posts/:post_id/*id on top of /posts/:id
This way, the numeric id is primarily used to look up the record, if available. This allows us to loosely match /posts/12345/not-the-right-slug to be redirected to /posts/12345/the-right-slug
The service is written in a universal fashion, so I can use it in any resourceful controller. I have't found a way to break it yet, but I'm open to correction.
Resources
Railscast #398: Service Objects by Ryan Bates
This Helpful Tweet by Jared Fine

howto find_by ownkey the exact entry in rails

we have an show-action which should find by the own_key the right entry. The own_key is generated as UUIDTools::UUID.timestamp_create().to_s.
The following question is now here.
class ListController < ApplicationController
respond_to :html, :xml, :json
def show
#list = List.find_by_own_key(params[:own_key])
respond_with(#list)
end
end
the routes are here so generates
resources :lists
match '/:id' => 'list#show'
why did we get also an entry back if we only type one simple letter after the /?
The own_key look so f6d47c20-a276-11e1-b127-68a3c454c2b4. So if we type an /lists/f i get the entry with an f own_key. how can we manage that we only get the entry with the own_key?
Could it run by an contraint?
thanks for the help if anone can help us?
Marcus
From your routes, params[:id] will contain the I'd to search for, however you're using params[:own_key] which will be nil. Instead of searching for the record with the specified value of own_key your code will always fetch the row with a null own_key.
Change your code to use params[:id] and you should be ok
U can use constrainsts for route or check params[:own_key] in controller
:constraints => {:own_key=> /regexp pattern for uuid/}

Overriding Rails to_param?

How do I get the to_param method to deliver keyword slugs all the time? I have trouble getting it to work with this route:
map.pike '/auction/:auction_id/item/:id', :controller => 'items', :action => 'show'
Earlier the overridden to_param was working for
'items/1-cashmere-scarf'
but fails with 'auction/123/item/1'
Update:
I'm not sure if the syntax is correct[(edit: it's correct: it works :-)], or even efficient.... but using haml, I found that the following code works to generate the desired link ('auction/:auction_id/item/:id')
- for auction in #auctions.sort{|a, b| a.scheduled_start <=> b.scheduled_start}
-for item in #items
- unless auction.current_auction
... pike_path(auction.auction_id, item)
I'm not sure whether I understand your question. (it's 3:41 AM here)
From what I see, you directly access auction_id method, instead of using pike_path(auction, item) that'd use #to_param.
Also, it might fail for auction/123/item/1 because you haven't changed your controller.
I think it'd be helpful to describe how to get working slugs.
Broadly speaking, if you override #to_param, IDs no longer works. It means, that if you go with slugs, every time polymorpic URL is generated (eg, link_to object, object), it passes to_param's value. It is worth noting that you must change your controller as well.
Personally I think that the best way to generate slugs easily is to use techno-weenie's permalink_fu, adding has_permalink to your model, and then, override to_param. For example
class Auction < ActiveRecord::Base
has_permalink :title, :slug
end
assuming that you have slug, a string field, and want to slugize your title.
You also need to adjust your controller:
class AuctionsController < ApplicationController
def show
#auction = Auction.find_by_slug(params[:id]) || raise(ActiveRecord::RecordNotFound)
respond_to do |format|
format.html # show.html.erb
end
end
Then, you can generate routes, in the views, this way:
link_to #action, #action
By the way, you should NOT sort your actions in the view. The best way is to use named_scope.

Resources