So i want to create the view:
1. for normal user, to see it job app status:
def index
#users ||= current_user
#job_apps = #users.job_app
end
It works perfectly on view.
2. Trouble (job_app method undefined) : create view for admins so they can see all candidates:
def empl
#users = User.all.where(:user_type => 'candidate')
#job_apps = #users.job_app.all
end
Note : without #job_apps i can see all the users as well.
I'm going to make a bit of an educated guess here: job_app is indeed a method of the User class, but what you're dealing with in your controller's empl method is not an instance of User, but rather, an instance of ActiveRecord::Relation, which is more or less an array of User objects. User.job_app works because job_app is a member of User, but not of ActiveRecord::Relation.
To achieve what you want, you have to do some iterating through the elements of that array within the view associated with your empl method.
controller code:
def empl
#users = User.all.where(:user_type => 'candidate')
end
view code:
<% #users.each do | user | %>
<%= user.job_app %>
<% end %>
Related
I am quite new at rails and I am having some trouble designing an admin dashboard.
What I want to achieve is this:
Have a list of multiple users from database.
Have the ability to select multiple records.
Have the ability to apply different actions to all of the
selected records.
The actions MAY not be directly translatable into SQL queries. (for example send an email)
I am not looking for a complete solution to the problem just a general description on how to approach this. I have a feeling I started on a wrong path.
So far I am doing this:
view
<%= form_tag("some_path", method: "get") do %>
<% #users.each do |user| %>
<%= check_box_tag "user_ids[]", users.id %>
<%end%>
<%= submit_tag("Send Email") %>
<%end%>
controller
def send_email
#recipients = User.find(params[:user_ids])
#recipients.each do |recipient|
Notifier.raw_email(recipient.email, params[:user_email][:subject], params[:user_email][:body]).deliver
end
end
This works as it is but i can only apply one action, send email that is.
I want to be able to choose an action to apply to all selected records or apply multiple actions to the selected records
Any thoughts?
You can use the send method to call methods of the model.
class User
def send_email(subject, body)
Notifier.raw_email(self.email, subject, body).deliver
end
end
Let /some_path also accept an array of actions
In our case actions = ['send_email']
In the action that some_path resolves to,
class SomeController < ActionController::Base
def some_action # that some_path resolves to in your config/routes.rb
#recipients = User.find(params[:user_ids])
#actions = params[:actions]
#recipients.each do |recipient|
#actions.each do |action|
recipient.send(action, params[:subject], params[:body])
end
end
end
end
In this way you can call multiple methods. Make sure you only accept valid action values or else the admin can simply call any of the User's methods.
You can have a select tag with the different actions you need.
Then on change of the select tag, you can update the action attribute of the form. eg, using jQuery.
$('#my-action-select').change(function() {
$('#myform').attr('action', $(this).val)
})
I am making an app where current_user (logged in user) can write reviews, and make each review public or private,
with a radio button.
If public, every other user can see that review. If private, only current_user can see it.
visible.true and visible.false, depending on which radio button is selected.
I'm trying to come up with the code/syntax to get this working?
Something like:
#review.user is the person who wrote a particular review
#if review.user is not current_user, and the review is
#marked as false, then don't show that review
If review.user != current_user
&& review.visible = false
don't show review.
At present in a reviews_helper.erb I have:
def review_block(review, options = {})
options = {:review => review}
render 'reviews/review', options
end
And in my view, show.html.erb:
<div class="reviews" >
<% #reviews.each do |review| %>
<%= review_block review %>
<% end %>
</div>
Any chance you could tell me how I should modify my helper to get it working, or any other suggestions?
In the case you want to filter the #reviews array you could do something like this:
#reviews.select { |review| review.visible_to?(current_user) }.each do |review|
render 'reviews/review', :review => review
end
The Array's #select method filters a given array with the condition passed as block. I would move the visibility logic to the Review model to the method call visible_to? which would be something like you said above:
# review.rb
def visible_to?(user)
self.user.id == user.id || # assuming they have an ID
visible == true
end
Better yet, if you are using Rails you can completely remove the select method call from the view and create a scope in the Review class.
Edit: Using a scope
#review.rb
scope :visible_to, lambda { |user| conditions( 'user_id = ? or visible = ?', user.id, true ) }
This way, when you are building your #reviews array - presumably in a controller action, you can do something like this:
#reviews_controller.rb
#reviews = Review.visible_to(current_user)
You can obviously nest several scopes - like order, limit, where, etc - and filter the review the way you want. Nevertheless the utility visible_to? method should also be defined for the instance itself alongside with the scope.
Always keep in mind to have your views as dumber as you can, i.e. your views should know the least about your models and your business logic. This will ensure there are no tight dependencies between your views and your models.
I'm trying to list a user's wanted ads in their show page when they access /users/:id.
In my controller I have:
def show
#user = User.find(params[:id])
#wanted_ads = WantedAd.where(:user_id => params[:id])
And in my show.html.erb I have:
<%= #wanted_ads %>
Binding.pry says #wanted_ads is nil. On the actual page I get #<ActiveRecord::Relation:0x007fa3b5a93408>. This is seemingly a simple thing I'm trying to do -- what am I missing?
The where function returns a ActiveRecord::Relation.
So, you can call first to get the first element, last to get the last one or all to get all elements stored in an array called #wanted_ads.
#wanted_ads = WantedAd.where(:user_id => params[:id]).all
You can then go through this array and choose the attributes you want to pass to the view for each element.
Just a tip:
You should have in your User model an ActiveRecord relation, like this:
has_many :wanted_ads
And in your WantedAd model, like this:
belongs_to :user
And with this, you have a relation of one-to-may.
Then, you can do this:
def show
#user = User.includes(:wanted_ads).find(params[:id])
end
And then, in your view:
<% #user.wanted_ads.each do |wanted_ad| %>
<%# do something %>
<% end %>
where returns a collection of objects, not just a single object. So depending on what's returned you'll want to either call first to get the single instance that ought to return, or call each to iterate over the wanted ads and display them on your page.
You're seeing an instance of ActiveRecord::Relation in pry because of the underlying query mechanism that lazy loads the results. More details can be found here.
Assuming your #wanted_ads is not nil and you want to loop through all the wanted ads...
<% #wanted_ads.each do |wanted_ad| %>
<%= wanted_ad.some_attribute_of_wanted_ad %>
<% end %>
I would also suggest you be aware of SQL injection with the following code in your controller.
#wanted_ads = WantedAd.where(:user_id => params[:id])
As it should be
#wanted_ads = WantedAd.where(":user_id => ?", params[:id])
is It possible get a shuffle/random of a collection from action in controller.
def action
#pseudocode something like the next:
#objects = Object.random
respond_to do |format|
format.html
end
end
I now can get shuffle from my view, with:
<% #objects.shuffle.each do |microfunc| %>
.
.
.
<% end %>
On view is possible with each or for loop. I don't want use loop to get random Object from one collection.
How can I get random objects inside Mongoid::Criteria from my action controller?
There isn't a great way. Your choices:
Store an integer for each document and get by its value: http://cookbook.mongodb.org/patterns/random-attribute/
use 'skip' which is inefficient: Mongoid random document
I have a users table. It contains a field "user_type".
I added the following scope stmts to the user.rb file:
scope :uemployee, where(:user_type => 'employee')
scope :uclient, where(:user_type => 'client')
scope :ucontractor, where(:user_type => 'contractor')
I created a view and I would like it to list he employees.
Here is the code I'm trying to use:
<% #users.uemployee.each do |user| %>
But, I get "undefined method `uemployee' for nil:NilClass"
What am I doing wrong?
Thanks
Looks like you wanted to do this:
<% User.uemployee.each do |user| %>
But this is considered to be a bad practice. You have to prepare you data in a controller and a view just cycles through it:
# in a controller's action
#users = User.uemployee
#in a view
<% #users.uemployee.each do |user| %>
But even this isn't the best approach. If you create the file views/users/_user.html.erb which shows the info about a particular user (current user will be available as a simple user variable, without the #) then you can simply write:
# in a view
<%= render #users %>
# remember, #users variable was set in your controller
then Rails will cycle through all the users "inside" the #users variable and show them one-by-one.
Your #users collection is nil