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
Related
I have a User model which can have many child accounts. I have set up the model as below
class User < ApplicationRecord
has_many :child_accounts, class_name: "User", foreign_key: "parent_account_id"
belongs_to :parent_account, class_name: "User", optional: true
end
I have created a ChildAccountsController to handle the child accounts creation etc. and defined routes as below.
resources :users do
resource :child_accounts
end
But I can get form_with to work in this situation. as
form_with(model: [current_user, #child_account], local: true) do
#...
end
form_with infers the url from the model class since both of them are User. the path it infers user_user_path instead of user_child_accounts_path.
So, is there a rails way to create forms with self joins? Or do I have manually handle this case?
To start with you have a pluralization error:
resources :users do
resources :child_accounts
end
resource is used to declare singular resources.
But the polymorphic route helpers will not be able route to that path automatically anyways, when you pass model instances to form_for, form_with, link_to and button_to they deduce the name of route helper method by calling #model_name and using the methods of ActiveModel::Naming. Since #child_account is an instance of User you get user_users_path. The polymorphic routing helpers are not aware of your associations.
It does not matter at all here if you use form_for or form_with as both use the exact same methods to figure out a path from a model or array of models.
You either need to explicitly pass the url:
form_with(model: #child_account, url: user_child_accounts_path(current_user), local: true) do
#...
end
Or use single table inheritance:
class AddTypeToUsers < ActiveRecord::Migration[6.0]
def change
change_table :users do |t|
t.string :type
end
end
end
class User < ApplicationRecord
has_many :child_accounts,
foreign_key: "parent_account_id",
inverse_of: :parent_account
end
class ChildAccount < User
belongs_to :parent_account,
class_name: "User",
inverse_of: :child_accounts
end
class ChildAccountsController < ApplicationController
def new
#child_account = current_user.child_accounts.new
end
def create
#child_account = current_user.child_accounts.new(child_account_params)
# ...
end
private
def child_account_params
params.require(:child_account)
.permit(:foo, :bar, :baz)
end
end
I have a not so traditional code and i'm struggling to generate the correct path for a resource.
In my routes.rb
namespace :admin do
resources :matches do
resources :lineups do
resources :substitutions
end
end
end
My models are:
Match.rb
class Match < ApplicationRecord
has_one :home_lineup
has_one :away_lineup
end
On home_lineup.rb for the STI structure
class HomeLineup < Lineup
end
On away_lineup.rb for the STI structure
class AwayLineup < Lineup
end
lineup.rb
class Lineup < ApplicationRecord
belongs_to :match
#has a :type column as :string
end
and, substitution.rb
class Substitution < ApplicationRecord
belongs_to :lineup
end
When I try to:
m = Match.last
l = m.home_lineup
s = Substitution.new
app.polymorphic_url([:admin, m, l, s])
I get:
NoMethodError (undefined method `admin_match_away_lineup_substitutions_url' for #<ActionDispatch::Integration::Session:0x000055f4327a60d0>)
Did you mean? admin_match_lineup_substitutions_url
admin_match_lineup_substitution_url
admin_match_lineup_substitution_path
admin_match_lineup_substitutions_path
But what I really wanted is "admin_match_lineup_...".
What should I do to fix this problem?
I found a solution for my problem in this blog post (http://leomayleomay.github.io/blog/2014/03/24/customize-the-polymorphic-url-for-sti/).
To force Lineup to respond the correct name add this code on it`s file:
lineup.rb
def self.model_name
ActiveModel::Name.new(self, nil, "Lineup")
end
Thanks and happy coding.
I am working on a Rails 4 application and recently got into a strange issue. I am looking for your help here. Kindly advise.
A small gist snippet has been created to understand the issue undefined method committed?
Just to summarize everything:
# app/models
class User < ActiveRecord::Base
has_many :responses, dependent: :destroy
end
class Response < ActiveRecord::Base
has_one :report
has_many :points
belongs_to :user
end
class Report < ActiveRecord::Base
belongs_to :response
end
class Point < ActiveRecord::Base
belongs_to :response
end
# config/routes.rb
resources :users do
resources :responses do
resources :action_plans
end
end
# app/controllers/action_plans_controller.rb
class ActionPlansController < ApplicationController
before_filter :response
def new
#report = #response.build_report
5.times do
#response.points.build
end
end
private
def response
#response = current_user.responses.find(params[:id])
end
end
Whenever, I am trying to hit:
http://localhost:3000/users/:user_id/responses/:id/action_plans/new
I get error that says: undefined method `committed?' for Response Object. What I am doing wrong here?
By defining a method called response in your controller you're overriding an internal getter used by Rails. To solve the problem, just use a different name for your before action. The common way of naming the action is to use set_<entity name> so set_response it is.
There is a Response class namespaced inside ActionDispatch (ActionDispatch::Response) and it is used throughout Rails. Can it be the case that you're actually hitting the response object instead of your model? Maybe use pry-rails to debug it from inside?
I have an application in which a club has_many locations. Clubs & their locations can only be edited within an admin namespace.
I am trying to pre-load the club into the controller so that all actions deal with that club only.
The routes are nested; however, in the locations controller, it does not find the Club model. What am I doing wrong?
routes.rb
namespace :admin do
resources :clubs do
resources :locations
end
end
club.rb
class Club < ActiveRecord::Base
belongs_to :membership
has_many :users
has_many :locations
#accepts_nested_attributes_for :locations
end
admin/locations_controller.rb
class Admin::LocationsController < ApplicationController
before_filter :load_club
protected
def load_club
#club = Club.find(params[:club_id])
end
end
Also, lastly: What is wrong with my routes that it is not looking for the locations controller in admin/clubs/locations? I'm not sure if that is part of the problem.
from rake routes
admin_club_locations POST /admin/clubs/:club_id/locations(.:format) admin/locations#create
new_admin_club_location GET /admin/clubs/:club_id/locations/new(.:format) admin/locations#new
edit_admin_club_location GET /admin/clubs/:club_id/locations/:id/edit(.:format) admin/locations#edit
admin_club_location PUT /admin/clubs/:club_id/locations/:id(.:format) admin/locations#update
DELETE /admin/clubs/:club_id/locations/:id(.:format) admin/locations#destroy
It probably looks up the Club model within the current Admin namespace. You could try:
def load_club
#club = ::Club.find(params[:club_id])
end
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.