Querying postgres database with rails - postgresql

I'm trying to search my database based on params from a search form. I had it working perfectly fine in SQLlite, but when I migrated to postgres, several things broke. in app/views/index.html.erb I defined a form:
<tr>
<%= form_tag(guidelines_path, :method => "get", id: "search-form") do %>
<td><%= label_tag(:invprogsearch, "Search by Investor and Program")%></td>
<td><%= text_field_tag :investor, nil, placeholder: "Enter investor" %></td>
<td><%= text_field_tag :program_code, nil, placeholder: "Enter program" %></td>
<td><%= submit_tag "Search", :name => nil %></td>
<% end %>
</tr>
and in my controller (app/controllers/guidelines_controller.rb) I defined the index action as such
def index
if params[:investor].present? && params[:program_code].present?
#guidelines = Guideline.where(investor: params[:investor], program: params[:program_code])
else
#guidelines = Guideline.all
end
end
Any idea why this wouldn't work? I'm out of ideas. Thanks!
app/models/guideline.rb:
class Guideline < ActiveRecord::Base
validates :guide_desc, presence: true
belongs_to :parent, class_name: 'Guideline'
has_many :children, class_name: 'Guideline', foreign_key: 'parent_id'
scope :top_level, where(:parent_id => nil)
def descendants
self_and_descendants - [self]
end
def self_and_descendants
self.class.tree_for(self)
end
def self.tree_for(instance)
where("#{table_name}.id IN (#{tree_sql_for(instance)})").order("#{table_name}.id")
end
def self.tree_sql_for(instance)
tree_sql = <<-SQL
WITH RECURSIVE search_tree(id, path) AS (
SELECT id, ARRAY[id]
FROM #{table_name}
WHERE id = #{instance.id}
UNION ALL
SELECT #{table_name}.id, path || #{table_name}.id
FROM search_tree
JOIN #{table_name} ON #{table_name}.parent_id = search_tree.id
WHERE NOT #{table_name}.id = ANY(path)
)
SELECT id FROM search_tree ORDER BY path
SQL
end
end

Related

cannot save data using a nested form with the cocoon gem

I am having trouble saving data using a nested form with the cocoon gem, and haven't been able to find a solution on SO.
I have two models: Requests has_many Votes.
I would like to create a single form that saves a new request, and a new vote simultaneously. The issue is that currently neither a new request nor a new vote is saved using the below code. I've pasted the terminal output below for completeness.
Terminal output:
Started POST "/requests" for ::1 at 2015-06-25 15:41:17 +0100
Processing by RequestsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"FCHcO1RLg2zr6mo8MpmVNMEasvPrAqyHAY5d2SdrlDUn83ppnsRhQUU33YiOZ84c4z1xMYQI4gzjLymN1NL3fw==", "request"=>{"firstname"=>"sdf", "lastname"=>"sf", "email"=>"sdf#lskdjf.com", "request"=>"lskdj", "description"=>"sldkjf", "votes_attributes"=>{"1435243272926"=>{"comment"=>"sadflkj", "email"=>"lkfj#sldk.com", "beta"=>"1", "_destroy"=>""}}}, "commit"=>"Save"}
(0.2ms) begin transaction
Vote Exists (0.2ms) SELECT 1 AS one FROM "votes" WHERE LOWER("votes"."email") = LOWER('lkfj#sldk.com') LIMIT 1
Request Exists (0.1ms) SELECT 1 AS one FROM "requests" WHERE LOWER("requests"."email") = LOWER('sdf#lskdjf.com') LIMIT 1
(0.1ms) rollback transaction
Rendered requests/_vote_fields.html.haml (0.9ms)
Rendered requests/_vote_fields.html.haml (1.0ms)
Rendered requests/_form.html.haml (8.4ms)
Rendered requests/new.html.erb within layouts/application (9.2ms)
Completed 200 OK in 118ms (Views: 105.8ms | ActiveRecord: 0.5ms)
Models:
class Request < ActiveRecord::Base
has_many :votes, dependent: :destroy
accepts_nested_attributes_for :votes
end
class Vote < ActiveRecord::Base
belongs_to :request
end
Requests controller
class RequestsController < ApplicationController
before_action :set_request, only: [:show, :edit, :update, :destroy]
def create
#request = Request.new(request_params)
if #request.save
redirect_to #request
else
render 'new'
end
end
private
def set_request
#request = Request.find(params[:id])
end
def request_params
params.require(:request).permit(
:id, :firstname, :lastname, :email, :request, :description, :votes, :tag_list,
votes_attributes: [:firstname, :lastname, :email, :comment, :beta, :id, :_destroy] )
end
end
requests/_form.html
= form_for(#request) do |f|
.field= f.text_field :firstname, placeholder: "Requester firstname"
.field= f.text_field :lastname, placeholder: "Requester Lastname"
.field= f.text_field :email, placeholder: "Email"
.field= f.text_field :request, placeholder: "Request"
.field= f.text_field :description, placeholder: "Description"
#votes
= f.fields_for :votes do |vote|
= render 'votes/vote_fields', :f => vote
.links
= link_to_add_association 'add vote', f, :votes, :render_options => { :wrapper => 'inline' }, partial: 'votes/vote_fields'
.action= f.submit "Save"
requests/_votes_fields.html.haml
.nested-fields
.form-inline
= f.text_field :comment, :placeholder => 'comment'
= f.text_field :email, :placeholder => 'email'
= f.check_box :beta, :placeholder => 'beta', :as => :boolean
.links
= link_to_remove_association "remove vote", f
votes and model validations:
vote.rb
belongs_to :request
before_save { self.email = email.downcase } #to ensure email uniqueness
validates :email, presence: true, length: { maximum: 250 }, uniqueness: { case_sensitive: false }
validates :request_id, presence: :true
request.rb
belongs_to :user
has_many :votes, dependent: :destroy
accepts_nested_attributes_for :votes
before_save { self.email = email.downcase }
validates :request, presence: true
validates :firstname, presence: true, length: { maximum: 50 }
validates :lastname, presence: true, length: { maximum: 50 }
validates :email, presence: true, length: { maximum: 250 }, uniqueness: { case_sensitive: false }
acts_as_taggable

Submitting follower by form

Getting strange error in rails when saving a follower:
Error on Page after submitting follower form
I execute all of the commands in the followers#create method in the rails console and it works. But for some reason when I execute the form on the page, it does not seem to save the user then I get this error on the page. Any ideas? Not sure if it's got something to do with my routes, so I'll post them as well.
Routes.rb:
TwitterApp::Application.routes.draw do
get "followers/show"
get "followers/new"
get "dashboard/new"
get "users/new"
get "users/edit"
get "sessions/new"
get "add_follower" => "followers#new", :as => "add_follower"
#get '/followers/:id', to: 'followers#show', as: 'followers'
get '/like/:id', to: 'followers#like', as: 'like'
get "log_out" => "sessions#destroy", :as => "log_out"
get "" => "sessions#new", :as => "log_in"
get "sign_up" => "users#new", :as => "sign_up"
get "settings" => "users#edit", :as => "settings"
get "dashboard" => "dashboard#new", :as => "dashboard"
root :to => "sessions#new"
resources :users
resources :sessions
resources :followers
end
Follower Form:
<%= #follower_to_save.inspect %>
<h3>Add Follower: </h3>
<%= form_for #follower do |f| %>
<% if #follower.errors.any? %>
<div class="error_messages">
<h2>Form is invalid</h2>
<ul>
<% for message in #user.errors.full_messages %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.text_field :follower_username, class: "form-control", autofocus: "", required: "", placeholder: "Twitter Username" %><br/>
<p class="button"><%= submit_tag "Add", class: "btn btn-lg btn-primary btn-block" %></p>
<% end %>
Follower Controller:
class FollowersController < ApplicationController
helper_method :logged_in?
def new
#follower = Follower.new
end
def create
Twitter.configure do |config|
# Test Account
config.consumer_key = "6xkis3S0lpGZD6uFuhaLQ"
config.consumer_secret = "pxxDbmipacThWNZYOYVphakXbXGa5IMY0k6CFoe0M"
config.oauth_token = "2182147123-5V5Wy6syh420U6M6SduBWScZXiPSfCrLmN9GtUi"
config.oauth_token_secret = "KgeKQEt8Tddq8xjSVZIQ65TW9m48GWJardgZA7zloGvDF"
# Personal Account
#config.consumer_key = "HwJH0RTuonm8Z01IwCr0pA"
#config.consumer_secret = "1INqGLyDucW6rIHKKqq2pBS9pHgoIwQTg8CYvBuXrjI"
#config.oauth_token = "82839887-bCld1xMgYKq9Bqe8ie4XhzcEevsOyNc7kJC3NOpOB"
#config.oauth_token_secret = "In3a5B1oRG2xoaQSqoCk7gJqsJTOnMegWZoAirZp0tPzj"
end
#user = User.find(session[:user_id])
#follower_to_save = Follower.new
follower = Twitter.user(params[:follower_username])
#follower_to_save.follower_id = follower[:id]
#follower_to_save.owner = #user.id
#follower_to_save.follower_username = follower[:screen_name]
#follower_to_save.follower_nationality = follower[:location]
#follower_to_save.no_of_followers = follower[:followers_count]
#follower_to_save.following= follower[:friends_count]
#follower_to_save.no_of_tweets = follower[:statuses_count]
#follower_to_save.profile_picture_url = follower[:profile_image_url]
#follower_to_save.updated_at = Time.now
if #follower_to_save.save
redirect_to "/dashboard", #just_updated => "Follower Added!"
else
render "new"
end
end
def like
follower = Follower.find(params[:id])
if follower.liked == false
follower.liked = true
else
follower.liked = false
end
follower.save
end
def show
#follower = params[:id]
Twitter.configure do |config|
# Test Account
#config.consumer_key = "6xkis3S0lpGZD6uFuhaLQ"
#config.consumer_secret = "pxxDbmipacThWNZYOYVphakXbXGa5IMY0k6CFoe0M"
#config.oauth_token = "2182147123-5V5Wy6syh420U6M6SduBWScZXiPSfCrLmN9GtUi"
#config.oauth_token_secret = "KgeKQEt8Tddq8xjSVZIQ65TW9m48GWJardgZA7zloGvDF"
# Personal Account
config.consumer_key = "HwJH0RTuonm8Z01IwCr0pA"
config.consumer_secret = "1INqGLyDucW6rIHKKqq2pBS9pHgoIwQTg8CYvBuXrjI"
config.oauth_token = "82839887-bCld1xMgYKq9Bqe8ie4XhzcEevsOyNc7kJC3NOpOB"
config.oauth_token_secret = "In3a5B1oRG2xoaQSqoCk7gJqsJTOnMegWZoAirZp0tPzj"
end
#follower_tweets = Twitter.user_timeline(#follower)
#follower_db_instance = Follower.find_by_follower_username(#follower)
#follower_profile_pic ||= Twitter.user(#follower)[:profile_image_url]
end
def logged_in?
if session[:user_id].present?
true
else
false
end
end
end
rename #follower_to_save to #follower in method create

Rails 4 + Devise 3.0 - Authenticate using username and email

I'm trying to allow users to sign in with either their username or their email address.
as per here: https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address
When ever I try to sign in with either the email or the login this is logged:
Started POST "/users/sign_in" for 192.168.2.8 at 2013-11-22 10:11:50 +0800
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"â", "authenticity_token"=>"WVTOKWQ8yJAJSu3NmXi3skJ8UC8zXY7qGZj7qbM3cr0=", "user"=>{"email"=>"testuser", "password"=>"password"}, "commit"=>"Sign in"}
User Load (3.3ms) SELECT "users".* FROM "users" WHERE "users"."email" = 'testuser' ORDER BY "users"."id" ASC LIMIT 1
Completed 401 Unauthorized in 20ms
Processing by Devise::SessionsController#new as HTML
Parameters: {"utf8"=>"â", "authenticity_token"=>"WVTOKWQ8yJAJSu3NmXi3skJ8UC8zXY7qGZj7qbM3cr0=", "user"=>{"email"=>"rtype", "password"=>"password"}, "commit"=>"Sign in"}
Rendered devise/sessions/new.html.erb within layouts/application (6.4ms)
Completed 200 OK in 80ms (Views: 62.6ms | ActiveRecord: 0.0ms)
its weird the sql isn't checking for the username, so maybe the call on the user is wrong, but its exactly from the devise documentation.
I have read the following:
Adding Username to devise rails 4
Logging in with username using Devise with Rails 4
I also reviewed the warden code and the devise code to try and discover if I'm overriding the wrong method in the user.
Any ideas why it is not authenticating with username, when it does with email?
ApplicationController.rb
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation) }
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password, :remember_me) }
# Need to add other user fields like gender etc.
devise_parameter_sanitizer.for(:account_update) {|u| u.permit(:email, :password, :password_confirmation, :current_password)}
end
end
User.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :confirmable, :encryptable, :recoverable, :rememberable, :trackable, :validatable
attr_accessor :login # This is used to add the login for allowing user to sign in with both email or username
# Validations
validates :username, presence: true, length: {maximum: 255}, uniqueness: { case_sensitive: false }, format: { with: /\A[a-zA-Z0-9]*\z/, message: "may only contain letters and numbers." }
# Overwrite devise’s find_for_database_authentication method in user model
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:username)
where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions).first
end
end
end
new.html
<fieldset>
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => 'form-horizontal' }) do |f| %>
<div class="control-group">
<%= f.label :login, "Email or Username" %>
<div class="controls"><%= f.text_field :login, :autofocus => true %></div>
</div>
<div class="control-group">
<%= f.label :password %>
<div class="controls"><%= f.password_field :password %></div>
</div>
<div class="form-actions">
<%= f.submit "Sign in", :class => "btn btn-primary", data: { disable_with: 'Working...' } %> <%= link_to "Forgot password?", new_password_path(resource_name), :class => "btn" %>
</div>
<% end %>
</fieldset>
Devise.rb
config.secret_key = 'Omitted for security'
config.mailer_sender = 'Omitted for security'
config.case_insensitive_keys = [ :email ]
config.strip_whitespace_keys = [ :email ]
config.skip_session_storage = [:http_auth]
config.stretches = Rails.env.test? ? 1 : 10
config.reconfirmable = true
config.password_length = 8..128
config.reset_password_within = 6.hours
config.encryptor = :sha512
config.sign_out_via = :delete
You need to add
config.authentication_keys = [ :login ]
within devise.rb
Also if you want to use login as reset password or confirmation keys you should also add within the same file:
config.reset_password_keys = [ :login ]
config.confirmation_keys = [ :login ]
You also need to whitelist the login parameter within your application_controller. In the new.html view you have a login form, so you must accept the login parameter for the sign_in instead of the username and email parameters.
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:login, :password, :remember_me) }

Call method after submitting form Rails

I have the following model:
class Coupon < ActiveRecord::Base
belongs_to :company
validates :description, presence: true, length: { maximum: 50 }, uniqueness: { case_sensitive: false }
validates :fine_print, presence: true
end
and the following method in the coupon controller:
def redeem
if params[:pin] == #coupon.company.pin
redirect_to root_path
else
flash.now[:notice] = "Incorrect Pin"
render :show
end
end
This form is in the a view:
<%= form_for( #coupon, :url => coupons_redeem_path( #coupon ), :html => { :method => :post } ) do |f| %>
<%= label_tag("pin", "Search for:") %>
<%= text_field_tag("pin") %>
<%= f.submit "Close Message" %>
<% end %>
I want the form to call the redeem method in the coupons controller when hitting submit but am getting this error:
No route matches [POST] "/coupons/redeem.1"
EDIT
These are my routes:
resources :companies do
resources :coupons
end
get 'coupons/redeem'
In your routes, coupons are nested resources of companies. So you should choose one of these alternatives:
1st:
resources :companies do
resources :coupons do
post :redeem, on: :member
end
end
This leads to helpers like this: redeem_company_coupon_path(company, coupon) (and send smth there via POST).
If you don't want to include company to your path, you could choose 2nd:
resources :companies do
resources :coupons
end
post 'coupons/:id/redeem', to: 'coupons#redeem', as: :redeem_coupon
After that you could use redeem_coupon_path(coupon) helper

Save the file manually using paperclip from the params, without scaffold

I am new to rails, I was working on paperclip gem and wanted to save the simple files, saved from paperclip.
I have the My model as follow :-
class UserAttachment < ActiveRecord::Base
attr_accessible :email, :user_id, :attached_file
has_attached_file :attached_file
validates_attachment_presence :attached_file
validates_attachment_size :attached_file, :less_than => 20.megabytes
end
My controller action where the form is called :-
class HomeController < ApplicationController
def index
#uattachment = UserAttachment.new
end
end
Index view code, where the form is located
<%= form_for #uattachment, :url => attachment_get_link_path, :html => { :method => :post, :id => 'attachment_form', :multipart => true }, :remote => true do |f| %>
<%= f.email_field :email, :value=>nil, :placeholder => "Enter your email here", :required => true %><br />
<%= f.file_field :attached_file %>
<%= f.submit "Submit" %>
<% end %>
I want to use some following kind of code to save the data :-
(Code below is not the correct code, it's an excitation to tell what I want to do in my application.)
#uattachment = UserAttachment.new
#uattachment = params[:user_attachment]
#uattachment.save
Params received are as follows :-
(rdb:6) pp params
{"utf8"=>"✓",
"authenticity_token"=>"dfjaskldjadslgjsoidruts48589034lsker=",
"user_attachment"=>
{"email"=>"testing#email.com",
"attached_file"=>
#<ActionDispatch::Http::UploadedFile:0x007fcb58682ba0
#content_type="image/jpeg",
#headers=
"Content-Disposition: form-data; name=\"user_attachment[attached_file]\"; filename=\"someimage.jpg\"\r\nContent-Type: image/jpeg\r\n",
#original_filename="800px-Kinnaur_Kailash.jpg",
#tempfile=#<File:/tmp/RackMultipart20121205-8432-1fc1kpi>>},
"commit"=>"Submit",
"controller"=>"attachment",
"action"=>"get_link"}
Got the catch, it was pretty simple, I checked it from the scaffolded assignment,
def index
#uattachment = UserAttachment.new(params[:user_attachment])
#uattachment.save
end
And you get the golden words in response "true".