So I'm trying to send a contact us form into dropbox, so the goal is for a user to create a lead (contact us form) with an upload_file field (attachment) and then I'm going to ask that user if he wants to become a customer irl, so if he becomes one, I want that attachment in his lead (contact us form related to him) to go into my dropbox.
so here is my contact us controller:
class LeadsController < ApplicationController
require 'dropbox_api'
skip_before_action :verify_authenticity_token
def create
#lead = Lead.new
fullname = params['Name']
company = params['Company']
email = params['Email']
phone = params['Phone']
projectName = params['ProjectName']
projectDescription = params['ProjectDescription']
department_incharge = params['DepartmentInCharge']
message = params['Message']
attachment = params['attachment']
#lead.full_name = fullname
#lead.company_name = company
#lead.email = email
#lead.phone = phone
#lead.project_name = projectName
#lead.project_description = projectDescription
#lead.department_in_charge = department_incharge
#lead.message = message
params_attach = attachment
if params_attach
#lead.attachment = params_attach.read
#lead.original_filename = params_attach.original_filename
client = DropboxApi::Client.new(ENV['DROPBOX_OAUTH_BEARER'])
#lead.save!
redirect_to root_path
end
end
end
here is my customer model:
class Customer < ApplicationRecord
has_many :lead
has_many :buildings
belongs_to :address
belongs_to :user
after_update :dropbox
self.all.each do |lead|
def dropbox
self.lead.all.each do |lead|
if lead.attachment != nil
client = DropboxApi::Client.new(ENV['DROPBOX_OAUTH_BEARER'])
client.create_folder("/#{lead.full_name}")
client.upload("/#{lead.full_name}/#{File.basename(lead.original_filename)}", lead.attachment)
# lead.file_attachment = nil
# lead.original_filename = nil
# lead.save!
end
end
end
end
end
The problem is when i hit the send button to confirm my quote, it just refreshes the page (it's supposed to go to a confirmation page) and in the ubuntu console, this appears:
No template found for LeadsController#create, rendering head :no_content
Completed 204 No Content in 795ms (ActiveRecord: 0.0ms)
Tell me if you need any more information, I'm really stuck on that one
Try this, move redirect_to out of if, add flash message to make it more clear, I suspect params_attach is false/nil in this case
if params_attach
#lead.attachment = params_attach.read
#lead.original_filename = params_attach.original_filename
client = DropboxApi::Client.new(ENV['DROPBOX_OAUTH_BEARER'])
#lead.save!
end
redirect_to root_path
Hope that helps!
Related
I've followed multiple stack overflow posts regarding this same issue, but I don't think I have the rails proficiency to know how to apply these fixes to my code.
Been following an old railscast show: http://railscasts.com/episodes/217-multistep-forms
And I'm aware that the issue is something to do with permitting objects/hashes but I just don't understand it all.
The error I'm getting is from this line of code in my controller:
session[:zerch_params].deep_merge!(params[:zerch]) if params[:zerch]
Controller
class ZerchesController < InheritedResources::Base
def index
#zerches = Zerch.all
end
def show
#zerch = Zerch.find(params[:id])
end
def new
session[:zerch_params] ||= {}
#zerch = Zerch.new(session[:zerch_params])
#zerch.current_step = session[:zerch_step]
end
def create
session[:zerch_params].deep_merge!(params[:zerch]) if params[:zerch]
#zerch = Zerch.new(session[:zerch_params])
#zerch.current_step = session[:zerch_step]
if #zerch.valid?
if params[:back_button]
#zerch.previous_step
elsif #zerch.last_step?
#zerch.save if #zerch.all_valid?
else
#zerch.next_step
end
session[:zerch_step] = #zerch.current_step
end
if #zerch.new_record?
render "new"
else
session[:zerch_step] = session[:zerch_params] = nil
flash[:notice] = "zerch complete!"
redirect_to #zerch
end
end
private
def zerch_params
params.require(:zerch).permit(:location, :category, :price)
end
end
So I was able to solve this from the model and in the controller:
I still had
attr_accessor
while also having params in private. I removed this, and also in the controller I changed the line of code from this:
session[:zerch_params].deep_merge!(params[:zerch]) if params[:zerch]
to this:
session[:zerch_params].deep_merge!(params.permit![:zerch]) if params[:zerch]
I'm builing a weight loss app. For this in my app each user has_one :profile and has_many :weights. Each profile belongs_to :pal. For my app to work I need a value called SMR which basically is a formula that takes as variables the user's size, age and gender (all from profiles table), the user's current weight (from weights table) as well as a float number from pal table.
I am able to calculate SMR in profiles_controller.rb show action and show it in the profiles show.html.erb.
I have two questions now:
Is it correct to do this calculation in the profiles_controller.rb show action or should I do it in the profile.rb model? If I should do it in the model: how can I do it (how should the code look like)?
I will need the SMR value later on in my app as a variable for other calculations as well. How can I achieve this (if it is calculated in the profile controller/model but needed somewhere else later on)?
I'm fairly new to the Rails world so maybe my questions are really noob questions.
profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
belongs_to :pal
belongs_to :goal
def age
if birthdate != nil
now = Time.now.utc.to_date
now.year - birthdate.year - (birthdate.to_date.change(:year => now.year) > now ? 1 : 0)
else
nil
end
end
end
weight.rb
class Weight < ActiveRecord::Base
belongs_to :user
end
pal.rb
class Pal < ActiveRecord::Base
has_many :profiles
end
profiles_controller.rb (show action only)
def show
#pal = #profile.pal
#goal = #profile.goal
#current_weight = Weight.where(:user_id => current_user.id).order(:day).last
if #profile.gender == 0
#smr = (10*#current_weight.kilograms+6.25*#profile.size-5*#profile.age+5)*#pal.value
elsif #profile.gender == 1
#smr = (10*#current_weight.kilograms+6.25*#profile.size-5*#profile.age-161)*#pal.value
else
nil
end
end
I think you should create a separate class or you can do on profile model as well
class SmrCalculator
def initialize(profile, user)
#profile = profile
#user = user
end
def get_smr
#pal = #profile.pal
#goal = #profile.goal
#current_weight = Weight.where(:user_id => #user.id).order(:day).last
if #profile.gender == 0
#smr = (10*#current_weight.kilograms+6.25*#profile.size-5*#profile.age+5)*#pal.value
elsif #profile.gender == 1
#smr = (10*#current_weight.kilograms+6.25*#profile.size-5*#profile.age-161)*#pal.value
else
nil
end
#smr
end
end
And call this class on your controller show method like this:
#smr_calculator = SmrCalculator.new(#profile, current_user)
#smr = #smr_calculator.get_smr
And add this class as smr_calculator.rb in models folder
so anywhere in the app you need #smr you can call this class with profile and current user
You can create a services directory inside app folder.And inside that you can create your class as CalculatorService.
Example:
class CalculatorService
def initialize(profile, user)
#profile = profile
#user = user
end
def smr_value
#pal = #profile.pal
#goal = #profile.goal
#current_weight = Weight.users_weight(#user.id)
#smr = if #profile.gender == 0
(10*#current_weight.kilograms + 6.25*#profile.size-5*#profile.age+5)*#pal.value
elsif #profile.gender == 1
(10*#current_weight.kilograms + 6.25*#profile.size-5*#profile.age-161)*#pal.value
else
nil
end
#smr
end
end
class Weight < ActiveRecord::Base
scope :users_weight, ->(user_id) { where(:user_id => user_id).order(:day).last}
end
And call this service in your controller like this:
#smr_calculator = CalculatorService.new(#profile, current_user)
#smr = #smr_calculator.smr_value
First, sorry for my English, I am totally new in ruby on rails even in very basic thing, so I hope you all can help me.
I have table Role and RoleUser
table Role have has_many relationship to RoleUser with role_id as foreign key
in table RoleUser is contain user_id, so I can call it 1 role have many users
and I want is to show all record in Role with additional field in every record called total_users,
total_users is in every record have role_id and count the user_id for every role, and put it in total_users,
I know this is must use the join table, but in rails I absolutely knew nothing about that, can you all give me a simple example how to do that.
and one more, same with case above, can I do for example Role.all and then the total_users in include in that without added it in database? is that use virtual column?
anyone have a good source of link to learn of that
I have following code in model
def with_filtering(params, holding_company_id)
order = []
if params[:sort].present?
JSON.parse(params[:sort]).each do |data|
order << "#{data['property']} #{data['direction']}"
end
end
order = 'id ASC' if order.blank?
if self.column_names.include? "holding_company_id"
string_conditions = ["holding_company_id = :holding_company_id"]
placeholder_conditions = { holding_company_id: holding_company_id.id }
else
string_conditions = []
placeholder_conditions = {}
end
if params[:filter].present?
JSON.parse(params[:filter]).each do |filter|
if filter['operation'] == 'between'
string_conditions << "#{filter['property']} >= :start_#{filter['property']} AND #{filter['property']} <= :end_#{filter['property']}"
placeholder_conditions["start_#{filter['property']}".to_sym] = filter['value1']
placeholder_conditions["end_#{filter['property']}".to_sym] = filter['value2']
elsif filter['operation'] == 'like'
string_conditions << "#{filter['property']} ilike :#{filter['property']}"
placeholder_conditions["#{filter['property']}".to_sym] = "%#{filter['value1']}%"
else
string_conditions << "#{filter['property']} = :#{filter['property']}"
placeholder_conditions["#{filter['property']}".to_sym] = filter['value1']
end
end
end
conditions = [string_conditions.join(' AND '), placeholder_conditions]
total_count = where(conditions).count
if params[:limit].blank? && params[:offset].blank?
data = where(conditions).order(order)
else
data = where(conditions).limit(params[:limit].to_i).offset(params[:offset].to_i).order(order)
end
return data, total_count.to_s
end
And I have follwing code in controllers
def crud_index(model)
data, total = Role.with_filtering(params, current_holding_company)
respond_to do |format|
format.json { render json: { data: data, total_count: total }.to_json, status: 200 }
end
end
My only purpose is to add virtual field called total_users, but i want added it in model and combine it with data in method with_filtering
If you have the models like this:
Class Role < ActiveRecord::Base
has_many :role_users
end
Class RoleUser < ActiveRecord::Base
belong_to :role
end
You could use select and joins to generate summary columns, but all the Role's attributes should be include in group.
roles = Role.select("roles.*, count(role_users.id) as total_users")
.joins(:role_users)
.group("roles.id")
Type those scripts in Rails console, Rails will generate a sql like :
SELECT roles.id, count(role_users.id) as total_users
FROM roles
INNER JOIN role_users
ON roles.id = role_users.role_id
GROUP BY roles.id
Then you can use roles.to_json to see the result. The summary column total_users can be accessed in every member of roles.
And there are many other way can match your requirement. Such as this. There is a reference of counter cache.
My suggestion is after searching, you can test those method by rails console, it's a useful tool.
UPDATE
According to OP's update and comment, seems you have more works to do.
STEP1: move with_filtering class method to controller
with_filtering handle a lot of parameter things to get conditions, it should be handled in controller instead of model. So we can transfer with_filtering into conditions and orders in controller.
class RolesController < ApplicationController
def conditions(params, holding_company_id)
if self.column_names.include? "holding_company_id"
string_conditions = ["holding_company_id = :holding_company_id"]
placeholder_conditions = { holding_company_id: holding_company_id.id }
else
string_conditions = []
placeholder_conditions = {}
end
if params[:filter].present?
JSON.parse(params[:filter]).each do |filter|
if filter['operation'] == 'between'
string_conditions << "#{filter['property']} >= :start_#{filter['property']} AND #{filter['property']} <= :end_#{filter['property']}"
placeholder_conditions["start_#{filter['property']}".to_sym] = filter['value1']
placeholder_conditions["end_#{filter['property']}".to_sym] = filter['value2']
elsif filter['operation'] == 'like'
string_conditions << "#{filter['property']} ilike :#{filter['property']}"
placeholder_conditions["#{filter['property']}".to_sym] = "%#{filter['value1']}%"
else
string_conditions << "#{filter['property']} = :#{filter['property']}"
placeholder_conditions["#{filter['property']}".to_sym] = filter['value1']
end
end
end
return [string_conditions.join(' AND '), placeholder_conditions]
end
def orders(params)
ord = []
if params[:sort].present?
JSON.parse(params[:sort]).each do |data|
ord << "#{data['property']} #{data['direction']}"
end
end
ord = 'id ASC' if ord.blank?
return ord
end
end
STEP2: update action crud_index with conditions and orders to get total_count of Roles.
class AnswersController < ApplicationController
def crud_index(model)
total = Role.where(conditions(params, current_holding_company)).count
if params[:limit].blank? && params[:offset].blank?
data = Role.where(conditions(params, current_holding_company)).order(orders(params))
else
data = Role.where(conditions(params, current_holding_company)).limit(params[:limit].to_i).offset(params[:offset].to_i).order(orders(params))
end
respond_to do |format|
format.json { render json: { data: data, total_count: total }.to_json, status: 200 }
end
end
end
STEP3: update action crud_index to get total_users by every role.
Make sure the two previous steps is pass the test.
class AnswersController < ApplicationController
def crud_index(model)
total = Role.where(conditions(params, current_holding_company)).count
if params[:limit].blank? && params[:offset].blank?
data =
Role.select(Role.column_names.map{|x| "Roles.#{x}"}.join(",") + " ,count(role_users.id) as total_users")
.joins(:role_users)
.group(Role.column_names.map{|x| "Roles.#{x}"}.join(","))
.where(conditions(params, current_holding_company))
.order(orders(params))
else
data =
Role.select(Role.column_names.map{|x| "Roles.#{x}"}.join(",") + " ,count(role_users.id) as total_users")
.joins(:role_users)
.group(Role.column_names.map{|x| "Roles.#{x}"}.join(","))
.where(conditions(params, current_holding_company))
.order(orders(params))
.limit(params[:limit].to_i)
.offset(params[:offset].to_i).order(orders(params))
end
respond_to do |format|
format.json { render json: { data: data, total_count: total }.to_json, status: 200 }
end
end
end
NOTE: step3 may need you to modify conditions and orders method to generate column_name with table_name prefix to avoid column name ambiguous error
If you can make these steps through, I suggest you can try will_paginate to simplify the part of your code about total_count ,limit and offset.
With what you explained, you could do something like this:
class Role < ActiveRecord::Base
has_many :role_users
has_many :users
def total_users
self.users.count
end
end
So you just need to call the total_users method on roles object which should get you what you desire. Something like this:
Role.first.total_users
# this will give you the total users for the first role found in your database.
Hope it helps
You might want to watch this Railscast too:
#app/models/role.rb
Class Role < ActiveRecord::Base
has_many :role_users
has_many :users, -> { select "users.*", "role_users.*", "count(role_users.user_id) as total_users" }, through: :role_users
end
This will allow you to call:
#roles = Role.find params[:id]
#roles.users.each do |role|
role.total_users
end
You can see more about how this works with a question I wrote some time ago - Using Delegate With has_many In Rails?
--
It's where I learnt about Alias columns, which Ryan Bates uses to count certain values:
I have this action in my rails controler,
def step_submit
validate_user()
#owning = #user.create_user_car_transaction(Variant.find(params[:variant]), params[:details], params[:address], params[:somethin1])
Contact.user_contact(current_user, params[:contact]) if #user.contact.nil?
redirect_to "/next_step"
end
I use codeClimate to check the quality of the code..
it shows this action's complexity ~ 30 ..
I actually broke a really huge method into this.. how can i still reduce this complexity?
these are the different methods the action calls
def self.user_contact(user, contact_hash = nil)
contact = user.contact || user.create_contact()
contact.update_attributes(contact_hash) if contact_hash.present?
contact
end
def validate_user
if params[:user] && current_user.nil?
user = User.create(params[:user])
sign_in user
end
end
def create_user_car_transaction(car, details_hash, address_hash, coupon_hash = nil)
transaction = self.transactions.create()
car.transaction_item = transaction.transaction_items.create()
car.save
payment_hash = details_hash
payment_hash.merge!(address_hash)
payment = transaction.create_payment(payment_hash)
transaction.update_attributes(:status=>"1") if transaction.status.nil?
transaction
end
I'm trying to save the url params from ever page, into a session, so if someone fills out a form after navigating away from their landing page it keeps the campaign id. I've managed to make it work page by page, so if they land on the form with params it keeps it, but if they navigate away obviously it doesn't. I currently have:
Controller:
def campaign
if params[:campaign]!= nil
session[:campaign] = params[:campaign]
end
end
def post
rif = Registerinterest.find(:all, :conditions => ["reference = ?", session[:campaign]])
if rif.count == 0
post["Campaign_ID"] = "701D00000001111"
else
post["Campaign_ID"] = rif.first.campaign_id
end
end
It worked when i used params, but not session, so i'm assuming i'm not saving it properly?
You could add a before filter in controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_filter persist_campaign_session
def persist_campaign_session
session[:campaign] ||= params[:campaign]
end
end
If session[:campaign] is set it will be used, otherwise params[:campaign]will be used. You should implement
the reset of session[:campaign] at a good place.
I put this in my application layout:
- if params[:campaign] != nil || params[:campaign] != ""
- session[:campaign] == params[:campaign]
and then that made the controller work properly:
def post
rif = Registerinterest.find(:all, :conditions => ["reference = ?", session[:campaign]])
if rif.count == 0
post["Campaign_ID"] = "701D00000001111"
else
post["Campaign_ID"] = rif.first.campaign_id
end
end