Ruby on Rails search & Result on the same page error - ruby-on-rails

Here the show.html displays a dropdown, which contain Roles.
When we select the role we should able to get permission result in the same page
For that I used partial, but getting error as given in the image,
Without using partial when i tried to display in a separate display.html.erb file , I am getting proper result.
but i want to get result in same show.html.erb file.
Kindly give my some suggestions to attain the proper results
permission_controller
def display
param = params[:role]
id=param[:id]
#roles = Role.includes(:permissions).all
#uniq_controller = Role.joins(:permissions).where('roles.id=?',id).select('permissions.*').group_by { |p| p.description }
redirect_to permissions_show_path
end
def show
#permission = Permission.new
end
show.html.erb
<%= form_tag(:controller => "permissions", :action => "display") do %>
<%= collection_select(:role, :id, Role.all, :id, :name) %>
<button type="submit">search</button>
<% end %>
<th width="25px"> <%= "Controller" %></th>
<th width="25px"> <%= "Permissions" %></th>
<% #uniq_controller.each do |permission| %>
<%= render partial:"display", locals:{permission:permission} %>
<% end %>
_display.html.erb
<thead>
<th width="25px"> <%= permission.first.gsub("_"," ") %></th>
<% permission.second.each do |cont| %>
<tr>
<th width="25px"><%= check_box_tag :permission_ids, {multiple: true},
cont.id %><%= cont.name %></th>
</tr>
<% end %>
</thead>

You haven't defined #uniq_controller in the show action which triggered that error. Just define it in the show action
def show
#permission = Permission.new
#uniq_controller = Role.joins(:permissions).where('roles.id=?',id).select('permissions.*').group_by { |p| p.description }
end

You have not defined #uniq_controller in the show action in permission_controller controller which triggers this error.
I'd recommend that you define a method called uniq_controller in permission_controller as follows:
def uniq_controller(id)
Role.joins(:permissions).where('roles.id=?',id).select('permissions.*').group_by { |p| p.description }
end
and then make it available in your view as a helper method by adding this code to your permission_controller:
helper_method :uniq_controller
So the code in permission_controller should be like:
helper_method :uniq_controller
def display
#roles = Role.includes(:permissions).all
redirect_to permissions_show_path
end
def show
#permission = Permission.new
end
def uniq_controller(id)
Role.joins(:permissions).where('roles.id=?',id).select('permissions.*').group_by { |p| p.description }
end
Then in your view show.html.erb replace:
#uniq_controller.each
with:
uniq_controller(params[:role][:id]).each
This should fix the error that you are getting and follows Rails practices, for more details about helper_method please refer to:
https://apidock.com/rails/ActionController/Helpers/ClassMethods/helper_method
One more recommendation is to rename permission_controller to permissions_controller to follow Rails resources/controller naming convention.

Related

Selecting data in a view and inserting them in Users database

I am reading the contact informations of users from Outlook API, and I would like to add them to my Users database using a submit_tag approach. But it does not work. So far my form on index.html.erb looks like:
<h1>My contacts</h1>
<table class="table">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
<%= form_tag import_contacts_path, method: :put do %>
<%= submit_tag "Import Selected contact" %>
<% #contacts.each do |contact| %>
<tr>
<td> <%= check_box_tag "contact_ids[]", 'Select' %></td>
<td><%= contact.given_name %></td>
<td><%= contact.surname %></td>
<td><%= !contact.email_addresses[0].nil? ? contact.email_addresses[0].address : '' %></td>
</tr>
<% end %>
</table>
<%= submit_tag "Import Selected contactact" %>
<% end %>
My ContactController looks like:
class ContactsController < ApplicationController
include AuthHelper
def index
token = get_access_token
if token
# If a token is present in the session, get contacts
callback = Proc.new do |r|
r.headers['Authorization'] = "Bearer #{token}"
end
graph = MicrosoftGraph.new(base_url: 'https://graph.microsoft.com/v1.0',
cached_metadata_file: File.join(MicrosoftGraph::CACHED_METADATA_DIRECTORY, 'metadata_v1.0.xml'),
&callback)
#contacts = graph.me.contacts.order_by('givenName asc')
else
# If no token, redirect to the root url so user
# can sign in.
redirect_to root_url
end
end
def import
User.create(:first_name => #contacts.givenName , :last_name => #contacts.surname, :email => #contacts.email_addresses)
redirect_to imported_path
end
end
I can read my contact information without any problem, but when i try clicking on the button to import a selection of contact, I have the following error:
NoMethodError (undefined method `givenName' for nil:NilClass):
app/controllers/contacts_controller.rb:26:in `import'
My routes look like
resources 'contacts' do
collection do
put :import
end
Does anyone knows if it is actually possible to create such import function ? Because i am trying to read something that is not on a local database actually.
I ended up creating the following function in the controller:
def import_contact(contact)
Contact.create(email: !contact.email_addresses[0].nil? ? contact.email_addresses[0].address : '', first_name: contact.given_name, last_name: contact.surname, user_id: current_user )
return !contact.email_addresses[0].nil? ? contact.email_addresses[0].address : ''
end
and the the view calls the function: <%= import_contact(contact) %>
This way i unfortunately do not select which conctact i want to import. I import all of them, but that is the best i could find now.
You have called #contacts in
def import
User.create(:first_name => #contacts.givenName , :last_name => #contacts.surname, :email => #contacts.email_addresses)
redirect_to imported_path
end
But you have not define #contacts. Since #contacts is nil and you are calling givenName to nil it is giving error. Can you specify #contacts within import method or before filter so that it would be available with in that method.
Hope defining #contacts will fix the issue. If the issue still exist let me know.
Please check the params, in params the value must have come you can use something like
def import
User.create(:first_name => params[:givenName] , :last_name => params[:surname], :email => params[:email_addresses])
redirect_to imported_path
end
Try this one and let me know if there is any issue. Or you can send what params that comes.

rails5: generic grid - how to get column names for current search

I wan to do a generic grid, that could be used in my app to show data from different Models. As I am a newbie in RoR - please let me know if my "vision" is ok, or i should change the way i think about this problem:
Controller:
class Admin::UsersController < ApplicationController
before_action :authenticate_user!
authorize_resource
def index
#current_scope = params[:role]
#users = User.select(:id, :email, :role, :last_sign_in_at).role(#current_scope)
end
end
User Model:
scope :role, -> (role) {where('role = ?', role) if role.present?}
Index view:
<%= render '/layouts/shared/grid', object: #users%>
Grid partial:
<% object.column_names.each do |column_name| %>
<th><%= column_name %></th>
<% end %>
My problem is that i can show always ALL columns (that is what ActiveRecord::Relation returns), not only columns for parameters selected in my query. I see few potential solutions - which one would be the best?
usage of ActiveRecord::Base.connection.exec_query - if i do so, i could use then .columns method that returns what i need. But i am not sure if i like it...
usage of search_params instead of query result to iterate
Any other suggestion?
You can use values method. It's not very documented but it returns parsed sql query.
For this query:
User.select(:id, :email, :role,:last_sign_in_at).role(#current_scope).values
It returns something like this:
{:select=>[:id, :email, :role, :last_sign_in_at], :where=>#<ActiveRecord::Relation::WhereClause:0x007fe0d3b29bf0 #predicates=["role = admin"], #binds=[]>}
If a query will not use select when values will not return select result too. In this case, you need to use column_names.
Too I can recommend you wrap table code to decorator. This is raw example:
class TableDecorator
def initialize(scope)
#scope = scope
end
def header_columns
scope.values[:select] || #scope.column_names
end
def columns
#scope
end
end
# controller
#table = TableDecorator.new(#users)
# index view
<%= render '/layouts/shared/grid', locals: {table: #table} %>
# grid partial
<table>
<thead>
<tr>
<% table.header_columns.each do |column_name| %>
<th><%= column_name %></th>
<% end %>
</tr>
</thead>
<tbody>
<% table.columns.each do |item| %>
<tr>
<% table.header_columns.each do |column_name| %>
<td><%= item[column_name] %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>

Custom Controller Method, Route, & ERB

I have a search form and I need to be able to filter based on whether or not pets are allowed, but I'm not sure how to accomplish this. I have setup a route, a controller method, and a button but none of that seems to be working.
listings_controller:
def pets_allowed
#listings = #listings.where(pets: true)
end
routes.rb:
get "pets_allowed" => "listings#pets_allowed"
html.erb file:
<div>
<%= link_to 'Pets Allowed', pets_allowed_path, :class => 'button btn-transparent' %>
</div>
Maybe you meant
def pets_allowed
#listings = Listing.where(pets: true)
end
This is a basic example of another way to do what I think you're aiming for (as per comments).
This adds a new action in your Listings controller that returns a filtered list of results based on the users input from the search form on your listings index page. The results are rendered using the same index template. The logic for checking/retrieving results can be modified based on what you want. If you just want a check box, only have a checkbox or a button that calls the action.
You could do similar logic but use ajax to return the results and render them on the index template using a partial.
This should give you enough information to google for examples/tutorials and try different ways of getting what you want.
Add a route:
# routes.rb
get 'pets_allowed', to: 'things#pets_allowed'
Add a new action:
# listings_controller.rb
# GET /things
# GET /things.json
def index
#listings = Listing.all
end
# Get /pets_allowed
def pets_allowed
#listings = Listing.where("name LIKE ? and pets = ?", "%#{params[:name]}%", params[:pets] )
render template: "listings/index", variable: #listings
end
Add a search form to your view:
# listings/index.html.erb
<h1>Listings</h1>
<%= form_tag('pets_allowed', method: 'GET' ) do %>
<%= label_tag :name %><br>
<%= text_field_tag :name %>
<br>
<%= label_tag :pets %><br>
<%= check_box_tag :pets, 't' %>
<br>
<%= submit_tag("Search") %>
<% end %>
<table>
<thead>
<tr>
<th>Listing name</th>
</tr>
</thead>
<tbody>
<% #listings.each do |listing| %>
<tr>
<td><%= listing.name %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Listing', new_listing_path %>

rails will_paginate not work with search results

I'm following the advanced search form revised from railscasts and i'd like to paginate search results but I don't know where put the code for pagination.
I have a model:
mineralisearch.rb
class Mineralisearch < ActiveRecord::Base
attr_accessible :keywords,:keywords1
def segnalazione_mineralis
#segnalazione_mineralis ||= find_segnalazione_mineralis
end
private
def find_segnalazione_mineralis
segnalazione_mineralis = SegnalazioneMinerali.order(:titolo)
segnalazione_mineralis = segnalazione_mineralis.where("titolo like ?", "%#
{keywords}%") if keywords.present?
segnalazione_mineralis
end
end
I have a controller
mineralisearches_controller.rb
class MineralisearchesController < ApplicationController
def new
#mineralisearch = Mineralisearch.new
end
def create
#mineralisearch = Mineralisearch.create!(params[:mineralisearch])
redirect_to #mineralisearch
end
def show
#mineralisearch = Mineralisearch.find(params[:id])
end
end
and a view
show.html.erb
<h1>Risultati della ricerca</h1>
<table class="table1">
<tr>
<th>Titolo:</th><br>
<th>Creato il:</th>
<th>Ultima Modifica il:</th>
<th></th>
</tr>
<%= render #mineralisearch.segnalazione_mineralis %>
</table>
with this partial
_segnalazione_minerali.html.erb
<tr>
<td><%= segnalazione_minerali.titolo %> </td>
<td><%= l(segnalazione_minerali.created_at, format:"%e %B %Y %k:%M:%S") %></td>
<td><%= l(segnalazione_minerali.updated_at, format:"%e %B %Y %k:%M:%S")%></td>
<td><%= link_to 'Mostra', [segnalazione_minerali.user, segnalazione_minerali]%></td>
</tr>
I know that I must put some code like
#mineralisearch = Mineralisearch.order("Titolo").page(params[:page]).per_page(10)
in the controller
and
<%= will_paginate #mineralisearch, :previous_label => 'Prec', :next_label => 'Succ' %>
but I really don't know where! I tried to put these in the show view and in the controller but they don't work!
Thanks all for help
According to will_paginate
This code
#mineralisearch = Mineralisearch.order("Titolo").page(params[:page]).per_page(10)
should be like this
#mineralisearch = Mineralisearch.order("Titolo").paginate(:page => params[:page],:per_page => 10)
And you can have this
<%= will_paginate #mineralisearch, :previous_label => 'Prec', :next_label => 'Succ' %>
in your show view.
But it is not a normal thing to have pagination in the show view currently which you wants.It is much preferred to have pagination on the index view.If you want to have like this,then you have to move the respected controller code snippet to index action and the view code snippet to the index.html.erb file.

Ransack not working (no error, just not functioning)

Would love it if anyone can see what I'm doing wrong. Followed the docs: https://github.com/activerecord-hackery/ransack
My model defines that a Signup has_many Inventories
Controller code:
def index
#q = Inventory.search(params[:q])
#inventories = #q.result.includes(:signup)
end
View code:
<%= search_form_for #q, url: url_for(controller: 'inventories', action: 'index') do |f| %>
<%= f.label :item_name_cont %>
<%= f.search_field :item_name_cont %>
<%= f.label :signup_email_cont %>
<%= f.search_field :signup_email_cont %>
<%= f.submit %>
<% end %>
<table>
<thead>
<tr>
<th><%= sort_link(#q, :item_name, "Item", default_order: :desc) %></th>
<th><%= sort_link(#q, 'signups.email', "Email") %></th>
<th>Action</th>
<th colspan="5"></th>
</tr>
</thead>
<tbody>
<% Inventory.all.each do |inventory| %>
<tr>
<td><%= inventory.item_name %></td>
<td><%= inventory.signup.email %> %></td>
</tr>
</tbody>
</table>
Also, if it's helpful, if I remove the url: specification in the search form, I get an error: No route matches [GET] "/inventories/search"
Better Option
Please make sure that the view code that you posted is in views/inventories/index.html.erb file and change Inventory.all.each to #inventories.each. Then you would be able to access the search form at http://localhost:3000/inventories.
Or
From the error that you mentioned, it looks like you are doing this on /inventories/search page. If you want to stick to that URL, move your index method code into search method in your controller (as shown below) and add a route for search with GET in your routes file.
def search
#q = Inventory.search(params[:q])
#inventories = #q.result.includes(:signup)
end
Change this;
def index
#q = Inventory.search(params[:q])
#inventories = #q.result.includes(:signup)
end
to
def index
#q = Inventory.ransack(params[:q])
#inventories = #q.result.includes(:signup)
end
I think I fell into the same situation. It might be working it's just tricky to identify. Are you getting any returns? Possible all the returns? If that is the case it might be a matter of the default search. The default search returns everything as you would expect if you had just put Inventory.all Try .
Inventory.ransack(name_eq: 'potatos').result
this would also work
Inventory.ransack(special_potato_eq: 'potatoes').result
This will limit the return to exact matches of Inventory.potato or Inventory.special_potato
This is the exact bit of code that worked for me
#q = User.ransack(email_eq: params[:q][:email])
Checkout the reference link for other search options.
Reference: https://github.com/activerecord-hackery/ransack/wiki/basic-searching

Resources