Maintaining Similar URL for Multiple Methods Ruby - ruby-on-rails

I have a 3 controllers with the method show namely
class CarController < ApplicationController
def show
end
end
class MotorcycleController < ApplicationController
def show
end
end
class TravelController < ApplicationController
def show
end
end
In my routes, i want the show method of all tree to follow the same url structure /:company_id/:id
So given an example that my home page url is https://localhost:3000, company id is 1 and id is 2, if i go to the show method of car controller, my url should be http://localhost:3000/1/2
At the moment, i did this in my routes
get '/:company_id/:id' => 'travel_controller#show', as: 'travel_insurance_product'
get '/:company_id/:id' => 'car_controller#show', as: 'car_insurance_product'
get '/:company_id/:id' => 'motorcycle_controller#show', as: 'motorcycle_insurance_product'
But when i trigger the car show method, it goes to the travel controller method
Is this possible to be done in ruby?

No, it's not possible. How is the router supposed to know if the id is for a Car, Motorcycle, or Travel?
BTW, the convention is for the controller to be in the plural form (such as MotorcyclesController).
Also BTW, routing is a Rails phenomenon, not a Ruby phenomenon.

Related

Using Rails helpers in model

In my model I have a method that marks a record as pending by changing its status to 2. After which it calls another method in another controller to create a notification containing details of the record that was changed.
e.g.
class Page < ActiveRecord::Base
def pend_page
self.update(status: 2)
Notification.create_notification("#{link_to self.title, pages_path(:status => 2)} marked as pending", #current_user)
end
end
However it seems Rails doesn't pass helpers for link_to and the routes to the models... as I get the error: undefined method 'pages_path' for #<Page:0x007fd15c996c88>.
How can I make it so that the link_to and pages_path work?
I'm using Rails 4.2.5.1
edit: here is what create_notification looks like:
class Notification < ActiveRecord::Base
belongs_to :user
def self.create_notification(content, user)
notification = Notification.new
notification.content = content
notification.user_id = user.id
notification.status = 0
notification.save
end
end
This should go in either a service object or in a PORO (plain old ruby object). A model's concerns should begin and end with database related functionality, anything else is in the wrong place.

In Rails, how can I tell, from within a model, whether the request came via a namespaced API controller or regular controller?

I have a Rails app with a namespaced API and regular controllers that match.
Both sets of controllers of course use the same models. E.g., API::CouponController and CouponController both use the Coupon model.
We are building features into the web side of things first and need to have some conditional logic in the model to tell whether the request is coming from the API or from the regular controller, so we can bifurcate the model logic. How can I do this?
Or is there a way to use a different model for each pair of controllers, but point to the same table?
Try This, I have listed a example it may be helpful
app/controllers/api/coupon_controller.rb
class Api::CouponController < Api::ApiController
def index
Coupon.test_method(params)
end
end
app/controllers/coupon_controller.rb
class CouponController < ApplicationController
def index
Coupon.test_method(params)
end
end
app/models/coupon.rb
class Coupon
def self.test_method(params)
return "You can check your controller and action using params"
end
end
Check The controller and action in test_method
params[:controller]
params[:action]

Rails 4 execute associated model method from controller

Let say we have a code:
Model:
class Dog < ActiveRecord::Base
def self.make_noise
puts 'bow-wow'
end
end
Controller:
class DogsController < ApplicationController
def index
Dog.make_noise
end
end
This will work, but I would rather like to write the controller index method code like: AssociatedModel.make_noise or Model.make_noise
Is it possible in Rails to call associated model method without using its class name in code?
This would be useful if I would like to use inheritance and make let say PetsController which will be the base for all pets (or a PetNoise Concern included for every applicable controller) and declare there index method.
I'm not sure if I explained this well enough.
OK. The one way (which i don't like) is to write PetsController method like this:
def index
params[:controller].classify.constantize.make_noise
end
This way if I inherit PetsController from DogsController it will still work without defining separate index inside DogsController. But maybe there are other more neat solutions.
As I also explained in this answer, you can determine the model using params[:controller]. Like this:
params[:controller] # => "dogs"
params[:controller].classify # => "Dog"
Therefore you can write your index action "generically" like this:
def index
model_class = params[:controller].classify.constantize
model_class.make_noise
end

Custom url_for for non rolling ids

Right now if I create a URL for a model show action I simply call:
link_to model_instance
which creates something like this the when model is User and the id is 1:
/user/1
I like to customize that behavior without having to go through all instances in the codebase where a URL for such a model is generated. The motivation behind the change is avoiding rolling id's in the URL that lets anybody discover other entries by simply increasing the id. So something like
/user/88x11bc1200
Is there a place where I can simply override how a URL for selected models are generated? I am using RoR 4.x
There are essentially two places you'll have to update.
In the model
class User < ActiveRecord::Base
# Override the to_param method
def to_param
# Whatever your field is called
non_rolling_id
end
end
In the controller
class UsersController < ApplicationController
def show
# Can't use `find` anymore, but will still come over as `id`
#user = User.find_by_non_rolling_id(params[:id])
end
end

Rails 3 - how to set up the routes for example.com/whatever-i-need

I have a little database with a movies that I saw. Now when I want to display a detail of a movie, so the profile of wanted movie is on the address example.com/movies/21.
But I would like to have a profile page of every movie on the nicer URL address, for example example.com/lords-of-the-rings.
How can I do it?
In your model, store the url name into a new field, like Movie.permalink
In config/routes.rb :
MyApp::Application.routes.draw do
match "movies/:permalink" => "movies#show"
end
And in your controller :
class MoviesController < ApplicationController
def show
#movie = Movie.find_by_permalink( params[:permalink] )
end
end
For more on routes in rails : http://guides.rubyonrails.org/routing.html
Consider using the slugged gem: https://github.com/Sutto/slugged
Many folks like this approach.
It's rails 3+
Just to help guide the answers, would you allow something like:
http://example.com/movies/lord-of-the-rings
If so, grabbing the params[:id] from that URL is easy.
You can automate the generation of that last :id by changing to_param of the model:
class User < ActiveRecord::Base
def to_param # overridden
name
end
end
Then you could change the show method of the controller to reflect the new :id format.
user = User.find_by_name(params[:id])

Resources