rails- Pass infomation to a controller based on url - ruby-on-rails

I have a controller for "Productions" and if you go to localhost/productions you see an index page, you can click show and view the show page for that particular productions.
Each production has a unique ID like 036ea872f9011a7c, I want my users to be able to add items to a production like follows:
localhost/productions/036ea872f9011a7c/fixtures/add
localhost/productions/036ea872f9011a7c/positions/add
localhost/productions/036ea872f9011a7c/dimmers/add
localhost/productions/036ea872f9011a7c/channels/add
localhost/productions/036ea872f9011a7c/etc/add

You should build a route with the necessary parameters like this:
Suppose we have tasks that we assign to a project
model project.rb:
class Project < ActiveRecord::Base
has_many :tasks, through: :project_task
end
model task.rb
class Task < ActiveRecord::Base
has_many :projects, through: :project_task
end
routes.rb
...
resources :projects do
member do
get 'affect_task/:task_id', action: 'affect_task', as: :affect_task
end
end
projects/show.haml
= link_to "task_name", affect_task_project_path(task_id: #task_id, project_id: #project_id)
controller.rb
...
def affect_task
...
CollaboratorTask.create(task_id: params[:task_id], project_id: params[:project_id])
...
end
...
Of course this is an example so you understand..

Related

retrieving the :id of a given show view

I want to add an RSVP button to an Event view. For the RSVP controller, how do I retrieve the id of the Event that the view of which the user has opened, with a check that it is indeed an Event view? Should I create a private method like current_event in the application controller?
class RsvpsController < ApplicationController
def create
#rsvp = Rsvp.new(rsvp_params)
##rsvp.event_id = ???
end
end
UPDATE with additional info
my models looks like this
class Rsvp < ApplicationRecord
belongs_to :event
belongs_to :user
end
class Event < ApplicationRecord
has_many :rsvps
has_many :users, through: :rsvps
end
class User < ApplicationRecord
has_many :rsvps
has_many :events, through: :rsvps
end
You really haven't provided enough information about your application. How does an event relate to a RSVP. I'm going to make a few assumptions, but think that it will help you overall. Let's say your application will have many Events. An Event has many RSVP and a RSVP belongs to an event.
Typically, you will have something like this within your routes
Rails.application.routes.draw do
resources :events do
resources :rsvps
end
end
If you run rake routes, you may see something like this
Prefix Verb URI Pattern Controller#Action
event_rsvps GET /events/:event_id/rsvps(.:format) rsvps#index
POST /events/:event_id/rsvps(.:format) rsvps#create
new_event_rsvp GET /events/:event_id/rsvps/new(.:format) rsvps#new
edit_event_rsvp GET /events/:event_id/rsvps/:id/edit(.:format) rsvps#edit
event_rsvp GET /events/:event_id/rsvps/:id(.:format) rsvps#show
PATCH /events/:event_id/rsvps/:id(.:format) rsvps#update
PUT /events/:event_id/rsvps/:id(.:format) rsvps#update
DELETE /events/:event_id/rsvps/:id(.:format) rsvps#destroy
So your button should point to the rsvps#new controller and action. Once your user submits the form, it will call the rsvps controller and the create action.
From here, you can access your event with something like #event = Event.find(params[:event_id])
Since an event has_many :rsvps and a rsvp belongs_to :event, you can create your rsvp with something like
def create
#event = Event.find(params[:event_id])
#rsvp = #event.rsvps.create(rsvp_params) # strong params
if #rsvp.save
...
else
...
end
end
Bonus tip: Within your RSVP's form, you will need to change it to something like this since we have nested RSVP under Events.
<%= form_for [#event, #rsvp] do |f| %>
...
<% end %>

View/Controller Balance - Rails

I have a query that adds a Customer to a certain Category. It is currently in the view template, and while it works, there's a bug - the customer is added to the category upon loading the page, before they have clicked the button.
I thought that moving that logic back to the controller might solve it (using form_for), then rendering the submit button in the view.
What do you think? And how would one implement it using form_for?
= link_to "JOIN CATEGORY NOW", root_path(#product.category.add_customer(current_customer)), class: "button4"
Edit:
Category Model
class Category < ActiveRecord::Base
#Associations
belongs_to :product
has_many :customer_categories
has_many :customers, through: :customer_categories
def add_customer(customer_id)
if customer = Customer.where(id: customer_id).first
self.customers << customer unless self.customers.include?(customer)
end
end
end
Product Model
class Product < ActiveRecord::Base
include ActionView::Helpers
#Callbacks
after_create do
Category.create product: self
end
#Associations
has_one :category, dependent: :destroy
Customer Model
class Customer < ActiveRecord::Base
#Associations
has_many :customer_categories
has_many :categories, through: :customer_categories
EDIT #2:
ActionView::Template::Error (undefined method `add_customer_category' for #<#<Class:0x007fcaebdbb5b0>:0x007fcae377ab90>):
routes:
resources :categories do
member do
get 'add_customer', to: 'categories/add_customer'
end
end
Categories Controller:
def add_customer
#product = Product.find(params[:id])
#product.category.add_customer(current_customer.id)
end
The customer is added to the category upon loading the page is happening because of this line:
= link_to "JOIN CATEGORY NOW", root_path(#product.category.add_customer(current_customer)), class: "button4"
Or more specifically this part of the code:
#product.category.add_customer(current_customer)
Since, when you load the page the Ruby code in view gets evaluated and hence the above code gets executed and customer gets added to the category.
Solution:
In your routes.rb:
resources :categories do
member do
get 'add_customer'
end
end
Now, in your view:
= link_to "JOIN CATEGORY NOW", add_customer_category_path(#product.category)
In your CategoriesController:
def add_customer
#category = Category.find(params[:id])
if #category.add_customer(current_customer)
redirect_to root_path
else
# Redirect user to an error page, maybe?
end
end

Rails Polymorphic associations without nesting forms

I am still new to rails and I am trying to figure out how to implement a polymorphic association without using a nested route or form. I tried searching but everything seemed to be about nesting forms or adding comments, which is not what I am trying to do.
Here are my models
Article.rb
class Article < ActiveRecord::Base
belongs_to :articable, polymorphic: true
end
Organization.rb
class Organization < ActiveRecord::Base
has_many :articles, as: :articable
end
People.rb
class People < ActiveRecord::Base
has_many :articles, as: :articable
end
I want to implement a 'New Article' link from a Organization or People show page and have the correct article_id and article_type entered. What would the correct syntax be to generate this link?
Thanks!
Routes:
resource :people do
resource :articles
end
resource :organizations do
resource :articles
end
ArticlesController:
def create
article = Article.new(params[:article])
if params[:people_id]
people = People.find(params[:people_id])
people.articles << article
else
organization = Organization.find(params[:organization_id])
organization.articles << article
end
article.save
end
Organizations view:
link_to new_organization_article_path(#organization)...

Rails 3 namespaced model and controller routing issue

I have namespaced model Equipment::Feature and namespaced controller in my admin part Admin::Equipment::FeaturesController. Model is generic and is used as from within :admin namespace and for public website. I've set up the routing for :admin and :equipment namespaces
namespace :admin do
namespace :equipment do
resources :features
end
end
Which gives me following routes:
admin_equipment_features GET /admin/equipment/features(.:format) admin/equipment/features#index
POST /admin/equipment/features(.:format) admin/equipment/features#create
new_admin_equipment_feature GET /admin/equipment/features/new(.:format) admin/equipment/features#new
edit_admin_equipment_feature GET /admin/equipment/features/:id/edit(.:format) admin/equipment/features#edit
admin_equipment_feature GET /admin/equipment/features/:id(.:format) admin/equipment/features#show
PUT /admin/equipment/features/:id(.:format) admin/equipment/features#update
DELETE /admin/equipment/features/:id(.:format) admin/equipment/features#destroy
Pretty standard stuff. But when I address /admin/equipment/features it throws uninitialized constant Admin::Equipment::FeaturesController::Equipment exception
#index action in my Admin::Equipment::FeaturesController looks like
def index
#features = Equipment::Feature.all
end
It did seem to work, until I declared Admin::Equipment namespace. Before it was like Admin::EquipmentFeaturesController
I guess this is some sort of namespace collision, but I don't get it - where does it come from?
Thanks in advance!
UPDATE Feature model (uses STI pattern)
class Equipment::Feature < ActiveRecord::Base
attr_accessible :category_id, :name_en, :name_ru, :type
belongs_to :category, :class_name => 'Equipment::Category'
has_many :item_features, :class_name => 'Equipment::ItemFeature'
has_many :items, :through => :item_features
translates :name
end
class FeatureBoolean < Equipment::Feature
end
class FeatureNumeric < Equipment::Feature
end
class FeatureString < Equipment::Feature
end
class FeatureRange < Equipment::Feature
end
UPDATE2
Fixing #index action as per answer below resolved the issue. New code:
def index
#features = ::Equipment::Feature.all
end
I think it's now looking for Feature in Admin::Equipment, rather than in ::Equipment
Try specifying that there is no namespace, i.e.
def index
#features = ::Equipment::Feature.all
end
Please create folder like this app/controllers/admin/equipment/features.rb
And then edit your controller name to Admin::Equipment::FeaturesController
class Admin::Equipment::FeaturesController < ActiveRecord::Base
end

Rails 3 Routing Error (Namespaced routes help)

Model relationships:
class Project < ActiveRecord::Base
...
has_one :project_team
...
end
class ProjectTeam < ActiveRecord::Base
belongs_to :project
end
Controller:
class Project::TeamController < ApplicationController
...
end
Routes:
resources :projects do
namespace :project do
resources :team
end
end
Form code:
= form_for #project do |f|
When I visit the new Project form, I get the following error:
No route matches {:controller=>"project/team", :project_id=>#<Project id: nil, user_id: 1 ...
I've tried many variations of this:
= form_for [:project, :team, #project] do |f|
To no avail. The routes are just barely off. But, I'm on the new project form, so I'm wondering why it's trying to grab the project team for that anyway.
Thanks for the help! [:
We should use the nested resources here,
resources :projects do
resource :project_team
end
I'm not sure of the issue, but to fix it, I just pluralized my controller name.

Resources