I am trying to use a controller and action to do a simple check to see if a user account with that email address exists or not.
The controller's action looks like this:
def checkEmail
email = params["email"]
if Account.find_by_email(email).blank?
render :inline=>"true"
else
render :inline=>"false"
end
end
And to test this action, I can go to:
http://localhost:3000/home/checkEmail/email#website.com
When I do so, I can see in the Ruby console the following being queried:
Parameters: {"email"=>"email#website"}
Account Load (0.0ms) SELECT `accounts`.* FROM `accounts` WHERE `accounts`.`email` = 'email#website' LIMIT 1
You can see that the TLD of the email address has been cropped off.
However, when I go to:
http://localhost:3000/home/checkEmail/email#website.co.uk
I get a routing error:
No route matches [GET] "/home/checkEmail/email#website.co.uk"
My routes.rb file looks like this:
Gallery::Application.routes.draw do
#Match home URL
match 'home(/:file)' => "home#index"
match 'home/checkUser/:username' => "home#checkUser"
match 'home/checkEmail/:email' => "home#checkEmail"
root :to=> "home#index"
end
Yeah, the default behavior in Rails is to treat a dot (.) in a route as a format specifier, instead of part of the parameter.
In order to match the dot as part of the parameter, specify the route like this:
match "/home/checkEmail/:email" => "home#checkEmail", :constraints => { :email=> /[^\/]*/ }
Here's a post that describes the problem and the fix:
http://coding-journal.com/rails-3-routing-parameters-with-dots/
Related
In the rails the default behavior shows the id in the url like
http://0.0.0.0:3000/users/1
Now to change the url to show me something other than the id, I know I could put this in model
def to_param
name
end
And then get something like http://0.0.0.0:3000/users/mikey
I am wondering how can achieve a twitter style url. Currently the model name is still showing in the url. Something like this http://0.0.0.0:3000/mikey without the model name
Get the name of the database column storing your users’ names (let’s say it’s ‘name’).
In config/routes.rb add, somewhere above the default route:
match 'users/:name', :controller => 'users', :action => 'show'
Now, in users_controller, find def show and change it to:
#user = User.find_by_name(params[:name])
Lastly, all the id-based urls pointing to your users need to be updated to reflect the name-based change. Like the one your Users index.html.erb file.
link_to #user.name, 'users/#{#user.name}'
Add a route, near the bottom of your routes file (right above your root route!)
get '/:id', :to => "users#show", :as => :friendly_user
This will act as a fall-through route, so /anything that wasn't caught by an earlier route will route to users#show and pass an :id accordingly. You can then use friendly_user_path(#user) to generate links to that user's Twitter-style profile.
Be sure that this is one of the lowest-priority routes, as you wouldn't want a user to be able to sign up with a username like "logout" and replace your /logout page with their profile!
I'm currently defining routes for my pages in the following manner:
get "home/index"
get "photo/index"
get "project/index"
get "home/about"
root :to => 'home#index'
However, I can only seem to be able to create a link to the photo/project index pages by using:
link
link
In the URL, the "index" part also shows up. I can't simple use /photo in the a link, because rails throws a routing error:
No route matches [GET] "/photo"
How would I create a route match for this?
match "/photo", to: "controller#action"
http://guides.rubyonrails.org/routing.html#connecting-urls-to-code
The best answer is to use match. Don't forget to include via to preserve your restriction on the http method:
match "/photo", to: "controller#action", :via => 'get'
I'm trying to do the following in rspec (know that I shouldn't have hardcoded value) in an integration test:
get '/api/get-other-items?id=5109'
The closest I could find was: call a specific url with rspec but it selects only a single item. I have tried the following:
get :controller => 'api', :action => 'get-other-items', :id => '5109'
get 'api/get-other-items', :id => '5109'
These are giving me a bad argument(expected URI object or URI string)
If I run as
get get_other_items, :id => '5109' q
I get
undefined local variable or method `get_other_items' for #<RSpec::Core::ExampleGroup::Nested_1:0x007f938fd65590>
but the route does exist:
Mon Jan 23$ rake routes | grep get_other_items
get_other_items /api/get-other-items(.:format) {:controller=>"api", :action=>"get_other_items"}
How would I perform this simple get?
thx
update for answer 1 comment
here's the rspec code in question:
it "testing getting other items for menu item" do
get get_other_items_path(:id => '5109')
JSON.parse(response.body)
puts response.body
Mon Jan 23$ rspec requests/get_other_items_spec.rb
F
Failures:
1) GetOtherItems testing getting other items for menu item
Failure/Error: JSON.parse(response.body)
JSON::ParserError:
743: unexpected token at 'this is not found '
# ./requests/get_other_items_spec.rb:19:in `block (2 levels) in <top (required)>'
Finished in 13.57 seconds
1 example, 1 failure
Failed examples:
The call should be get get_other_items_path(:id => 5109) - you need to add path to the name of the route, or url if you want the full URL instead of a relative path.
Your route doesn't look like it's taking a :id as a parameter, if you want to send an :id I would expect to see the following:
get_other_items /api/get-other-items/:id(.:format) {:controller=>"api", :action=>"get_other_items"}
Given the structure of your generated route I assume that you are using match to define the route (There is no HTTP verb in your route). To fix it try:
match 'api/get-other-items/:id' => 'api#get_other_items'
If instead you are using restful routes then it looks like you have specified a collection route rather than a member route. A collection route doesn't take an :id and is designed to return many records of the type you have specified. To make it a member route use the following:
resources :api do
get 'get_other_items', :on => :member
end
Once you get this working you should be able to try the following in rspec in your ApiController spec:
get :get_other_items, :id => '5109'
If neither of these options work please post your routes entry so we can try something else.
What I have
match "/home/markread/:id" => "books#markread"
goes to
def markread
#mark params[:id] as read
end
What I want
What If I want to pass another parameter so that urls looks like
/home/markread/1/didread=read or /home/markread/1/didread=unread
so my method will change to
def marked
#mark params[:id] as params[:didread]
end
Question
what should my routes.rb look like for me to achieve this?
How about just changing to
match "home/markread/:id/used=:used" => "books#markread"
Give the route a name using the 'as' option and pass the optional parameters as many you want.
For example:
match "/home/markread/:id" => "books#markread", :as => 'markread'
This will give you helpers like, markread_path and markread_url. You can pass the parameters like markread_path(:id => 1, :other => 'value' ...)
You need to do the checks in the controller for that action whether a particular parameter is passed or not. Rails Doc.
In rails 4 you will have:
resources :home, only: :none do
get 'markread/:another', action: :markread, on: :member
end
GET /home/:id/markread/:another(.:format) /home#markread
I have a pages controller with two records in the db; 'pages' and 'contact'.
The id for each page record is the title.
How do I write a specific route for each page?
I currently have a catch-all route which works...
match '/:id' => 'pages#show'
but I want to create a single route for each page
I probably don't understand your question because I have no idea why you would want to do that ;)
Anyhow, say you have a page what the title/id "about". This is what your route could look like:
match '/about' => 'pages#show', :defaults => { :id => 'about' }
cf. http://guides.rubyonrails.org/routing.html#defining-defaults
Note: I wouldn't call the route you're using already a "catchall"; it's a pretty normal Rails route. This is what I would call a catchall:
match ':controller(/:action(/:id))'