I am trying to implement a chat feature in my rails app deployed on heroku . For this I have created two rails apps one my original app and the other to acts as faye server.
I have given the faye app url in my original app to create faye server object.
Following is what I have added in my original app:
Ruby version: 2.0.0
gemfile
gem 'thin'
gem 'faye'
gem 'rails', '4.1.5'
Application.rb
<%= javascript_include_tag 'http://xxx.herokuapp.com/faye.js' %>
Application.js
$(function(){
$(document).foundation();
var faye = new Faye.Client('http://xxx.herokuapp.com/faye');
faye.subscribe("/messages/new", function(data) {
eval(data);
});
});
Message Helper
def broadcast(channel, &block)
message = {:channel => channel, :data => capture(&block)}
uri = URI.parse("http://xxx.herokuapp.com/faye")
Net::HTTP.post_form(uri, :message => message.to_json)
end
Message Controller
class MessagesController < ApplicationController
def index
#messages = Message.all
end
def create
#message = Message.create!(message_params)
end
private
def message_params
params.require(:message).permit(:content)
end
end
My View:
messages/create.js.erb
<% broadcast "/messages/new" do %>
$("#chat").append("<%= escape_javascript render(#message) %>");
<% end %>
$("#new_message")[0].reset();
/messages/index.html.erb
<ul id="chat">
<%= render #messages %>
</ul>
<%= form_for Message.new, :remote => true do |f| %>
<%= f.text_field :content %>
<%= f.submit "Send" %>
<% end %>
Follwing is what I added in my faye server app:
faye.ru
require 'faye'
Faye::WebSocket.load_adapter('thin')
app = Faye::RackAdapter.new(:mount => '/faye', :timeout => 25)
run app
Procfile
web: bundle exec thin -p $PORT -e $RACK_ENV -R faye.ru start
I am getting a 500 internal sever error whenever I try to send a message. The code is working fine on local. Also I am getting Error during WebSocket handshake: Unexpected response code: 404 in chrome. I tried enabling cors but that did not helped either.
Note: Below are some reference links which are not working for me
Using rails sync gem with Faye and Thin in production mode on Heroku
https://blog.heroku.com/archives/2013/10/8/websockets-public-beta
This is not working heroku labs:enable websockets
I am new for heroku and faye.
Related
I've removed turbolinks from my Rails 6.0.0 beta web application using Ruby 2.6.1 and upon doing so, whenever I update or create a chapter, a POST request will get sent to the database. But while the database will save the data, it will also try to redirect the page, but the browser does not redirect to anywhere and will still display the edit/new page.
This was not an issue before removing turbolinks. I have tried searching around but could not find any solution to this so far. I tried restarting the server and of course using bundle update beforehand to actually remove turbolinks.
Chapter Controller
def update
#book = Book.find(params[:book_id])
#chapter = #book.chapters.find(params[:id])
if #chapter.update(chapter_params)
redirect_to book_chapter_path(#book, #chapter)
else
...
end
end
...
private
def chapter_params
params.require(:chapter).permit(:title, :content, :status)
end
chapters > edit.html.erb
<%= form_with model: #chapter, url: { action: "update" } do |form| %>
...
<%= form.submit "Draft", class: "save-btn" %>
...
<% end %>
routes.rb
resources :books do
resources :chapters
end
Normally I expect this output from the server logs after it's POST request to update/create the chapter in the database...
Started GET "/books/1/chapters/1" for 127.0.0.1 at 2019-02-17 12:52:29 +1030
Processing by ChaptersController#show as HTML
But instead, it says
Started GET "/books/1/chapters/1" for 127.0.0.1 at 2019-02-17 12:52:29 +1030
Processing by ChaptersController#show as JS
I think I understand why this is happening, but again, I don't know how to solve it.
Default of form_with is Ajax(remote).
https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with
You should add local: true.
<%= form_with model: #chapter, url: { action: "update" }, local: true do |form| %>
I'm writing a rails application with which a user can upload images. I am deploying with Heroku, and using Carrierwave and S3 to upload and store images. I have followed this heroku guide step-by-step...unfortunately I am still getting an error "undefined method `presigned_post'", and do not know how to resolve it. It seems the S3_BUCKET is not being recognized as an aws object...
Has anyone come across this problem and figured it out? Here's some code for reference:
Pictures controller:
class PicturesController < ApplicationController
before_action :set_s3_direct_post, only: [:new, :create]
def index
#pictures = Picture.all
end
def new
#pictures = Picture.all
#picture = Picture.new
end
def create
#picture = Picture.new(picture_params)
if #picture.save
redirect_to new_picture_path, notice: "You just uploaded a picture!"
else
render "new"
end
end
...
def picture_params
params.require(:picture).permit(:attachment)
end
private
def set_s3_direct_post
#s3_direct_post = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: '201', acl: 'public-read')
end
end
New picture view:
<h1>Upload a new picture</h1>
<br>
<div class="well">
<%= form_for #picture, html: { class: 'directUpload', data: { 'form-data' => (#s3_direct_post.fields), 'url' => #s3_direct_post.url, 'host' => URI.parse(#s3_direct_post.url).host } } do |f| %>
<%= f.file_field :attachment %>
<%= f.submit "Upload", class: "btn btn-default" %>
<% end %>
</div>
And config/environment.rb:
require File.expand_path('../application', __FILE__)
# Initialize the Rails application.
Rails.application.initialize!
# S3
S3_BUCKET='fotoes'
AWS_ACCESS_KEY_ID='secretxxxxxxxx'
AWS_SECRET_ACCESS_KEY='xxxxxxxsecretxxxxxx'
Any thoughts?
#Jillian I suppose your expectation was that S3_BUCKET class should call presigned_post method which is supposed to be defined. However, it seems its not. I took a look at the heroku page containing the tutorial you followed and well you followed every instruction. I suggest you contact heroku about the documentation. However, I would keep looking into it
Thank you all for your help. In the end I found a different walk-through that was much simpler and effective. (The Heroku one was a little complicated and left a lot to go wrong - go figure.)
This solved everything :)
edit:
not everything - had to complete one last step before I got the site running. Run this line in the terminal: $ heroku config:add AWS_ACCESS_KEY=value
and $ heroku config:add AWS_SECRET_KEY=value, where the value is your S3 credentials for each, respectively.
This was the only combo of fog, carrierwave, rails, fog-aws gems that worked (after weeks of fussing with them):
gem 'rails', '4.1.0'
gem 'carrierwave', '~> 0.10.0'
gem 'fog', '1.34.0'
gem 'fog-aws', '0.7.6'
i resolved this by updating my version of aws-sdk
$ bundle update aws-sdk
I recently added the paperclip gem to my web app. I then added aws-sdk so that i can upload images on the production version of my app, which is on heroku. After configuring everything and trying to upload an image, i got the standard rails error page, and went to the log:
NameError (uninitialized constant Paperclip::Storage::S3::AWS):
app/controllers/pins_controller.rb:23:in `create'
I searched online and found out that this was a problem with the version-2 of aws-sdk, and that i had to downgrade the gem. So i downgraded the gem so that it uses version-1, then ran bundle install, commited my changes with git, and pushed it to heroku.
This time, when i tried to attach a photo to a pin, i got a different error. This led me to believe that the previous error was fixed and that i now have a different problem. Here is the error:
NoMethodError (undefined method `first' for nil:NilClass):
app/controllers/pins_controller.rb:23:in `create'
I did lots of research, and have not been able to find out what's going wrong. I'm a beginner with rails and i'm learning it by making a web app similar to pinterest, where i can allows users to make accounts and post pins, and i'm using devise to do this. I added paperclip so that i can enable image posting, and aws-sdk so that i can use amazon S3 for storing photos due to the fact that my production evironment is on heroku, and heroku can't store images. I will paste in some more helpful code:
Controller(app/controllers/pins_controller.rb): This is the controller file which is mentioned in the error log. The error is on line 23, like it says on the log. Line 23 is the line in the "create" action that says: if #pin.save
class PinsController < ApplicationController
before_action :set_pin, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#pins = Pin.all
end
def show
end
def new
#pin = current_user.pins.build
end
def edit
end
def create
#pin = current_user.pins.build(pin_params)
if #pin.save
redirect_to #pin, notice: 'Pin was successfully added.'
else
render :new
end
end
def update
if #pin.update(pin_params)
redirect_to #pin, notice: 'Pin was successfully edited.'
else
render :edit
end
end
def destroy
#pin.destroy
redirect_to pins_url, notice: 'Pin was successfully deleted.'
end
private
def set_pin
#pin = Pin.find(params[:id])
end
def correct_user
#pin = current_user.pins.find_by(id: params[:id])
redirect_to pins_path, notice: "You are not permitted to edit this pin" if #pin.nil?
end
def pin_params
params.require(:pin).permit(:description, :image)
end
end
Model(app/models/pin.rb): This is the model for the pins(which are basically posts)
class Pin < ActiveRecord::Base
belongs_to :user
has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
end
Config(config/environments/production.rb): This is the production file where i added the aws configuration variables
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Enable Rack::Cache to put a simple HTTP cache in front of your application
# Add `rack-cache` to your Gemfile before enabling this.
# For large-scale production use, consider using a caching reverse proxy like
# NGINX, varnish or squid.
# config.action_dispatch.rack_cache = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.
config.log_level = :debug
# Prepend all log lines with the following tags.
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups.
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
end
Form(app/views/pins/_form.html.erb): This is the form which is used to submit pins
<%= form_for #pin, html: { multipart: true } do |f| %>
<% if #pin.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#pin.errors.count, "error") %> prohibited this pin from being saved:</h2>
<ul>
<% #pin.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :image %><br>
<%= f.file_field :image, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :description %><br>
<%= f.text_field :description, class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit class: "btn btn-primary" %>
</div>
<% end %>
Migration(db/migrate/20150902154233_add_attachment_image_to_pins.rb): This is the migration i did so that i can attach photos to my pins
class AddAttachmentImageToPins < ActiveRecord::Migration
def self.up
change_table :pins do |t|
t.attachment :image
end
end
def self.down
remove_attachment :pins, :image
end
end
Gemfile: This is my gemfile, i'm using rails4, paperclip 4.3, and aws-sdk 1.6.5
source 'https://rubygems.org'
ruby '2.2.1'
gem 'rails', '4.2.4'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'bootstrap-sass', '~> 3.3.5'
gem 'devise', '~> 3.5.2'
gem "paperclip", "~> 4.3"
gem 'aws-sdk', '< 2.0'
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
gem 'sqlite3'
end
group :production do
gem 'pg'
gem 'rails_12factor'
end
group :development do
# Access an IRB console on exception pages or by using <%= console %> in views
gem 'web-console', '~> 2.0'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
end
I am really stuck right now, and i don't know what to do. I hope someone can help. If there's something i forgot to add, please tell me and i will add it.
I figured it out
I made it work after trying different things. Look at the comment to see what i did.
I am working on a Rails server which I can download my locally stored movies and anime etc from. This is kind of working but when I click the download link I have to refresh the page in order for the download to actually start.
This is the controller that handles the download:
class DownloadController < ApplicationController
def index
#title = params[:title]
#name = params[:name]
#path = '/media/sf_Anime,_VN,_LN/Watching, not watched yet/'+#title+'/'+#name
send_file( #path )
end
end
and this is the link that links to that controller:
<% #episodes.each do |x| %>
<p> <%= x %><%= link_to " Download",
{controller: 'download', action: 'index', title: #title, name: x } %> </p>
<% end %>
edit:
I did some testing today and noticed that the download links work instantly if i try to send a smaller file (text or image). I also noticed that the download links actually works for the movies aswell but it takes 20-30 seconds for the download to start.
Do you have any idea of what would cause this delay?
Are you using turbolinks? Turbolinks apparently doesn't play nicely with send_file (https://github.com/rails/turbolinks/issues/182). Try adding "data: { no-turbolink: true }" (or "'data-no-turbolink'=>true") in the link_to helper, e.g.:
<%= link_to "Downloadable File", downloadable_file, data: { no-turbolink: true } %>
See also: Rails 4, asset pipeline causes user downloadable files to be downloaded twice, rails won't send_data as file, Ruby on Rails send_file, code in controller action running twice
Edited to reflect comment below. I would simple add a concern for handling downloads and then use
include Concerns::Downloads
to handle your download request. the routes.rb would look like this.
resources :movies do
member do
post 'download'
end
and in the view
<%= link_to 'Download', {:controller => 'movies', :action => 'download'}, {:method => :post } %></a>
Move the file to public folder
add only file name into link_to
<%= link_to "Downloadable File", "/"+filename, %>
Try setting the disposition to attachment in send_file:
class DownloadController < ApplicationController
def index
...
send_file( #path, :disposition => 'attachment' )
end
end
The issue may be that your browser is trying to open the file itself - :disposition => 'attachment' prompts the browser to download the file, even if it thinks the file is something that it can open.
I'm trying to make a twitter web app on rails that can post and search for keywords and I can't figure out why it's not working, I've changed a thousand things and got a thousand different errors, this is my controller file
def hello
#time = Time.now
def user_tweet
require "rubygems"
require "twitter"
# Certain methods require authentication. To get your Twitter OAuth credentials,
# register an app at http://dev.twitter.com/apps
Twitter.configure do |config|
config.consumer_key = 'xxxx'
config.consumer_secret = 'xxxx'
config.oauth_token = 'xxxx'
config.oauth_token_secret = 'xxxx'
end
# Initialize your Twitter client
client = Twitter::Client.new
# Post a status update
client.update("updated tweet")
redirect_to request.referer, :notice => 'Tweet successfully posted'
end
end
and this is my view page
<%= form_for (#tweet = Tweet.new, :url => user_tweet_path) do |tweet_form|
tweet_form.text_area :tweet_content, :id => "tweet"
tweet_form.submit "Tweet"
end %>
Finally, here's the error I'm getting:
syntax error, unexpected ',', expecting ')'
I tried just putting <%= client.update("updated tweet")%> in the view file but it raised an undefined variable error, I'm new to rails, so any help would be appreciated, thanks.
For style, close your ERB tags after every line, don't put spaces after parentheses (like the form_for above) and don't assing values to #tweet (you don't need it):
<%= form_for(Tweet.new, :url => user_tweet_path) do |tweet_form| %>
<%= tweet_form.text_area :tweet_content, :id => "tweet" %>
<%= tweet_form.submit "Tweet" %>
<% end %>