Any help and advise would be much appreciated.
i have a company model that has many recruiters (users) &
a recruiter (user) belonging to a company
also recruiters belong to a gender & gender has many recruiters
using the GEM ransack, i am trying to display all male recruiters(users) in a
company but i am unsure of the code needed for the 'recruiters' action in the companies controller - anyway help & advise would be much appreciated. Below are my files:
Models:
user.rb
class User < ActiveRecord::Base
belongs_to :company
belongs_to :category_gender
end
company.rb
class Company < ActiveRecord::Base
has_many :users
end
category_gender
class CategoryGender < ActiveRecord::Base
has_many :users
end
Companies_controller.rb
class CompaniesController < ApplicationController
respond_to :html, :xml, :json
before_action :set_company, only: [:show, :edit, :update, :destroy]
# load_and_authorize_resource
........
def recruiters
#search = Company.search(params[:q])
#companies = #search.result.includes(:users)
#user = current_user
#company = #user.company
end
end
routes.rb
Rails.application.routes.draw do
resources :companies do
resources :comments, only: [:create, :destroy]
member do
get 'recruiters'
end
end
devise_for :users
resources :users do
resources :comments, only: [:create, :destroy]
resources :adverts
resources :blogs
member do
get 'applications'
get 'applicants'
get 'settings'
get 'dashboard'
get 'management'
end
end
recruiters.html.erb (views file):
<%= search_form_for #search, url: recruiters_company_path do |f| %>
<div>
<h3>gender</i></h3>
<ul>
<% CategoryGender.all.each do |gender| %>
<li>
<%= check_box_tag('q[category_gender_name_eq_any][]', gender.name) %>
<%= gender.name %> (<%= gender.users.count %>)
</li>
<% end %>
</ul>
</div>
<button><%= f.submit 'search' %></button>
<% end %>
Since you are searching for Users. Then, .ransack method should be called on User model and not on Company model.
Try the following in your recruiters method:
def recruiters
#company = Company.find(params[:id])
#users = User.ransack(params[:q]).result.where(company: #company)
#user = current_user
end
1st line: I used #company = Company.find(params[:id]) instead of #company = #user.company because you are using resources pathing for Company, in which recruiter method is a "member" of (as you defined in your routes.rb).
The problem with #user.company is that say for example a user browses /companies/1/recruiters, the #company that will be assigned is going to be the same as when browsing /companies/3/recruiters. But by convention, #company in these two paths should already be different because of the id changing.
2nd line: I just added a the predicate .where(company: #company) so that the results will be filtered to the respective company.
Then in your recruiters.html.erb view file, you could just add something like the following:
...
...
<% #users.each do |user| %>
<%= user.name %>
<% end %>
...
...
Related
I've got a one to many relationship with one movie per list entry, where a movie can be used in a list entry. My list_entries table has a movie_id and a list_id.
database schema
I've nested list_entries in lists so I can pass the list_id directly when creating a new instance.
Rails.application.routes.draw do
devise_for :users
root to: 'pages#home'
resources :movies, only: [:new, :index, :create, :show, :destroy, :edit, :update]
resources :users, only: [:show, :edit, :update]
resources :lists, only: [:new, :create, :show, :index, :destroy] do
resources :list_entries
end
end
Right now I can create and destroy list entries but I have to specify the movie id manually.
The UX I want to achieve is for the user to be able to search for movies from themy list_entries/new form but I don't even know where to begin.
The form as it is now:
<%= simple_form_for #list_entry, url: list_list_entries_path do |f| %>
<%= f.input :comment %>
<%= f.input :movie_id %>
<%= f.submit "Add", class: "btn devise-button" %>
<% end %>
My list entries controller:
class ListEntriesController < ApplicationController
before_action :find_list, only: [:index, :create, :show, :new, :destroy]
def new
#list_entry = ListEntry.new
end
def index
#list_entries = ListEntry.where(list: #list)
end
def show
#list_entry = ListEntry.find(params[:id])
end
def destroy
#list_entry = ListEntry.find(params[:id])
#list_entry.destroy
redirect_to list_list_entries_path
end
def create
#list_entry = ListEntry.new(entry_params)
#list_entry.list_id = params[:list_id]
if #list_entry.save
redirect_to list_list_entries_path
else
render 'new'
end
end
private
def find_list
#list = List.find(params[:list_id])
end
def entry_params
params.require(:list_entry).permit(:comment, :movie_id)
end
end
If you don't want to manually specify a movie_id in the form, you can use the simple_form_for association helper:
<%= f.input :comment %>
<%= f.association :movie %>
I believe it should be labeled based off of the movie title, but if not, you may have to specify a #to_label method in your Movie model.
Alternatively, you could query for the movies in your #new action and use them to do whatever you like in your view:
def new
#list_entry = ListEntry.new
#movies = Movie.all # or whatever query you think is relevant
end
The #collection_select documentation might be useful here:
https://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/collection_select
Working with nested routes and associations. I have a partial which creates a tenant, but after the creation it stays with the form rendered and the url changes to /tenants. Desired behavior is that it needs to redirect_to the show page. Routes are as follows:
Rails.application.routes.draw do
devise_for :landlords
authenticated :landlord do
root "properties#index", as: "authenticated_root"
end
resources :tenants
resources :properties do
resources :units
end
root 'static#home'
end
So far the properties and units work (and the landlord) Issue is with Tenants. Originally I had Tenants nested under units, but had issues there as well. Partial looks like this:
<%= form_for #tenant do |f| %>
<%= f.label "Tenant Name:" %>
<%= f.text_field :name %>
<%= f.label "Move-in Date:" %>
<%= f.date_field :move_in_date %>
<%= f.label "Back Rent Amount:" %>
$<%= f.text_field :back_rent %>
<%= f.button :Submit %>
<% end %>
<%= link_to "Cancel", root_path %>
Tenants Controller looks like this:
before_action :authenticate_landlord!
#before_action :set_unit, only: [:new, :create]
before_action :set_tenant, except: [:new, :create]
def new
#tenant = Tenant.new
end
def create
#tenant = Tenant.new(tenant_params)
if #tenant.save
redirect_to(#tenant)
else
render 'new'
end
end
def show
end
def edit
end
def update
if #tenant.update(tenant_params)
redirect_to unit_tenant_path(#tenant)
else
render 'edit'
end
end
def destroy
end
private
def set_property
#property = Property.find(params[:property_id])
end
def set_unit
#unit = Unit.find(params[:unit_id])
end
def set_tenant
#tenant = Tenant.find(params[:id])
end
def tenant_params
params.require(:tenant).permit(:name, :move_in_date, :is_late, :back_rent, :unit_id)
end
end
Models have associations:
class Tenant < ApplicationRecord
belongs_to :unit, inverse_of: :tenants
end
class Unit < ApplicationRecord
belongs_to :property, inverse_of: :units
has_many :tenants, inverse_of: :unit
end
Lastly the show#tenants in rake routes is:
tenant GET /tenants/:id(.:format) tenants#show
I have extensively searched for this topic, but haven't had any success. Any help is appreciated. Rails 5.1
The route you are showing near the end of your question:
tenant GET /tenants/:id(.:format) tenants#show
is not the tenants index; it is the individual tenants/show route. You can tell this because it includes :id, which means it will show you a specific tenant having that id.
Try running rake routes again. The index route should look like this:
tenants GET /tenants(.:format) tenants#index
If you want to return to the tenants index after creating or updating a Tenant record, then you need to specify that path in your TenantsController. In both the #create and #update actions, your redirect line (after if #tenant.save and if #tenant.update, respectively) should read:
redirect_to tenants_path
That will take you to the TenantsController, #index action.
In the alternative, if you want to return to the individual tenant show page, then instead change both of those redirects in the TenantsController in both the #create and #update actions to:
redirect_to tenant_path(#tenant)
That will take you to the TenantsController, #show action for the current #tenant.
I'm making a simple website to learn RoR. It allows users to post reviews for movies, but I want to implement a link in my root view that shows ALL of the reviews in the database. How do I do that?
I want to be able to <%= link_to 'Reviews', reviews_path %> but my reviews#index URI pattern is /movies/:movie_id/reviews
What do I put in my reviews model in order to extract all the reviews in the database?
My reviews controller:
class ReviewsController < ApplicationController
def create
#movie = Movie.find(params[:movie_id])
#review = #movie.reviews.create(review_params)
redirect_to movies_path(#movie)
end
private
def review_params
params.require(:review).permit(:email, :comment)
end
end
Review model:
class Review < ApplicationRecord
belongs_to :movie
end
And my root view:
<h3>All Reviews:</h3>
<!-- put link here -->
<h3>Sort By:</h3>
<p>
<%= link_to 'Release', movies_path(:sort_param => "release") %>
<%= link_to 'Title', movies_path(:sort_param => "title") %>
</p>
<h1>Popular Movies</h1>
<% #movies.each do |m| %>
<h2>Title</h2>
<%= m.title %>
<%= m.release %>
<%= link_to 'Show', movie_path(m) %>
<% end %>
Edit: I looked at this solution but I'm not sure where to put that code. I tried to put it in the Review's index method but I got an error:
Couldn't find all Reviews with 'id': (all, {:order=>"created_at DESC", :limit=>10})
In your routes.rb
resources :reviews, only: [:index]
reviews_controller.rb
If you want to display all the reviews from any movie, in most recent order, you could do:
class ReviewsController < ApplicationController
def index
#reviews = Review.order('created_at DESC').limit(10)
end
def create
...
end
end
You can add a route to reviews only in your routes.rb file.
resources :reviews, only: [:index]
I have the following schema:
attribute
----------
id
name
profile
----------
user_id
attribute_id
value
user
----------
id
name
What I am trying to do is display all the attributes and then for any attribute that the user does have in the profile it fills it in and an update can be performed. My background isn't ruby but I'm testing this framework for a proof of concept before possibly migrating an app.
I have mapped the association like that on the guides on rubyonrails.org (the appointments example)
class Attribute < ActiveRecord::Base
has_many :profiles
has_many :users, through: :profiles
end
class Profile < ActiveRecord::Base
belongs_to :attribute
belongs_to :user
end
class User < ActiveRecord::Base
has_many :profiles
has_many :attributes, through: :profiles
accepts_nested_attributes_for :profiles
end
I took the approach of using nested forms but unable to pass the model through even though the accepts_nested_attributes_for has been set.
<%= form_for(#user) do |f| %>
<% Attribute.all.each do |attribute| %>
<div>
<%= attribute.name %>
</div>
<div>
<%= f.fields_for :profiles do |upp| %>
<%= upp.hidden_field :user_id, :value => #user.id %>
<%= upp.hidden_field :attribute_id, :value => #attribute.id %>
<%= upp.text_field :value %>
<% end %>
</div>
<% end %>
<div>
<%= f.submit %>
</div>
<% end %>
e.g
Attributes
A
B
C
User has attribute A
A ["hello world"]
B [ ]
C [ ]
Attributes are dynamic, so if 2 new attributes are added, D and E would be shown as well
A ["hello world"]
B [ ]
C [ ]
D [ ]
E [ ]
How can I setup this form correctly so that it can be passed through as a model for saving? I assume the json would be something like
profile_attributes { [user_id:1 attribute_id:1 value:'hello world'], [user_id:1 attribute_id:2 value:''] }
I know the above form setup is not quite right but that is just one of several attempts I tried to see what it renders.
I tried:
<%= f.fields_for #user.profiles do |pp| %>
<% end %>
I even tried manually setting the field as arrays (similiar to asp.net mvc):
id=user[profiles][user_id]
id=user[profiles][attribute_id]
Controllers (they're empty shells at the moment, I just wanted to see the json output in the console)
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
end
class ProfileController < ApplicationController
def edit
#user = User.find(params[:id])
end
def update
respond_to do |format|
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(profiles_attributes: [:user_id, :attribute_id, :value])
end
end
end
I've tried many different approaches but with no success. Sometimes the form shows duplicated fields with same values, sometimes the form is shown but value is blank and upon submission complains about unpermitted parameter yet it was set in the controller.
Of course all the above can be done using javascript but I wanted to see if it was possible just using the model approach and nesting it.
You can do like this :
move form to your users/edit.html.erb and modify your users_controller as below
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def edit
#user.profiles.build
end
def update
if #user.update(user_params)
#redirect user where you want
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
def user_params
#permit user attributes along with profile attributes
end
end
I'm currently developing an app which allows users to post from their own account, but if they're an administrator of a group or venue, they can also post as that entity. I'm struggling converting the polymorphic association ideas from some of the other questions out there as generally they're all based around being able to comment on multiple things and not from multiple things.
I think my main issue is that I have my user's post form on the homepage, so it does not have an ID in the URL.
My post controller looks like this:
class PostsController < ApplicationController
before_action :authenticate_user!, only: [:create, :destroy]
before_filter :load_postable
def index
end
def new
#post = Postabe.posts.new(post_params)
end
def create
#post = #postable.posts.build(post_params)
if #post.save
flash[:success] = "Post created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
def destroy
#post.destroy
redirect_to root_url
end
private
def post_params
params.require(:post).permit(:content)
end
def load_postable
resource, id = request.path.split('/')[1, 2]
resource_name = resource.singularize.classify
if resource_name == "User"
#postable = current_user
else
#postable = resource_name.constantize.find(id)
end
end
end
and my _post_form.html.erb partial:
<%= form_for ([#postable, #postable.post.new]), remote: true do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Create a Post..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
my related routes:
devise_for :users, :controllers => { :omniauth_callbacks => "omniauth_callbacks", :registrations => "registrations" }
resources :users, :only => [:index] do
member do
get :favourite_users, :favourited_users
end
resources :posts
end
resources :venues do
resources :posts
end
resources :groups do
resources :posts
end
Models as follows:
class Post < ActiveRecord::Base
belongs_to :postable, polymorphic: true
end
class User < ActiveRecord::Base
has_many :posts, as: :postable, dependent: :destroy
end
class Venue < ActiveRecord::Base
has_many :posts, as: :postable, dependent: :destroy
end
class Group < ActiveRecord::Base
has_many :posts, as: :postable, dependent: :destroy
end
It seems that I keep getting the error
Couldn't find Post without an ID
but I don't know why it's looking for a Post ID if it's not been created yet. Any help would be appreciated!
You have before_filter :load_postable in your controller. By default it will run for all the actions in your controller, even when the id is not specified. The error is thrown by #postable = resource_name.constantize.find(id), id is nil for index method.
Change this line to:
before_filter :load_postable, except: [:index]