Rails - How to add a route to some resources - ruby-on-rails

Some routes are for CRUD operations, such as client, phone_numbers and products. I have 'unique-index' attributes for many of the models. For example, in Client, I could have "email" or "username", whereas in Products I could have "serialnumber", and in PhoneNumber the actual "number" could be unique-index.
So, I have methods in my ApplicationController that receives a JSON in a POST request, with the attribute name and attribute value. The server checks if the value exists and informs the user if the input is valid or if value exists.
So, for these models, I have to declare a route that points to the "unique" method, such as below
routes.rb
resources :clients
resources :phone_numbers
resources :products
post 'clients/unique' => 'clients#unique'
post 'phone_numbers/unique' => 'phone_numbers#unique'
post 'products/unique' => 'products#unique'
My question is: Can I "group" these routes, without prefix (unlike namespace and scope) to just add post 'unique' to them? a pseudo-code would be like this
pseudo-code
group alias: 'modelsWithUniqueAttrs'
resources :clients
resources :phone_numbers
resources :products
add_route 'unique'
end

Try this
resources :clients, :phone_numbers, :products do
collection do
post :unique
end
end
Or
unique_routing = Proc.new do
collection do
post :unique
end
end
resources :clients, &unique_routing
resources :phone_numbers, &unique_routing
resources :products, &unique_routing
Or
unique_routing = Proc.new do
collection do
post :unique
end
end
resources :clients, :phone_numbers, :products, &unique_routing

You can define your routes like this:
resources :clients do
member do
post :unique => 'clients#unique'
end
end
resources :phone_numbers do
member do
post :unique => 'phone_numbers#unique'
end
end
resources :products do
member do
post :unique => 'products#unique'
end
end
These will give you routes like:
unique_client POST /clients/:id/unique(.:format) clients#unique
unique_phone_numbers POST /phone_numbers/:id/unique(.:format) phone_numbers#unique
unique_products POST /products/:id/unique(.:format) products#unique
Update
You can define routes using collection block like this:
resources :clients, only: [:uniq] do
collection do
post :uniq
end
end
which you give you routes like:
uniq_clients POST /clients/uniq(.:format) clients#uniq
But, this is still not what you want exactly. Because, you have to have the similar collection blocks for products and phone_numbers as well.

Related

How to save a Boolean entry in a has_many through join Table

I need to define a method/action in my LessonsController that I can call from the lesson show action that marks the lesson as being completed by the current user. What does that controller method look like?
Here's the overview of my models:
User
has_many :completions
has_many :completed_steps, through: :completions, source: :lesson
Lesson
has_many :completions
has_many :completed_by, through: :completions, source: :user
Completions
belongs_to :user
belongs_to :lesson
My Completions Table looks like this:
t.integer "user_id"
t.integer "lesson_id"
t.boolean "completed_step"
t.string "completed_by"
I'm assuming in the LessonsController it looks like this
def complete_step
self.completions.create(completed_step: true, user_id: current_user.id)
end
Routes info:
Rails.application.routes.draw do
namespace :admin do
resources :users
resources :coupons
resources :lessons
resources :plans
resources :roles
resources :subscriptions
resources :completions
root to: "users#index"
end
devise_for :users, :controllers => { :registrations => "registrations"}
# Added by Koudoku.
mount Koudoku::Engine, at: 'koudoku'
scope module: 'koudoku' do
get 'pricing' => 'subscriptions#index', as: 'pricing'
end
resources :lessons do
member :complete
end
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root 'pages#home'
get '/dashboard' => 'pages#dashboard', :as => 'dashboard'
mount StripeEvent::Engine, at: '/stripe-events' # prov
end
Here's my button link to make this functional.
<%= button_to "Mark this Lesson as Complete", complete_lesson_path(#lesson), method: :put, class: "btn btn-warning btn-lg" %>
Will this work or am I WAY off? Thanks!
Keep this is the LessonsController, but change it in either of the following ways:
def complete_step
current_user.completions.create(completed_step: true, lesson_id: #lesson.id)
end
# ~~ OR ~~
def complete_step
#lesson.completions.create(completed_step: true, user_id: current_user.id)
end
Both of these assume that you've already set #lesson in the controller, probably in a before_action :set_lesson.
EDIT:
If you need a route suggestion, then assuming you have resources :lessons in your routes file, you can either use an existing route (likely update) or add a member route like this:
resources :lessons do
get 'complete', on: :member
end
If you add a route, then you will need to add an action that looks like
def complete
complete_step
redirect #lesson
end
or similar, however you want to handle the response itself. You will also need to ensure that #lesson is set, so you should tweak your before_action :set_lesson, only: [:show, :update, ...] to also include :complete
Please try with below code.in your completion controller
def create
#lession = Lession.find(params[:lession_id])
#completion = current_user.completions.create(completed_step: true, lesson_id: #lesson.id)
redirected_to #completion
end
You can also just pass user: current_user to the completions.create method instead of passing in the current_user.id
Something like #lesson.completions.create(completed_step: true, user: current_user)

Rails 4 shallow routes menu parameters undefined error

I have shallow routes like below:
resources :venues, shallow: true do
#Halls
get "hall/:id/exhibition" => "halls#exhibition", as: :exhibition
get "hall/:id/visit" => "halls#visit", as: :hall_visit
get "structure", :to => "venues#venue_structure"
resources :asset_types, :booths_tags, :tags, :uploaded_files, :events, :chats
resources :halls do
resources :webcasts
resources :booths do
resources :chats
end
end
end
Problem with this is with below helper where I need to provide #booth resource as a parameter:
hall_booths_path(#booth.hall)
But this is not always possible especially when it gets to index action as it does not set #booth resource.
Is there a good approach to tackle this problem?
Even if you're in booths#index action, you have your hall id, so you could set #hall instance variable:
#hall = Hall.find(params[:hall_id])
and then, you just can do following:
hall_booths_path(#hall)

Rails 3 create a route to nested independent page

I have 3 levels of nesting.
routes.rb looks like this
resources :clients do
resources :departments do
resources :tasks
end
end
I would like to create a custom path that looks like this
/clients/:client_id/departments/:department_id/tasks/data
I have tried adding the following
resources :clients do
resources :departments do
resources :tasks
member do
get "data"
end
end
end
This creates the route
/clients/:client_id/departments/:department_id/tasks/:task_id/data
How would I remove the :task_id part the path?
A member route acts on a member, that's why it requires an id. A collection acts on a collection and so doesn't require an id.
resources :clients do
resources :departments do
resources :tasks do
collection do
get "data"
end
end
end
end
You should use
resources :clients do
resources :departments do
resources :tasks
get "data", :on => :collection
end
end

Creating a specific custom route in rails 3

I have several levels of nested routing.
resources :departments do
resources :tasks do
collection do
get "report" => "tasks#report"
end
end
This a piece of it.
What I am attempting to do is create a custom route for a report.html.erb file. However, this route creates the path /department/:id/tasks/report
I would like to create the path /department/:id/tasks/:id/report
Is this possible? I considered creating a new controller and model for report but this seems to be inefficient.
try with:
resources :departments do
resources :tasks do
member do
get "report" => "tasks#report"
end
end
end
or just:
resources :departments do
resources :tasks do
get "report" => "tasks#report", :on => :member
end
end

Adding a Route to the base URL of plural Resources

In Ruby on Rails, is there a way to add another RESTful action to the base URL of a plural resource? I'm looking for something like this:
resources :groups do
resources :users do
put on: :base, to: 'users#update_all'
end
end
Which would generate the route: [PUT] groups/:group_id/users => users#update_all
I've already tried doing this:
resources :groups do
resources :users
put 'users', on: :member, to: 'users#update_all'
end
But that doesn't preserve the value of params[:group_id] in the controller.
resources :users do
collection do
put '' => 'users#update_all' ## PUT /users
end
end
UPDATE
It would be recommended to do this though:
resources :users do
collection do
put 'update_all' ## PUT /users/update_all
end
end
Both route to the update_all action of the users controller.
RESOURCES
http://guides.rubyonrails.org/routing.html#adding-more-restful-actions

Resources