So my simple question is, i want to call a mailer if particular column is updated in database with the form based on below controller. But i dont know how to take the column name ... I am doing like if #style.category after if #style.save but not working.
Controller
def new
#style = Style.new
#users = User.where('username <> ?', current_user.username)
respond_to do |format|
format.html # new.html.erb
format.json { render json: #style }
end
end
def create
#style = Style.new(params[:style])
#style.sender = current_user
respond_to do |format|
if #style.save,
### want to call mailer here , based on if column "category" is updated or not
if #style.receiver
format.html { redirect_to user_path(#style.receiver.username), notice: "successs!"}
else
format.html { redirect_to root_path, notice: 'Success!' }
end
add a after_save callback inside the model can help
class Style < ActiveRecord::Base
after_save :send_email
def send_email
if changed_attributes.has_key?('category')
call the mailer here
end
end
end
Related
I know that there are a lot of questions with the same error but i didn't find any that solves my problem. So, I have a "Bairro" and there are "Clientes" and "Imoveis" thats belongs to. The problem is that creating a customer "Cliente" works just fine, but when I go to create a "Imovel" I have the error:
undefined method `map' for nil:NilClass and highlight on:
<%= f.collection_select :bairro_id, #bairros, :id, :nome, {} , class: "form-control" %>
The Imovel.rb is like this:
class Imovel < ApplicationRecord
belongs_to :bairro
belongs_to :cliente
end
In the controller I have this:
def new
#imovel = Imovel.new
#bairros = Bairro.all
#clientes = Cliente.all
end
def edit
#bairros = Bairro.all
#clientes = Clientes.all
end
def update
#bairros = Bairro.all
respond_to do |format|
if #imovel.update(imovel_params)
format.html { redirect_to #imovel}
else
format.html { render :edit }
end
end
end
def create
#bairros = Bairro.all
#imovel = Imovel.new(imovel_params)
respond_to do |format|
if #imovel.save
format.html { redirect_to #imovel}
format.json { render :show, status: :created, location: #imovel }
else
format.html { render :new }
end
end
end
Usually this error happens when #bairros = Bairro.all is not defined, but not in this case.
The view opens just fine, I can edit to, but when I going to save, the error happens.
How can I solve this?
It is very likely that the error is because the form re-renders in your update action and you don't set #bairros there.
def update
if object.save
# works
else
# doesn't work
#bairros = Bairro.all # or something
render 'edit'
end
end
or if you re-render the form anyway you can just to
def create
#bairros = Bairro.all
if ....
In the index page i just filter the results by the projects_lkp_id.
def index
#filter = params[:projects_lkps_id] || ProjectsLkp.premitted_homes(current_user).first.id
#stock = Stock.where("projects_lkp_id = ?", #filter)
end
where projects_lkps_id has_many stocks
now my doubt is, when i create new stock how to bring this id to form? .
now my create method in controller is
def create
#stock = Stock.new(stock_params)
respond_to do |format|
if #stock.save
format.html{ redirect_to stocks_path(id: #stock.id), notice: "Item added to gallery" }
else
#stock = Stock.where(item: #stock.item).all
format.html { render 'index' }
end
end
end
stock_params is
params.require(:stocks).permit(:item,:unit,:projects_lkp_id)
If you have nested routes, like
resources :projects do
resources :stocks
end
Generated routes will be like -
project_stocks GET /projects/:project_id/stocks(.:format) stocks#index
POST /projects/:project_id/stocks(.:format) stocks#create
new_project_stock GET /projects/:project_id/stocks/new(.:format) stocks#new
edit_project_stock GET /projects/:project_id/stocks/:id/edit(.:format) stocks#edit
project_stock GET /projects/:project_id/stocks/:id(.:format) stocks#show
PATCH /projects/:project_id/stocks/:id(.:format) stocks#update
PUT /projects/:project_id/stocks/:id(.:format) stocks#update
DELETE /projects/:project_id/stocks/:id(.:format) stocks#destroy
Then you will have to have project_id in routes and you will be able to have project_id in controller, without having in form. Controller code will be like below
def create
#project = Project.find(params[:projects_id])
#stock = #project.stocks.new(stock_params)
respond_to do |format|
if #stock.save
format.html{ redirect_to projects_stocks_path(#project), notice: "Item added to gallery" }
else
#stock = Stock.where(item: #stock.item).all
format.html { render 'index' }
end
end
end
and stock_params will be -
params.require(:stocks).permit(:item,:unit)
I'm trying to send emails through my actionmailer to the commentable owners' email after another user writes them a comment but I keep getting an error. Can someone help me out with this? Thanks in advance.
comment_mailer.rb
def email_notification(member, comment)
#member = commentable.member
#sender = comment.member
mail to: commentable.member.email, subject: "#{comment.member.full_name} (#{comment.member.user_name}) has left you a comment"
end
comment.rb
belongs_to :member
belongs_to :commentable, polymorphic: true
attr_accessible :content
after_create :send_email
def send_email
CommentMailer.email_notification(member, comment).deliver
end
error
undefined local variable or method `comment' for #<Comment:0x51c2ad8>
app/models/comment.rb:18:in `send_email'
app/controllers/comments_controller.rb:20:in `block in create'
app/controllers/comments_controller.rb:19:in `create'
comments_controller
before_filter :authenticate_member!
before_filter :load_commentable
before_filter :find_member
def index
redirect_to root_path
end
def new
#comment = #commentable.comments.new
end
def create
#comment = #commentable.comments.new(params[:comment])
#comments = #commentable.comments.order('created_at desc').page(params[:page]).per_page(15)
#comment.member = current_member
respond_to do |format|
if #comment.save
format.html { redirect_to :back }
format.json
format.js
else
format.html { redirect_to :back }
format.json
format.js
end
end
end
def destroy
#comment = Comment.find(params[:id])
respond_to do |format|
if #comment.member == current_member || #commentable.member == current_member
#comment.destroy
format.html { redirect_to :back }
format.json
format.js
else
format.html { redirect_to :back, alert: 'You can\'t delete this comment.' }
format.json
format.js
end
end
end
private
def load_commentable
klass = [Status, Medium, Project, Event, Listing].detect { |c| params["#{c.name.underscore}_id"] }
#commentable = klass.find(params["#{klass.name.underscore}_id"])
end
def find_member
#member = Member.find_by_user_name(params[:user_name])
end
You error is in the send_email method. There is no local variable called comment. You are already inside an instance of comment, the instance you want to send an email about. So you want to use the keyword self instead.
Change this:
def send_email
CommentMailer.email_notification(member, comment).deliver
end
To this:
def send_email
CommentMailer.email_notification(member, self).deliver
end
self refers to the current instance of comment, which you want to use for your mailer.
I have just finished implementing ARRS, following R. Bates Railscasts #364.
I changed it to fit my app, so
a user votes on a movie in show view
Which is quite different to r. bates' one where
a user votes on a haiku in index view
And upon launching, the buttons look fine and they appear on the show view.
yet when i click on one this error appears
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Any ideas anyone?
Movies_controller.rb
class MoviesController < ApplicationController
# GET /movies
# GET /movies.json
def index
#search = Movie.search(params[:q])
#movies = Movie.all
end
# GET /movies/1
# GET /movies/1.json
def show
#movies = Movie.find_with_reputation(:votes, :all, order: 'votes desc')
#search = Movie.search(params[:q])
#movie = Movie.find(params[:id])
end
def search
#search = Movie.search(params[:q])
#movies = #search.result
respond_to do |format|
format.html # index.html.erb
format.json { render json: #movies }
end
end
# GET /movies/new
# GET /movies/new.json
def new
#search = Movie.search(params[:q])
#movie = Movie.new
end
# GET /movies/1/edit
def edit
#search = Movie.search(params[:q])
#movie = Movie.find(params[:id])
end
# POST /movies
# POST /movies.json
def create
#search = Movie.search(params[:q])
#movie = Movie.new(params[:movie])
respond_to do |format|
if #movie.save
format.html { redirect_to #movie, notice: 'Movie was successfully created.' }
format.json { render json: #movie, status: :created, location: #movie }
else
format.html { render action: "new" }
format.json { render json: #movie.errors, status: :unprocessable_entity }
end
end
end
# PUT /movies/1
# PUT /movies/1.json
def update
#search = Movie.search(params[:q])
#movie = Movie.find(params[:id])
respond_to do |format|
if #movie.update_attributes(params[:movie])
format.html { redirect_to #movie, notice: 'Movie was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #movie.errors, status: :unprocessable_entity }
end
end
end
# DELETE /movies/1
# DELETE /movies/1.json
def destroy
#movie = Movie.find(params[:id])
#movie.destroy
end
def vote
value = params[:type] == "up" ? 1 : -1
#movie = Movie.find(params[:id])
#movie.add_evaluation(:votes, value, current_user)
redirect_to :back, notice: "Thank you for voting!"
end
end
Movie.rb
has_reputation :votes, source: :user, aggregated_by: :sum
User.rb
has_reputation :votes, source: {reputation: :votes, of: :movies}, aggregated_by: :sum
show.html.erb //movies
<div class="ratings">
<em>
<%= pluralize #movie.reputation_for(:votes).to_i, "vote" %>
| <%= link_to "up", vote_movie_path(#movie, type: "up"), method: "post" %>
| <%= link_to "down", vote_movie_path(#movie, type: "down"), method: "post" %>
</em>
</div>
routes.rb
resources :movies do
member { post :vote }
end
def vote
value = params[:type] == "up" ? 1 : -1
#movie = Movie.find(params[:id])
#movie.add_evaluation(:votes, value, current_user)
redirect_to :back, notice: "Thank you for voting!"
end
the problem might be here:
add_evaluation(:votes, value, current_user)
requires current_userthat you don't have. Devise documentations says you need to include
before_filter :authenticate_user! in the conotroller to use the current_user helper.
Pay more attention to documentations when using a gem.
EIDT after chatting to solve this issue the acts_as_votable gem was used
https://github.com/ryanto/acts_as_votable instead of Active Record Reputation System
here the problem is in your add_evaluation line
change it to
'add_or_update_evaluation(:votes, value, current_user)'
this will add and also update the evaluation part.
Here i send the user.id as params dd
<h3><%= link_to("Lend Asset", {:controller => 'empassets', :action=> 'index', :dd => user.id})%></h3>
In controller empassets i fetch it by
def index
#id = params[:dd]
#empassets = Empasset.where(:ad => #id)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #empassets }
end
end
def show
#id = params[:dd]
#empasset = Empasset.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #empasset }
end
end
def new
#id = params[:dd]
#empasset = Empasset.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #empasset }
end
end
def edit
#id = params[:dd]
#empasset = Empasset.find(params[:id])
end
I need this #id in all new show edit method. But it takes in index only as i mention it in index. How can i make such that if Lend asset is click then #id= params[:id] have value in all methods. How can it is possible to make it available for another #id = params[:id] is not send in that controller?
Maybe will be better if you store the current user in session and after that, capture the user model with a filter in the controller, like this:
# controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_filter :set_current_user_in_model
private
def current_user
#current_user ||= User.find(params[:dd]) || User.new
end
# This method save the current user in the user model, this is useful to have access to the current user from a model and not from the controller only
def set_current_user_in_model
User.current_user current_user if not current_user.nil?
end
end
# models/user.rb
class User < ActiveRecord::Base
#...
# This is useful to get the current user inside a model
def self.current_user(user = nil)
##current_user = (user || ##current_user)
end
#...
end
Basically, my idea is store that information inside a model with a filter, you can use session if you wanth to get the information (user id).
def index
session[:user_id] = params[:dd]
#empassets = Empasset.where(:ad => session[:user_id])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #empassets }
end
end
def show
#empasset = Empasset.find(session[:user_id] || params[:dd])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #empasset }
end
end
Note I used session[:user_id] || params[:dd] because maybe, the session information was not stablished and you give it :dd parameter. But if you want to stablish the #id variable, you can use a filter like before.
But I don't know what is the main problem.
Edit
# controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_filter :set_dd_param, :except => :index
def index
session[:dd] = params[:dd] # Here you write the session
#current_user ||= User.find(params[:dd]) || User.new
end
# ...
protected
def set_dd_param
params[:dd] = session[:dd] || -1 # Here you read the session a write the params variable
end
end
Sorry for the delay.
Unless you want to store it to the session, there is no way to automatically make #id available to every method in the controller.. but you can add the param to each link/form, like so:
<%= link_to("New Asset", {:controller => 'empassets', :action=> 'new', :dd => #id})%>
<%= link_to("Show Asset", {:controller => 'empassets', :action=> 'show', :dd => #id})%>
where these links are in the index view and #id is set in the index method.
Not exactly sure what the goal is here, but something like this may work.
def index
$id = params[:dd]
#empassets = Empasset.where(:ad => #id)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #empassets }
end