Rails many to many association - ruby-on-rails

I have implemented a save buttons for jobs and it work fine now i want to list some of the saved jobs in the jobs index page for this i have this code
<h3>Saved Jobs</h3>
<ul>
<% #user.saved_jobs.limit(5).order(:created_at).reverse_order.each do |saved_job| %>
<li><%= link_to saved_job.job.title, saved_job.job.url %>
<span class="delete_button">
<%= link_to "X", saved_job, :method => :delete, :remote => true %></span></li>
<% end %>
</ul>
<%= link_to "see all", saved_jobs_path %>
but when i want access to the jobs index page i get this error undefined method saved_jobs' for nil:NilClass
this my saved_jobs controller
class SavedJobsController < ApplicationController
before_filter :authenticate_user!
def index
#saved_jobs = SavedJob.find_all_by_user_id(current_user.id)
end
def create
#job = Job.find(params[:saved_job][:job_id])
current_user.save_job!(#job)
respond_to do |format|
format.html { redirect_to #job }
format.js
end
end
def destroy
#job = SavedJob.find(params[:id]).job
current_user.saved_jobs.find(params[:id]).destroy
respond_to do |format|
format.html { redirect_to #job }
format.js
end
end
end
and this is my user controller
class ProfilesController < ApplicationController
before_filter :authenticate_user!
def show
#user = User.find_by_slug(params[:id])
if #user
#posts = Post.all
render action: :show
else
render file: 'public/404', status: 404, formats: [:html]
end
end
def index
#users = user_scope.paginate(page: params[:page], per_page: 2)
end
private
def user_scope
current_user ? User.where.not(id: current_user.id) : User.all
end
end

The error suggests that you didn't set #user in your controller action. Can you post the code from your controller?
Update based on controller code:
Your index action in SavedJobsController does not set #user. When you then call #user.saved_jobs.limit(5)..etc... in the view #user is nil, rather than current_user or whatever.
Additionally, you have set #saved_jobs - why not just use that instead of #user.saved_jobs?
for instance:
#in SavedJobsController
def index
#saved_jobs = current_user.saved_jobs.limit(5).order('created_at DESC')
end
and then, in your view:
<% #saved_jobs.each do |saved_job| %>

Related

First argument in form cannot contain nil or be empty Rails

In my index page I am trying to create a modal that contains a form so that users can create users on the index page. I am using devise to create these users.
However, when I try to create the form for this in the modal, I get this error.
First argument in form cannot contain nil or be empty
<%= form_for #user, html: { multipart: true } do |form| %>
...
<% end %>
Here is my controller:
class UsersController < ApplicationController
before_action :find_account, only: [:index, :new, :create]
def index
if params[:email].present?
#users = User.where(email: params[:email]).first
else
#users = User.all
end
respond_with #users
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to root_url, notice: 'User was sucessfully created' }
else
format.html { render :new }
end
end
end
private
def user_params
params.require(:user).permit(:email, :first_name, :last_name, :password)
end
def find_account
#account ||= Account.find(params[:account_id])
end
end
The user is a nested route because it belongs to an account:
new_account_user GET /accounts/:account_id/users/new(.:format) users#new
Does anybody know why I am getting this error? Since I am creating the #user variable in my controller and finding the account_id in the before_action I am not sure what the problem is.
Update:
If I implement this feature in another form that is working it gives the same error. Possibly something having to do with this not being on the correct action page?
You defined #user but using #material in form and of course #material is nil -> throw the errors.
If the user belongs to account, so the form should be:
<%= form_for [#account, #user], html: { multipart: true } do |form| %>
...
<% end %>
If the user is independent, so the form should be:
<%= form_for #user, html: { multipart: true } do |form| %>
...
<% end %>

Undefined method error when using Searchkick with pagination

I am trying to implement a search function on my Rails app to get a search box working.
However, when running the code, the following error is raised:
NoMethodError in PostsController#index undefined method `paginate' for #<Searchkick::Results:0x007f3ff123f0e0>
(I also have a tag cloud, which is working fine if I keep the code below unchanged, but if I change #posts = #posts to #posts = Post.search it breaks the tag functionality too.)
I am using:
Rails 4.2.0
ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux]
Code:
Here is how my PostsController looks like:
class PostsController < ApplicationController
before_action :find_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def new
#post = current_user.posts.build
end
def create
#post = current_user.posts.build(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def edit
#post = Post.friendly.find(params[:id])
end
def update
#post = Post.friendly.find(params[:id])
if #post.update(post_params)
redirect_to #post
else
render 'edit'
end
end
def destroy
#post.destroy
redirect_to root_path
end
def index
if params[:tag]
#posts = Post.tagged_with(params[:tag]).paginate(page: params[:page], per_page: 5)
else
#posts = Post.order('created_at DESC').paginate(page: params[:page], per_page: 2)
end
if params[:nil].present?
#posts = #posts.search(params[:nil]).paginate(page: params[:page])
else
#posts = #posts.paginate(page: params[:page])
end
end
def show
#post = Post.friendly.find(params[:id])
end
def autocomplete
render json: Post.search(params[:query], autocomplete: true, limit: 5).map(&:title)
end
private
def find_post
#post = Post.friendly.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :description, :content, :tag_list, :preview)
end
end
end
This is how my navbar search form looks like
<li class="navs">
<%= form_tag posts_path, method: :get do%>
<%= text_field_tag :search, params[:query], placeholder: "Search Blog", name: "nil" , required: "", class: "input-field", id: "post_search", autocomplete: "off" do %>
<%= submit_tag "", class: "material-icons search-box" %>
<% end %>
<% if params[:search].present? %>
<%= link_to "X", posts_path %>
<% end %>
<% end %>
</li>
I have searched a lot and couldn't find any answers specific that could give me a right direction as to what I am doing wrong.
I would really appreciate any help.
The problem is that the search call will return a Searchkick::Results collection, rather than an ActiveRecord::Relation. The latter has been patched with the paginate method, while the former has not, thus raising a NoMethodError.
According to the documentation, you should be able to make this work by passing the pagination parameters to the search method:
#posts = #posts.search(params[:nil], page: params[:page])
Alternatively to doing pagination within the SeachKick query you can just do the following in a separate step.
#posts = Kaminari.paginate_array(#posts).page(params[:page])

How to create a new object with Ajax request?

For example I have my index view with all objects in database. And instead of clicking on Create button I want to get it done without refreshing the page using Ajax. How to do it? How can I change my controller for this purpose? Thanks in advance.
My controller
class ArticlesController < ApplicationController
before_filter :authorize, only: [:edit, :new, :destroy]
def index
#articles = current_user.articles
end
def show
#article = Article.find(params[:id])
redirect_to users_path
end
def edit
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
def create
#article = current_user.articles.build(article_params)
if #article.save
redirect_to user_articles_path(current_user)
else
render 'new'
end
end
def update
#article = Article.find(params[:id])
respond_to do |format|
if #article.update(article_params)
format.html {redirect_to user_articles_path(current_user), notice: 'Post was successfully updated'}
format.json { head :no_content }
else
format.html {render action: 'edit' }
end
end
end
def destroy
#article = Article.find(params[:id])
#article.destroy
respond_to {|format| format.js }
end
private
def article_params
params.require(:article).permit(:title)
end
end
For the Ajax, you need a form/link/button with remote:true option, a controller action to handle the JS request and a corresponding view page.
#new.html.erb
<%= form_for #article, remote: true do |f| %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<% end %>
<b>List of Articles</b>
<ul id="articles">
<%= render #articles %>
</ul>
As you want it for creating the articles, change your new and create methods like below
#articles_acontroller
def mew
#article = Article.new
#articles = current_user.articles
end
def create
#article = current_user.articles.build(article_params)
if #article.save
respond_to do |format|
format.html { redirect_to user_articles_path(current_user) }
format.js
else
render 'new'
end
end
end
Add a create.js.erb file
#create.js.erb
$("<%= escape_javascript(render #article) %>").appendTo("#articles");
And a _article.html.erb to display the created articles.
<li><%= article.title %></li>

Create check box form from rendered members to send email - Ruby on Rails

I've got a team members page which pulls through the users associated with a university sports club, I'm trying to get it to produce a check box next to each member so that a member of the committee can simply select several members and on pressing a submit button the system will send an email to them.
I tried <%= check_box_tag(<%= render #users %>) %> but didn't have any luck
show_selection.html.rb - This is the page that renders the users
<% if signed_in? %>
<% if current_user.captain? %>
Welcome, select members to send a message to below
<table summary="Team members">
<tr>
<td class="main">
<% unless #users.empty? %>
<ul class="users">
<%= render #users %>
</ul>
<%= will_paginate #users %>
<% end %>
</td>
</tr>
</table>
<br>
<br>
<% else %>
<h1>An error has occured</h1>
<br>
<p>It looks like you're trying to access a restricted page <%= link_to "Please Click Here", '/' %> </p>
<% end %>
<% else %>
An error has occured
<br>
<p>It looks like you're trying to access a restricted page <%= link_to "Please Click Here", '/' %> </p>
<% end %>
users_contorller.rb
class UsersController < ApplicationController
before_filter :authenticate, :only => [:index, :edit, :update, :destroy]
before_filter :correct_user, :only => [:edit, :update]
before_filter :admin_user, :only => :destroy
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(:page => params[:page])
#title = #user.name
#admins = User.where(:admin => "t")
#captains = User.where(:captain => "t")
#clubs = User.where(:captain => "t")
end
def new
#user = User.new
#title = "Sign up"
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to University Sports!"
redirect_to #user
UserMailer.welcome_email(#user).deliver
else
#title = "Sign up"
render 'new'
end
end
def edit
#title = "Edit user"
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated."
redirect_to #user
else
#title = "Edit user"
render 'edit'
end
end
def index
#users = User.paginate(:page => params[:page])
end
#def admins
# #users = User.admins
# render "users/index"
#end
def admins
#admins=User.where(:admin => "t")
end
def captains
#captains=User.where(:captain => "t")
end
def clubs
#clubs=User.where(:captain => "t")
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to users_path
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.following.paginate(:page => params[:page])
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.paginate(:page => params[:page])
render 'show_follow'
end
def selection
#title = "Selection"
#user = User.find(params[:id])
#users = #user.followers.paginate(:page => params[:page])
render 'show_selection'
end
private
def authenticate
deny_access unless signed_in?
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
end
Firstly you will need to wrap this in a form to handle the submission of the selected members to email. The form should be posted to a mailer controller or an action to handle the selected members for emailing.
<%= render #users %>
This will render a partial for each of the objects inside #users. You should add the checkbox inside this partial in order to render it for each member.
You will have something like this in your partial
<%= check_box_tag "user_ids[]", user.id %>
Ryan has a railscast that will point you out the in right direction of how to implement. This is about updating the records, but you can modify the code to work with your scenario.
http://railscasts.com/episodes/52-update-through-checkboxes

User and associated Post

I created an twiiter like app, where friends can post, but i want a include the name of the person who created the post in the list showing all the post.
here is my code
class PostsController < ApplicationController
def index
#posts = Post.all(:order => "created_at DESC")
respond_to do |format|
format.html
end
end
def create
#post = Post.create(:message => params[:message])
respond_to do |format|
if #post.save
format.html { redirect_to posts_path }
format.js
else
flash[:notice] = "Message failed to save."
format.html { redirect_to posts_path }
end
end
end
end
`
Assuming, of course, that the 'user has many posts' association is set, and the user model has a 'username' field, you can do this in your view :
<% #posts.each do |post| %>
<%= post.user.username %>
<% end %>

Resources