Ruby on Rails Search Bar for Devise Users - ruby-on-rails

hey guys im working on an application where there a two devise users 'Family' & 'Team', I want one of the users to be able to search for the other users by name. I'm having trouble doing this i currently have the following code
team.rb
class Team < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable
def self.search(user_name)
if user_name
user_name.downcase!
where('LOWER(name) LIKE ?', "%#{user_name}%")
else
all
end
end
end
routes.rb
devise_for :teams, path: 'teams' , controllers: { sessions: "teams/sessions", confirmations: 'teams/confirmations', registrations: 'teams/registrations'}
controller.rb
def team_search
#users = Team.search(params[:search])
end
view
<%= form_tag teams_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>

You can use a separate controller and path:
class TeamsController
def search
# ...
end
end
# routes.rb
resources :team do
collection do
get :search
end
end

Related

How to display which user created the post?

Trying to learn ruby on rails by creating a reddit clone.
So now I'm trying display the username of the user who created the post, but I'm only getting it displayed as u/username everywhere.
Also when I try to click on u/username to see if I can get data about user by going to his page, all I'm getting is an error saying:
undefined method `username' for nil:NilClass
This is my partial _list class that displays data about post:
<% posts.each do |post| %>
<%= link_to post.community.name %> | Posted by <%= link_to post.account.username, profile_path(:username) %> <%= time_ago_in_words post.created_at%> ago. </p> </small>
<%= link_to post.title, community_post_path(post.community_id, post) %>
<%= truncate post.body, length: 200 %>
<% end %>
profile.html.erb just to display username for now:
<%= #profile.username %>
account.rb:
class Account < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :posts
has_many :communities
validates_presence_of :username
end
public_controller:
class PublicController < ApplicationController
def index
#communities = Community.all.limit(5)
#posts = Post.order(id: :desc).limit(20)
end
def profile
#profile = Account.find_by_username params[:username]
end
end
post.rb:
class Post < ApplicationRecord
belongs_to :account
belongs_to :community
validates_presence_of :title, :body, :account_id, :community_id
end
and routes.rb:
Rails.application.routes.draw do
devise_for :accounts
get "u/:username" => "public#profile", as: :profile
resources :communities do
resources :posts
end
root to: "public#index"
end
Full repo here

Using devise_invitable with enum User roles

1. Description core problem
I am implementing the devices_invitable gem for inviting users. The gem is correctly added, as I am able to send users the standard devices_invitable email to invite them for the application.
The problem that I am encountering, is that I am not sure how to enable an admin (to be identified with enum) to assign the role of the user they are inviting (e.g. they should enter an email AND role of the user they invite, which should then be correctly added to my DB).
Note: As you can see below, I'm currently trying to solve it using nested forms with the cocoon gem, but I am open to other approaches.
2. My current application
The application has 2 tables with a many to-many relationship between them:
(i) Users, with role attributes defined by enum.
(ii) Parks
The idea is to let an admin invite a new user to a park (not entire application) by entering email+role.
3. The code
user.rb
class User < ApplicationRecord
has_many :user_parks, dependent: :destroy
has_many :parks, :through => :user_parks
enum role: [:owner, :admin, :employee, :accountant]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :admin
end
devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :invitable
end
park.rb
class Park < ApplicationRecord
has_many :user_parks, dependent: :destroy
has_many :users, :through => :user_parks
accepts_nested_attributes_for :users, allow_destroy: true, reject_if: ->(attrs) { attrs['email'].blank? || attrs['role'].blank?}
end
parks_controller.rb
class ParksController < ApplicationController
def update
#park = Park.find(params[:id])
authorize #park
url = Rails.application.routes.recognize_path(request.referrer)
last_action = url[:action]
if last_action == 'edit_users' & #park.user.last.nil?
#user=#park.user.last.invite!(email: park_params[:user][:email])
end
#park = #park.update_attributes(park_params)
redirect_to parks_path
end
def edit_users
#park = Park.find(params[:id])
authorize #park
end
private
def park_params
params.require(:park).permit(:name, users_attributes: [:email, :role, :_destroy])
end
end
edit_users.html.erb
<%= render 'users_edit_form', park: #park%>
_users_edit_form
<%= simple_form_for [#park] do |f|%>
<h1>Park</h1>
<% #park.users.each do |user| %>
<%= user.email %>
<% end %>
<div>
<% f.simple_fields_for User.new, :url=> new_user_invitation_path, html: { class: 'form-inline' } do |user| %>
<%= user.input :email %>
<%= user.input :role, priority: [:employee], collection:[:owner, :admin, :employee, :accountant] %>
<%= f.button :submit, 'Invite User', class: 'btn-primary' %>
<% end %>
</div>
#TEST for standard view (sends invite but does not assign park/role)
<%# link_to "new user add", new_user_invitation_path %>
<%= f.button :submit, 'Invite User', class: 'btn-primary' %>
<% end %>
1st issue I can see is you are using a bitwise & on this line:
if last_action == 'edit_users' & #park.user.last.nil?
you would usually use a logical and && or and
2nd issue with that line is #park.user should be #park.users if it's declared as a has_many
3rd issue is I'm not sure you need to be looking at request.referrer?
Assuming you can get to the invite! line then you might want to check the docs for the 2 different versions of invite!
When the user is already created:
user = User.find(42)
user.invite!(current_user) # current user is optional to set the invited_by attribute
see example in README
OR
When the user isn't created yet:
User.invite!(email: 'new_user#example.com', name: 'John Doe')
# => an invitation email will be sent to new_user#example.com
see example in README

param is missing or the value is empty: user - Rails

I have got the following rails app, which allows users to subscribe to widgets. i.e. Many-to-Many through model with Users-to-Widgets through Subscriptions.
My Models:
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :widget
validates_uniqueness_of :user_id, scope: :widget_id
end
class User < ActiveRecord::Base
has_many :subscriptions
has_many :widgets, through: :subscriptions
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
class Widget < ActiveRecord::Base
has_many :subscriptions
has_many :users, through: :subscriptions
end
My Controller:
class SubscriptionsController
def edit
#user = current_user
end
def update
#user = current_user
if #user.update(user_subscription_params)
redirect_to #user, notice: "Subscriptions updated"
else
render :edit
end
end
private
def user_subscription_params
params.require(:user).permit(:widget_ids)
end
end
and this is being rendered in views/subscriptions/_forms.html.erb like this:
<%= form_for #user, url: user_subscription_path, method: :patch do |f| %>
<%= f.collection_check_boxes :widget_ids, Widget.all, :id, :name %>
<%= f.submit %>
<% end %>
I am getting the error:
No route matches {:action=>"show", :controller=>"subscriptions"} missing required keys: [:id]
I would be really grateful of any ideas how to fix this.
Edit:
Routes.rb:
Rails.application.routes.draw do
root 'home#index'
resources :widgets
resources :subscriptions
devise_for :users
devise_scope :user do
get '/users/sign_out' => 'devise/sessions#destroy'
end
authenticated :user do
root to: 'home#index', as: :authenticated_root
end
You can try
<%= form_for #user, url: user_subscription_path(#user), method: :patch do |f| %>
<%= f.collection_check_boxes :widget_ids, Widget.all, :id, :name %>
<%= f.submit %>
<% end %>

Devise: Could not find a valid mapping for User id

The following form in a partial called locationpicker:
<%= simple_form_for(current_user, url: registration_path(current_user), method: :put ) do |f| %>
<% f.association :location, collection: Location.where(category: 'Country'), label: false, input_html: {onchange: "this.form.submit()"} %>
<% end %>
brings up this error:
Could not find a valid mapping for #<User id:...
It's the registration_path(current_user) which is causing it. My suspicions were that something has changed in the routes or the users model, but I can't for the life of me think what or know where to start looking. I thought it might be the recent inclusion of ActiveModel::Dirty but removing that doesn't solve the problem.
Routes.rb:
scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
devise_for :users, :controllers => {:registrations => "registrations"}
...
end
User.rb
class User < ActiveRecord::Base
include ActiveModel::Dirty
devise :database_authenticatable, :registerable, #:encryptable,
:recoverable, :rememberable, :trackable, :validatable, :lockable
has_one :assignment
has_one :role, :through => :assignment
has_many :changerequests, inverse_of: :created_by, foreign_key: "created_by_id"
belongs_to :location, required: true
belongs_to :person, inverse_of: :user, required: true
has_many :people_details, through: :person
scope :inclusive, -> {includes(:person).includes(:people_details).includes(:location).includes(:assignment).includes(:role)}
after_update :update_locale
after_save :expire_caches
def role?(role_sym)
role_name.to_sym == role_sym
end
def role_group?(role_sym)
role_group_name.to_sym == role_sym
end
def send_on_create_confirmation_instructions
true
end
def update_locale
if locale_changed?
I18n.locale = self.locale || "en"
self.expire_caches
end
end
def country
if self.location.category == "Country"
self.location
elsif self.location.ancestors.where(category: "Country")
self.location.ancestors.where(category: "Country").first
elsif self.location.children.where(category: "Country")
self.location.children.where(category: "Country").first
end
end
def expire_caches
#Admin users can change their location so the caches need expiring
if location_id_changed? or locale_changed?
ctrlr = ActionController::Base.new
#Clear fragments
ctrlr.expire_fragment("#{id}_#{locale}_location_picker")
etc...
end
if location_id_changed?
#Clear other caches
Rails.cache.delete("#{id}_locations_scope")
.... etc
end
end
Try adding as: in your simple_form_for call:
<%= simple_form_for(current_user, as: :user, url: registration_path(current_user), method: :put ) do |f| %>
<% f.association :location, collection: Location.where(category: 'Country'), label: false, input_html: {onchange: "this.form.submit()"} %>
<% end %>
Normally, the devise registrations edit form looks like:
= simple_form_for(resource, as: resource_name, url: user_registration_path, html: { method: :patch }) do |f|
In other words, using "resource" not "current_user". You might try that as well, if your form partial is being rendered within the devise controller context.

Couldn't find Photo with id=16

Not sure why this isn't working but I've been mis-guided I think....I'd rather not re-route but simply have the photo uploaded in the current landing_welcome page.. not be transfered to an update template.
error:
Couldn't find Photo with id=16 [WHERE "photos"."attachable_id" = $1 AND "photos"."attachable_type" = $2]
def update
#user = current_user.photos.find(params[:id])
#user.update_attributes!(person_params)
redirect_to #user
end
Users_controller.rb
class UsersController < ApplicationController
def update
#user = current_user.photos.find(params[:id])
#user.update_attributes!
redirect_to #user
end
def show
end
end
landing_welcome.html.erb
<div class="tab-pane" id="tab2">
<%= nested_form_for current_user, :html=>{:multipart => true } do |f| %>
<%= f.fields_for :photos do |p| %>
<p>
<%= image_tag(p.object.file.url) if p.object.file? %>
<%= p.label :file %><br />
<%= p.file_field :file %>
</p>
<%= p.link_to_remove "Remove this attachment" %>
<% end %>
<%= f.link_to_add "Add photos to your profile", :photos %>
<br /><br />
<p><%= f.submit %></p>
<% end %>
</div>
routes.rb
root to: "home#landing"
devise_for :users, :controllers => {:registrations => "users/registrations",
:sessions => "users/sessions",
:passwords => "users/passwords"}
get "welcome", to: "home#landing_welcome"
devise_scope :user do
# get "edit/edit_account", :to => "devise/registrations#edit_account", :as => "account_registration"
get 'edit/edit_account' => 'users/registrations#account_registration', as: :edit_account
end
patch '/users/:id', to: 'users#update', as: 'user'
photo.rb
class Photo < ActiveRecord::Base
attr_accessible :file
belongs_to :attachable, :polymorphic => true
mount_uploader :file, FileUploader
end
user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email,
:password,
:password_confirmation,
:zip,
:gender,
:remember_me,
:first_name,
:last_name,
:birthday,
:current_password,
:occupation,
:address,
:interests,
:aboutme,
:profile_image,
:photos_attributes
has_many :photos, as: :attachable
accepts_nested_attributes_for :photos
mount_uploader :profile_image, ProfileImageUploader
validates :gender, :presence => true
def number_of_users
User.all.count
end
end
For lack of a better answer, I think your woes lie in the query generated by your app:
Couldn't find Photo with id=16 [WHERE "photos"."attachable_id" = $1 AND "photos"."attachable_type" = $2]
Two factors are present here:
Why is your attachable_id being called as $1?
Why is your attachable_type a number, not a string?
Polymorphic Association
Your query is trying to load a Photo with ID=16, however, your query is also trying to validate the model, to satisfy the polymorphic association. This is where the error is coming from
As you've not stated which route / page this error is showing, I can only speculate as to the cause of the problem:
#user = current_user.photos.find(params[:id])
This query is really bad for a number of reasons:
You're using the current_user object directly. I might be wrong here, but this is used by Devise / Warden to store relative information about the logged-in user, and is not a real ActiveRecord object (with relational data etc)
You're trying to .find on top of a relation (current_user.photos)
Although this might be incorrect, I would look at doing this for that query:
#photo = User.joins(:photos).find(current_user.id).where("photos.id = ?", params[:id])
Then you can perform the updates you require

Resources