How to set mail attachments without saving file in database? - ruby-on-rails

I have created simple application form and i was trying to upload file and send it as email attachment. And i did it with this approach:
class ApplyController < ApplicationController
def prepare_email_content
ApplyMailer.with(params).apply.deliver_now
end
end
class ApplyMailer < ApplicationMailer
def apply
#company = Company.find(params[:company_id])
#candidate = params[:name]
#candidate_mail = params[:email]
#email = #company.email
attachments[params[:cv].original_filename] = params[:cv].read
mail to: #email, subject: 'Hello'
end
end
<h1>APPLY</h1>
<%= form_tag(apply_path, method: :post, multipart: true) do %>
<%= label_tag(:name, "First and last name:") %>
<%= text_field_tag(:name) %>
<%= label_tag(:email, "Email:") %>
<%= text_field_tag(:email) %>
<%= hidden_field_tag :company_id, params[:company_id] %>
<%= file_field_tag 'cv' %>
<%= submit_tag "Search", :name => nil %>
<% end %>
<%= link_to 'All offers', hello_path %>
Everything was working fine - i have tested application and it was fine. Then i have developed my application and when i come back to testing i started getting this error:
On the way i have installed some gems and updated few of them. I was checking out to commit where this feature was working and it is. But i'm not able to find any differences in my code. There were some changes in /.idea folder but i don't know if any of this files could trigger this issue.
I'm using rails 6.0.3 and ruby 2.5.8
EDIT
I can see that there is a problem inside called methods. Looks like it cannot find #sort_order value and it sets data value as nil. But i have no idea how to change working of this.

Replace the line you're attaching the file with
attachments["#{params[:cv].original_filename}"] = File.read(params[:cv].path)
Even though you're not saving the file, there is a still a local path to grab the file from.
Also, you should really consider passing the parameters to the mailer from the controller, rather than passing params in its entirety. That way if the information or format of the upload is incorrect, you can redirect back to the form and bypass sending the email.

Related

Rails form_tag not displaying the existing field value

I've a settings controller setup like this:
class Admin::SettingsController < ApplicationController
def index
#settings = Setting.all
end
def update
setting_params.each do |key, value|
Setting.where(key: key).first.update_attribute :value, value
end
redirect_to admin_settings_path, notice: "Settings saved."
end
private
def setting_params
params.require(:settings).permit(:site_title, :site_desc)
end
end
The index action has a view file in relevant path, its code is as follows:
<h1>Settings</h1>
<%= form_tag admin_settings_path, method: "put" do %>
<p>
<label>Site Title:</label>
<%= text_field_tag "settings[site_title]" %>
</p>
<p>
<label>Site Description:</label>
<%= text_field_tag "settings[site_desc]" %>
</p>
<p>
<%= submit_tag "Save settings" %>
</p>
<% end %>
Now, I'm able to save/update these fields data in relevant model and I can see the data through command Setting.all in rails console. But the issue is, after saving the record via form when I reload the settings index page the form is blank and it is not showing previously saved values in the fields.
What I'm doing wrong here?
You can do what has been mentioned in the previous answer i.e. using a form_for. However, this can also be accomplished by creating a Hash in both the controller actions that creates and processes this form.
In the action that creates this form, the values in the hash could be initialized to blanks/zeros depending upon the input tag and in the action that processes this form, the values in the hash could be assigned to the values obtained from the posted params[].
I ran into the similar issue with form_tag and I used the following code in my index action i.e. the action that renders the form initially:
#search = {name: "", ranking_group: 0}
Whereas, in the search action, I used the following code to fill up this hash:
#search = {name: params[:name], ranking_group: params[:ranking_group]}
Finally, in the view, I used the appropriate default value options with the input tags as below:
<%= text_field_tag :name, #search[:name] %>
<%= select_tag :ranking_group, options_for_select(AmenityEntities::Amenity.ranking_group_options, #search[:ranking_group]), include_blank: true %>
Hope this helps.
I think you need to use form_for(#variable) instead of just a form_tag because you need to persiste the object after save.
form_for works with resources, take a look here: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html

How to use devise-invitable

I just started with Rails and devise and I have a task, allow users to sign up only by invitation of existing user. I choose devise-invitable gem and got stuck with a bit unclear documentation. I have this code:
def invitationForm
#nuser = User.new
end
def invite_user
#user = User.invite!({:email => #nuser.email}, current_user)
end
Where invitationForm renders a form:
<%= form_for #nuser, url: {action: "invite_user"} do |f| %>
<%= f.text_field :email %>
<%= f.submit "Invite" %>
<% end %>
After all I`m getting this error:
RuntimeError in User#invite
Showing //invite.html.erb where line #2 raised:
Could not find a valid mapping for nil
What am I doing wrong and what should I do?
I think one of your problems could be here:
<%= form_for #nuser, url: {action: "invite_user"} do |f| %>
Your form was pointing to invite instead of the invite_user method you have created.
Okay, the deal was in the setup, somehow. After creating a new project and starting from scratch all workred fine.

Ruby on Rails: Getting Form Input to Model

I'm still learning more about Rails and I'm starting to play around with APIs, but I can't seem to figure out how to get an input from a form to the Model.
I want to take the User input (in the form of a zip code) and have it spit out the weather info at that user location.
Form on home.html.erb
<%= form_tag(root_path) do %>
<%= label_tag :zip, "ENTER YOUR ZIPCODE TO FIND YOUR WEATHER" %><br>
<%= text_field_tag :zip,'', placeholder: "e.g. 91765 " %>
<%= submit_tag "show me the weather!" %>
<% end %>
Controller pages_controller.rb
class PagesController < ApplicationController
def home
#weather_lookup = WeatherLookup.new(params[:zip])
end
end
Model weather_lookup.rb
class WeatherLookup
attr_accessor :temperature, :weather_condition, :city, :state, :zip
def initialize(zip)
self.zip = zip
zip = 91765 if zip.blank?
weather_hash = fetch_weather(zip)
weather_values(weather_hash)
end
def fetch_weather(zip)
p zip
HTTParty.get("http://api.wunderground.com/api/API-KEY-HERE/geolookup/conditions/q/#{zip}.json")
end
def weather_values(weather_hash)
self.temperature = weather_hash.parsed_response['current_observation']['temp_f']
self.weather_condition = weather_hash.parsed_response['current_observation']['weather']
self.city = weather_hash.parsed_response['location']['city']
self.state = weather_hash.parsed_response['location']['state']
end
end
I'm not exactly sure how to get the input from the form to the model. This is literally just to show the weather. I'm not trying to save anything in a database
The form helper defaults to "POST" if you don't provide a method. From the looks of your controller, "GET" is what you want. Here's some documentation to provide additional context. The updated form:
<%= form_tag(root_path, method: "get") do %>
<%= label_tag :zip, "ENTER YOUR ZIPCODE TO FIND YOUR WEATHER" %><br>
<%= text_field_tag :zip,'', placeholder: "e.g. 91765 " %>
<%= submit_tag "show me the weather!" %>
<% end %>
Next, if you try to instantiate your #weather_lookup variable without params[:zip], Rails will throw an error. Adding a conditional to your controller will solve this:
class PagesController < ApplicationController
def home
if params[:zip]
#weather_lookup = WeatherLookup.new(params[:zip])
end
end
end
Be sure your routes are set up. Something defining root should exist in routes.rb. For example:
root "pages#home"
I believe you also have to parse the JSON into a hash inside your model. Adding that to the weather_values method:
def weather_values(weather_json)
weather_hash = JSON.parse weather_json
self.temperature = weather_hash.parsed_response['current_observation']['temp_f']
self.weather_condition = weather_hash.parsed_response['current_observation']['weather']
self.city = weather_hash.parsed_response['location']['city']
self.state = weather_hash.parsed_response['location']['state']
end
Finally, be sure you're referencing #weather_lookup somewhere in your view, else the data won't show. A simple, unformatted example:
<%= #weather_lookup %>
Assuming the logic works in your model, the JSON should render after you submit a ZIP code via the form. I don't have an API key else I would have tested this myself.
It seems like you are not hitting your home controller after you hit submit. Make sure you are routing correctly with
root to: 'pages#home'
and add this to your form
<%= form_tag(root_path, method: 'get') do %>

File uploading Mailboxer Gem

I'm trying to send a message with an attachment in Mailboxer Gem.
My stack is : Rails 4 and Ruby 2.1.1
However, I can see that attachment using CarrierWave is already supported as the link in the code below.
https://github.com/ging/mailboxer/blob/4b2681c1790b823f7b493fb00b41e9899bb90ebe/app/models/message.rb#L13
However, I did my setup exactly like that. Normal message without an attachment is going fine.
This is my code :
Controller :
def create_message
if params[:user].present? & params[:message].present? & params[:subject].present?
current_user.send_message(User.find(params[:user]), params[:message], params[:subject])
redirect_to inbox_path
end
end
This is my view code :
<%= form_tag do %>
<%= select_tag 'user', options_from_collection_for_select(User.all, :id, :fullname) %><br/>
<%= text_field_tag 'subject' %><br/>
<%= text_area_tag 'message' %><br/>
<%= submit_tag 'Send' %>
<% end %>
The above code is working fine and the messages are getting sent, however, when I try to add the file field to it like so and try changing the controller code, the attachment is not getting uploaded :
def create_message
if params[:user].present? & params[:message].present? & params[:subject].present?
current_user.send_message(User.find(params[:user]), params[:message], params[:subject], true , params[:attachment])
redirect_to inbox_path
end
end
View :
<%= form_tag do %>
<%= select_tag 'user', options_from_collection_for_select(User.all, :id, :fullname) %><br/>
<%= text_field_tag 'subject' %><br/>
<%= text_area_tag 'message' %><br/>
<%= file_field_tag 'attachment' %>
<%= submit_tag 'Send' %>
<% end %>
I think this is a problem with the strong params. In Rails 3 I could have used attr_accessible. However how do I ensure that the attachment field is not being blocked and allowed?
P.S - I have the carrierwave gem installed and I have even restarted my server multiple times.
Thanks.
I am changing my previous answer, because in fact it wasn't correct.
Basically, if your problem is like mine, it could easily be solved by adding :multipart => true to your form. At least in my case, that's why carrierwave was not picking up the attachments.
I tried to solve the problem by extending the mailboxer Message class and setting up and mounting a completely new carrierwave object with a different attribute name. Basically, this allowed me to avoid working with the attachment attribute defined in mailboxer and to customize the attachments.
But this got very messy with the extension of the mailboxer message.rb Class. So I finally abandoned that course. Still, having your own uploader instead of relying on the mailboxer attachment is very convenient, especially if you want or need to upload your files to a different directory or to the cloud.
So finally, I have created a new model for my attachments and mounted a new carrierwave uploader on it. In that way, I can customize it as I want without having to tweak mailboxer, which has very little in terms of documentation or support.
Probably this is not useful to you anymore, but might help others!

using youtube_it gem in rails app

i'm using ruby-1.8.7 and rails 2.3.5 in my rails app. i have a requirement to let the users upload their videos to youtube for which i'm using youtube_it gem. But i'm not sure if i'm following the documentation right.
here's my controller code:
class VideosController < ApplicationController
def upload
#upload_info = YouTubeIt::Client.new.upload_token(params, videos_url)
# params represent what values here, the doc says title, description but do i have to #build another form to get these values, i really need a working example.
end
and here's my form:
<% form_tag #upload_info[:url], :multipart => true do %>
<%= hidden_field_tag :token, #upload_info[:token] %>
<%= label_tag :file %>
<%= file_field_tag :file %>
<%= submit_tag "Upload video" %>
<% end %>
my other question is where am i supposed to specify the following statement which will initialize a new client for me:
client = YouTubeIt::Client.new(:dev_key => "developer_key")
i need some assistance here.
you are close just is missing a first step for give title and description to the video
for example
1 step) ask for title and description
send this to the controller and call to the method
#upload_info = YouTubeIt::Client.new.upload_token(params[:first_step], videos_url)
and this has to call to second step
2 step) the form that do you had
<% form_tag #upload_info[:url], :multipart => true do %>
<%= hidden_field_tag :token, #upload_info[:token] %>
<%= label_tag :file %>
<%= file_field_tag :file %>
<%= submit_tag "Upload video" %>
<% end %>
I going to give you a gist with real example
https://gist.github.com/1051122
for the last question you can initialize the client in your application_controller.rb, you can see it in the gist
I hope that it help you, good luck!
here you have a code example
http://www.chebyte.com/2011/09/15/youtube-it-demo-rails-app/

Resources