Exporting to CSV and Excel

Step 1:Open  config/application. and add the line as given below:

/config/application.rb

require 'csv'

Step 2: In controller where you want to generate the xls, add the below code.

/controllers/events_controller.rb
 @events = Event.all(:name)
 respond_to do |format|  format.csv { send_data @events.to_csv }
format.xls {send_data @events.to csv(col sep: "\t")}
 

Step 3:Now in model of the event, add the below code.

/models/event.rb
  def csv(options = {})
    CSV.generate(options) do |csv|
      csv << column_names
      all.each do |event|
       csv << event.attributes.values_at(*column_names)

Step 4: Now open the below file and add the line to mime_types.

initializers/mime_types.rb
Mime::Type.register "application/xls", :xls

Step 5:  Now template is created as below .

views/events/list.xls.erb
<table border="1">
  <% @events.each do |event| %>
  <tr>
    <td><%= event.id %></td>
    <td><%= event.name %></td>
    <td><%= event.date %></td>
    <td><%= event.venue %></td>
  </tr>
  <% end %>
</table>

Step 6 :Now add the links to the page where the xls is generated, here i have pasted on the top of the page so in my out put the links are shown on the top of the page.

views/events/list.html.erb

<h1>Events List</h1>

<p>
  Download:
  <%= link_to "CSV", products_path(format: "csv") %> |
  <%= link_to "Excel", products_path(format: "xls") %>
</p>

Step 7: Now you will see the download links on the top of the page as shown below.

fdsfdsfdsfdsfdsf

Advertisements

Facebook Authentication in Ruby on Rails

Step 1: FaceBook Application Integration

Visit http://developers.facebook.com/apps and click the ‘Create New App’ and fill the required fields and select a category and subcategory, click Continue.

Step 2:

After that, note application’s id and secret and  click on ‘Website with Facebook Login’, here give a site URL i.e http://localhost:3000 and Save.

Step 3:Now in rails app open gem file and add the below gem.

gem ‘omniauth-facebook’  and type  $ bundle install  in console

Step 4:Create initializer i.e omniauth in/initializers/omniauth.rb & edit as below

OmniAuth.config.logger = Rails.logger

Replace ‘facebook app id’ with your app id, and ‘ facebook app secret’ with values that was i mentioned above.For solving Open SSL , issue we have to download a file i.e download this file and put in  rails application root folder.

Step 5:Next create a user model to save the data that retrieves from FaceBook i.e run the commands in console:

$rails g model user provider uid name oauth_token oauth_expires_at:datetime

$rake db:migrate

Step 6:Home controller and sessions  will allow user login & logout,So run the commands in the console.

$rails g controller home show

$rails g controller Sessions create destroy

Multiple Attachments with Validations In Rails Using Paper Clip Gem

Step 1 : Create the project

Here I just create a very simple Rails project called attachments with a single model class Task which contains only title and body attributes. Then I install Paperclip using Git. As I don’t need any of the image based functionality in Paperclip I haven’t installed any of its associated images packages, see the documentation if you think you might need them.

rails -d attachments
ruby script/generate scaffold Task title:string body:text
ruby script/plugin install git://github.com/thoughtbot/paperclip.git

Step 2: Add the attachments model

Below is the migration I used to create a table for storing the associations between model objects and their attachments. I have made it polymorphic so it can be used with other model classes. It is called Assets as if it is called Attachmentsthere is an error in some versions of Rails. Use rake db:migrate to create the tables.

class Assets < ActiveRecord::Migration
  def self.up
    create_table :assets do |t|
      t.string :data_file_name
      t.string :data_content_type
      t.integer :data_file_size
      t.integer :attachable_id
      t.string :attachable_type
      t.timestamps
    end

    add_index :assets, [:attachable_id, :attachable_type]
  end
  
  def self.down
    drop_table :assets
  end
end

Then create the attachments model class in asset.rb. This class has a few handy shortcut methods to get access to attachment information and a polymorphic association to the actual attachment data.

class Asset < ActiveRecord::Base
  has_attached_file :data,

  belongs_to :attachable, :polymorphic => true
  
  def url(*args)
    data.url(*args)
  end
  
  def name
    data_file_name
  end
  
  def content_type
    data_content_type
  end
  
  def file_size
    data_file_size
  end
end

To have a standard multiple attachments model like is seen in Brian Getting article and PaperclipPolymorph we just need to add an association to the Task model. In task.rb add the line: has_many :assets, :as => :attachable, :dependent => :destroy.

Step 3: Add Validations

To ensure that there are never more than 5 attachments on a Task and that each attachment is less than a megabyte, add the following lines to task.rb. Putting validations on the Task model allows the Asset model to be reused by other classes if they need multiple attachments. These limits can obviously be easily modified by changing the constants. You will see these constants used throughout the rest of the project, so that the control and display of validations is in a single place.

  validate :validate_attachments
  
  Max_Attachments = 5
  Max_Attachment_Size = 1.megabyte

  def validate_attachments
    errors.add_to_base("Too many attachments - maximum is #{Max_Attachments}") if assets.length > Max_Attachments
    assets.each {|a| errors.add_to_base("#{a.name} is over #{Max_Attachment_Size/1.megabyte}MB") if a.file_size > Max_Attachment_Size}
  end

Step 4: Add Security

By default Paperclip stores attachments under the public directory, thus they are generally available to everyone. To secure the attachments Paperclip needs to be told to store the attachments in a different place, and provided with a controller method to retrieve them. To store the attachments in an assets directory directly under the project root, and have the show method on the AssetsController retrieve them, then modify the association in asset.rb to be the following:

  has_attached_file :data,
                    :url  => "/assets/:id",
                    :path => ":rails_root/assets/docs/:id/:style/:basename.:extension"

This will require the creation of assets_controller.rb as below. I have just put the comment # do security check here in the method where you need to add any security checking as it tends to be application specific. Likely security includes checking the user is logged in or has a particular role or has permission to view the object which has the attachment.

Update: if you are using a web server that handles it, you can add :x_sendfile => true on the end of thesend_file to lower memory consumption. See the Rails documentation for more information.

class AssetsController < ApplicationController
  
  def show
    asset = Asset.find(params[:id])
    # do security check here
    send_file asset.data.path, :type => asset.data_content_type
  end
    
end

Step 5: Setup Display

To handle the display for this simple app there is a new page that allows users to add attachments to a task, a show page that displays the attachments for task and an edit page that allows both. To do this some javascript needs to be set up. Also the rest of this tutorial assumes that the image public/images/attachment.png is present and that the css includes the following (I just added it to public/stylesheets/scaffold.css):

#attachment_list #pending_files{ list-style:none;padding:0; }
#attachment_list li { padding:0 0 0.5em 21px;background:url('/images/attachment.png') no-repeat 0 2px; }
#attachment_list li #remove { margin-left:1em; }

I have used a slightly modified version of the multifile javascript library used by Brian Getting and originally by theStickman. This assumes you are using Prototype and Scriptaculous. It allows users to add a number of files at once which are then stored in page and sent on an update. Create the file public/javascripts/multifile.js as below:

// -------------------------
// Multiple File Upload
// -------------------------
function MultiSelector(list_target, max) {
  this.list_target = list_target;this.count = 0;this.id = 0;if( max ){this.max = max;} else {this.max = -1;};this.addElement = function( element ){if( element.tagName == 'INPUT' && element.type == 'file' ){element.name = 'attachment[file_' + (this.id++) + ']';element.multi_selector = this;element.onchange = function(){var new_element = document.createElement( 'input' );new_element.type = 'file';this.parentNode.insertBefore( new_element, this );this.multi_selector.addElement( new_element );this.multi_selector.addListRow( this );this.style.position = 'absolute';this.style.left = '-1000px';};if( this.max != -1 && this.count >= this.max ){element.disabled = true;};this.count++;this.current_element = element;} else {alert( 'Error: not a file input element' );};};this.addListRow = function( element ){var new_row = document.createElement('li');var new_row_button = document.createElement( 'a' );new_row_button.setAttribute('id', 'remove');new_row_button.title = 'Remove This Attachment';new_row_button.href = '#';new_row_button.innerHTML = 'Remove';new_row.element = element;new_row_button.onclick= function(){this.parentNode.element.parentNode.removeChild( this.parentNode.element );this.parentNode.parentNode.removeChild( this.parentNode );this.parentNode.element.multi_selector.count--;this.parentNode.element.multi_selector.current_element.disabled = false;return false;};new_row.innerHTML = element.value.split('/')[element.value.split('/').length - 1];new_row.appendChild( new_row_button );this.list_target.appendChild( new_row );};
}

Then just add the javascript into the page layout for any page that will require the ability to upload files (lazily, I put it inlayouts/tasks.html.erb despite not all task views needing it).

<%= javascript_include_tag  "prototype", "application",  "effects", "controls", "multifile" %>

Step 6: New Action

Firstly, to add new attachments to the scaffold new.html.erb the form needs to be updated to include :multipart => true, this allows the attachments to be sent along with the HTTP request. Then the Pending Attachment paragraph creates the input field and MultiSelector from multifile.js handles attachment upload on submit. The emptypending_files will contain references to the attachments. Note the use of the Task constants for the allowable number and size of the attachments.

<h1>New task</h1>
<% form_for(@task, :html => { :multipart => true }) do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </p>
  <p>Pending Attachments: (Max of <%= Task::Max_Attachments %> each under <%= Task::Max_Attachment_Size/1.megabyte%>MB)
      <% if @task.assets.count >= Task::Max_Attachments %>
        <input id="newfile_data" type="file" disabled />
      <% else %>
        <input id="newfile_data" type="file" />
      <% end %>
      <div id="attachment_list"><ul id="pending_files"></ul></div>
      <script type="text/javascript">
          var multi_selector = new MultiSelector($('pending_files'), <%=Task::Max_Attachment_Size%>);
          multi_selector.addElement($('newfile_data'));
      </script>
  </p>
  <p>
    <%= f.submit "Create" %>
  </p>
<% end %>
<%= link_to 'Back', tasks_path %>

In the controller the attachments need to be read in and added to the new task. The below code script needs to be added into app/controllers/tasks_controller.rb. Here most of the work is offloaded to the protectedprocess_file_uploads method, so it can be reused in other methods. Before the save or update of a task which may have attachments added to it, call process_file_uploads which just loops through the HTTP parameters and builds any given attachments. They will then be validated and persisted to the database with a save or update.

  # POST /tasks
  def create
    @task = Task.new(params[:task])
    
    process_file_uploads(@task)

    if @task.save
      flash[:notice] = 'Task was successfully created.'
      redirect_to(@task)
    else
      render :action => "new" 
    end
  end
  
  protected

  def process_file_uploads(task)
      i = 0
      while params[:attachment]['file_'+i.to_s] != "" && !params[:attachment]['file_'+i.to_s].nil?
          task.assets.build(:data => params[:attachment]['file_'+i.to_s])
          i += 1
      end
  end

Step 7: Show Action

The show action is a little different – it doesn’t allow any attachments to be added, instead just displaying a list of the current task attachments. Below in app/views/tasks/show.html.erb this is done with a partial.

<p>
  <b>Title:</b>
  <%=h @task.title %>
</p>
<p>
  <b>Body:</b>
  <%=h @task.body %>
</p>

<p><b>Attached Files:</b><div id="attachment_list"><%= render :partial => "attachment", :collection => @task.assets %></div></p>

<%= link_to 'Edit', edit_task_path(@task) %> | <%= link_to 'Back', tasks_path %>

The partial app/views/tasks/_attachment.html.erb just displays some basic information about the attachment, including a link for it to be downloaded using attachment.url. Remember from Step 4 that this will return the url of theAssetsController’s show method to add a layer of security. I have left the remove link in the partial, this will be explained in the next step.

<% if !attachment.id.nil? %><li id='attachment_<%=attachment.id %>'><a href='<%=attachment.url %>'><%=attachment.name %></a> (<%=attachment.file_size/1.kilobyte %>KB)
<%= link_to_remote "Remove", :url => asset_path(:id => attachment), :method => :delete, :html => { :title  => "Remove this attachment", :id => "remove" } %></li>
<% end %>

Step 8: Removing Attachments

The attachment.html.erb partial included a link to remove the attachment. This requires the following destroymethod added to the assetscontroller.rb. It simply finds the attachment and deletes it. The page is updated through javascript returned to the user’s browser.

  def destroy
    asset = Asset.find(params[:id])
    @asset_id = asset.id.to_s
    @allowed = Task::Max_Attachments - asset.attachable.assets.count 
    asset.destroy
  end

The destroy method’s view is app/views/assets/destroy.rjs which using javascript finds the attachment deleted and removes it from the page. It then checks for an attachment add section (by looking for a newfile_data id) and if it finds one updates the number of attachments that may still be added. With this check the RJS can still be used without error on pages that do not have a newfile_data input nor a MultiSelector.

page.hide "attachment_#{@asset_id}"
page.remove "attachment_#{@asset_id}"

# check that a newfile_data id exists
page.select('newfile_data').each do |element| 
  page.assign 'multi_selector.max', @allowed
  if @allowed < Task::Max_Attachments
    page << "if ($('newfile_data').disabled) { $('newfile_data').disabled = false };"
  end
end

Step 9: Edit Action

To complete the views, here is the edit.html.erb which combines the attachment adding functionality of new with the attachment list of show.

<h1>Editing task</h1>

<% form_for(@task, :html => { :multipart => true }) do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </p>
  <p>Pending Attachments: (Max of <%= Task::Max_Attachments %> each under <%= Task::Max_Attachment_Size/1.megabyte%>MB)
      <% if @task.assets.count >= Task::Max_Attachments %>
        <input id="newfile_data" type="file" disabled />
      <% else %>
        <input id="newfile_data" type="file" />
      <% end %>
      <div id="attachment_list"><ul id="pending_files"></ul></div>
      <script type="text/javascript">
          var multi_selector = new MultiSelector($('pending_files'), <%= @allowed %>);
          multi_selector.addElement($('newfile_data'));
      </script>
  </p>
  <p>
    Attached Files:<div id="attachment_list"><%= render :partial => "attachment", :collection => @task.assets %></div>
  </p>
  <p>
    <%= f.submit "Update" %>
  </p>
<% end %>

<%= link_to 'Show', @task %> | <%= link_to 'Back', tasks_path %>

Step 10: Ta-da!

Now its ready and its working 100%.

Action Mailer in Rails 4

Step 1
Create the Mailer called “UserMailer” with the action “sendMail” using following command:

$ rails generate mailer UserMailer sendMail

Step 2
Modify the “sendMail” action according to your requirement. Below is the example content of the/app/mailers/user_mailer.rb:

class UserMailer < ActionMailer::Base
default from: “sender@example.com”
def sendMail(email)
@greeting = “Hi”

mail to: email, subject: “Your Subject”
end
end

Step 3
You may modify the text content of the message at /app/views/user_mailer/sendMail.text.erb. You may also create the HTML version of the message by creating /app/views/user_mailer/sendMail.html.erb file and add the required html content. Below is the example content of the text message:

<%= @greeting %>, This is a text message.

Step 4
Configure the SMTP settings in the development.rb or production.rb or test.rb configuration file according to your requirement. These files are located at /config/environments/ folder.

config.action_mailer.raise_delivery_errors = false
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: “smtpcorp.com”,
port: 2525,
# 8025, 587 and 25 can also be used.

domain: “yourdomain.com”,
authentication: “plain”,
enable_starttls_auto: true,
user_name: “USERNAME”,
password: “PASSWORD”
}

Step 5
You may test the settings by running the following command from rails console.

UserMailer.sendMail(“recipient@example.com”).deliver
In this way you have to follow the steps to setup action mailer in rails application