Wednesday, 26 February 2025

Send attachment with mail in rails

 Routes: 

post "/send_email_with_attachment", to: "articles#send_email_with_attachment"

-----------------------------------

Controller:

class ArticlesController < ApplicationController

  def send_email_with_attachment

    email = "arvind@gmail.com"

    attachment = params[:attachment]

    # Save the file temporarily

    file_path = Rails.root.join('tmp', attachment.original_filename)

    File.open(file_path, 'wb') do |file|

      file.write(attachment.read)

    end

    MyMailer.send_email_with_attachment(email, file_path).deliver_now

    # Delete the temporary file after sending the email

    File.delete(file_path) if File.exist?(file_path)

    redirect_to root_path, notice: 'Email sent successfully'

  end

end


--------------------------

Mailer

class MyMailer < ApplicationMailer

  def send_email_with_attachment(email, attachment_path)

    @greeting = "Hi"

    attachments[File.basename(attachment_path)] = File.read(attachment_path)

    mail(to: email, subject: 'Email with Attachment')

  end

end

-------------------------------

View
Form view:

<%= form_tag "/send_email_with_attachment", class: "inline-form", multipart: true do %>
  <%= file_field_tag :attachment %>
  <%= submit_tag 'Send Email' %>
<% end %>

Mailer view:

<h1>My#send_email_with_attachment</h1>

<p>
  <%= @greeting %>, find me in app/views/my_mailer/send_email_with_attachment.html.erb
</p>

----------------------------

Development.rb

config.action_mailer.perform_deliveries = true
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.default_options = {from: 'localhost:3000'}
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    address:              'smtp.gmail.com',
    port:                 587,
    domain:               'localhost',
    user_name:            ENV["SMTP_EMAIL"],
    password:             ENV["SMTP_PASSWORD"],
    authentication:       'plain',
    enable_starttls_auto: true
  }


public bucket on AWS s3

 Please visite: https://alex-okorkov.medium.com/how-to-set-up-aws-s3-bucket-on-rails-with-activestorage-d384075ce773

--------------------


Code:

{

    "Version": "2012-10-17",

    "Statement": [

        {

            "Effect": "Allow",

            "Principal": "*",

            "Action": "s3:ListBucket",

            "Resource": "arn:aws:s3:::newlogoimages"

        },

        {

            "Effect": "Allow",

            "Principal": "*",

            "Action": [

                "s3:PutObject",

                "s3:GetObject",

                "s3:DeleteObject"

            ],

            "Resource": "arn:aws:s3:::newlogoimages/*"

        }

    ]

}



Thursday, 9 January 2025

Add nested form in rails 7

 1. Add Gem

gem "nested_form"

Run$ : bundle 
----------------
2. Created new file : app/javascript/js/nested_form.js

rails g nested_form:install
jb ye line run karege to public ke ander >> public/javascript/js/nested_form.js file generate hogi, lekin nested_form.js ka code is directory me add kar dena >>  app/javascript/js/nested_form.js

app/javascript/js/nested_form.js

(function($) {
  window.NestedFormEvents = function() {
    this.addFields = $.proxy(this.addFields, this);
    this.removeFields = $.proxy(this.removeFields, this);
  };

  NestedFormEvents.prototype = {
    addFields: function(e) {
      // Setup
      var link      = e.currentTarget;
      var assoc     = $(link).data('association');                // Name of child
      var blueprint = $('#' + $(link).data('blueprint-id'));
      var content   = blueprint.data('blueprint');                // Fields template

      // Make the context correct by replacing <parents> with the generated ID
      // of each of the parent objects
      var context = ($(link).closest('.fields').closestChild('input, textarea, select').eq(0).attr('name') || '').replace(new RegExp('\[[a-z_]+\]$'), '');

      // context will be something like this for a brand new form:
      // project[tasks_attributes][1255929127459][assignments_attributes][1255929128105]
      // or for an edit form:
      // project[tasks_attributes][0][assignments_attributes][1]
      if (context) {
        var parentNames = context.match(/[a-z_]+_attributes(?=\]\[(new_)?\d+\])/g) || [];
        var parentIds   = context.match(/[0-9]+/g) || [];

        for(var i = 0; i < parentNames.length; i++) {
          if(parentIds[i]) {
            content = content.replace(
              new RegExp('(_' + parentNames[i] + ')_.+?_', 'g'),
              '$1_' + parentIds[i] + '_');

            content = content.replace(
              new RegExp('(\\[' + parentNames[i] + '\\])\\[.+?\\]', 'g'),
              '$1[' + parentIds[i] + ']');
          }
        }
      }

      // Make a unique ID for the new child
      var regexp  = new RegExp('new_' + assoc, 'g');
      var new_id  = this.newId();
      content     = $.trim(content.replace(regexp, new_id));

      var field = this.insertFields(content, assoc, link);
      // bubble up event upto document (through form)
      field
        .trigger({ type: 'nested:fieldAdded', field: field })
        .trigger({ type: 'nested:fieldAdded:' + assoc, field: field });
      return false;
    },
    newId: function() {
      return new Date().getTime();
    },
    insertFields: function(content, assoc, link) {
      var target = $(link).data('target');
      if (target) {
        return $(content).appendTo($(target));
      } else {
        return $(content).insertBefore(link);
      }
    },
    removeFields: function(e) {
      var $link = $(e.currentTarget),
          assoc = $link.data('association'); // Name of child to be removed
      
      var hiddenField = $link.prev('input[type=hidden]');
      hiddenField.val('1');
      
      var field = $link.closest('.fields');
      field.hide();
      
      field
        .trigger({ type: 'nested:fieldRemoved', field: field })
        .trigger({ type: 'nested:fieldRemoved:' + assoc, field: field });
      return false;
    }
  };

  window.nestedFormEvents = new NestedFormEvents();
  $(document)
    .delegate('form a.add_nested_fields',    'click', nestedFormEvents.addFields)
    .delegate('form a.remove_nested_fields', 'click', nestedFormEvents.removeFields);
})(jQuery);

// http://plugins.jquery.com/project/closestChild
/*
 * Copyright 2011, Tobias Lindig
 *
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 */
(function($) {
        $.fn.closestChild = function(selector) {
                // breadth first search for the first matched node
                if (selector && selector != '') {
                        var queue = [];
                        queue.push(this);
                        while(queue.length > 0) {
                                var node = queue.shift();
                                var children = node.children();
                                for(var i = 0; i < children.length; ++i) {
                                        var child = $(children[i]);
                                        if (child.is(selector)) {
                                                return child; //well, we found one
                                        }
                                        queue.push(child);
                                }
                        }
                }
                return $();//nothing found
        };
})(jQuery);

--------------------------------------------
4. config/importmap.rb

# Pin npm packages by running ./bin/importmap

pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin "nested_form", to: "js/nested_form.js"
pin_all_from "app/javascript/controllers", under: "controllers"
pin_all_from "app/javascript/js", under: "js", preload: true

------------------------------------------------
5. app/javascript/application.js

// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import "controllers"
import "js/bootstrap.bundle.min"
import "js/simple-datatables"
import "js/quill.min"
import "js/tinymce.min"
import "js/validate"
import "js/main"
import "nested_form";
--------------------------------------------
6. User.rb
has_many :products, dependent: :destroy
  accepts_nested_attributes_for :products, allow_destroy: true
-----------------------------
7. Product.rb
class Product < ApplicationRecord
belongs_to :user
end
------------------------------------------

8. On form
<%= simple_nested_form_for @user, url: user_path(@user), html: { class: 'row g-3', "data-turbo": false } do |f| %>

<div class="col-md-6 mt-4">
         <label class="form-label">Bericht</label>
            <%= f.input :email, input_html: { class: "form-control form-control-sm", rows: 5 }, label: false %>
        </div>

<h3>Products</h3>
  <div id="products">
    <%= f.fields_for :products do |product_form| %>
      <div class="nested-fields">
        <%= product_form.label :name, "Product Name" %>
        <%= product_form.text_field :name %>

        <%= product_form.link_to_remove "Remove" %>
      </div>
    <% end %>
  </div>
        <%= f.link_to_add "Add a products", :products, :data => { :target => "#products" } %>

<% end %>
-------------------------------------------------

9. User controller.rb
def users_params
    params.require(:user).permit(:email, products_attributes: [:id, :name, :_destroy])
  end

Friday, 29 November 2024

Add Serializer

Is blog se aap serializer ka name kuchh bhi rakh sakte ho, isme mene index per RolesSerializer and show per RoleDetailsSerializer ka use kiya hai, aap chaho to kisi bhi method per kisi bhi name ka serializer use kar sakte ho, Thanks


 1. Gem

gem 'fast_jsonapi'

run: bundle

---------------

2. app/serializers/base_serializer.rb

class BaseSerializer

  include FastJsonapi::ObjectSerializer

end

---------------

3. A. app/serializers/roles/roles_serializer.rb ## serializers ke ander roles name ka folder bana bhi sakte ho or nhi bhi

module Roles

  class RolesSerializer < BaseSerializer

    attributes :id, :name

  end

end

  B. app/serializers/roles/role_details_serializer.rb 

module Roles

  class RoleDetailsSerializer < BaseSerializer

    attributes :id, :name, :created_at, :updated_at


    attribute :created_at do |object|

      object.created_at.strftime('%Y-%m-%d %H:%M:%S')

    end

  end

end

---------------

4. app/controllers/roles_controller.rb

class RolesController < ApplicationController
before_action :set_role, only: [:show]

def index
roles = Role.all
render json: Roles::RolesSerializer.new(roles).serializable_hash, status: :ok
end

def create
    role = Role.new(role_params)
    if role.save
      render json: Roles::RolesSerializer.new(role, meta: {message: "Role created successfully"}), status: :created
    else
      render json: { errors: { message: role.errors.full_messages } }, status: :unprocessable_entity
    end
  end

  def show
  render json: Roles::RoleDetailsSerializer.new(@role, meta: {message: "Role details"}).serializable_hash, status: 200
  end

  private

  def set_role
      @role = Role.find_by(id: params[:id])
      return render json: {errors: {message: ["Role not found."]}}, :status => :not_found if @role.blank?
    end


  def role_params
  params.require(:role).permit(:name)
  end
end

Sunday, 24 November 2024

Update ID with primary id

 create_table :apps do |t|

  t.references :company, foreign_key: true

  t.string :app_id

  t.string :app_secret

  t.boolean :status, default: false


  t.timestamps

end


Local : primary id updated

118 to 6

# There is no record of 6 id

ActiveRecord::Base.transaction do

  ActiveRecord::Base.connection.execute("ALTER TABLE apps DROP CONSTRAINT fk_rails_2701a89c0b;")

  company = Company.find(118)

  company.update!(id: 6)

  App.where(company_id: 118).update_all(company_id: 6)

  ActiveRecord::Base.connection.execute("ALTER TABLE apps ADD CONSTRAINT fk_rails_2701a89c0b FOREIGN KEY (company_id) REFERENCES companies(id);")

end


71 to 118


ActiveRecord::Base.transaction do

  ActiveRecord::Base.connection.execute("ALTER TABLE apps DROP CONSTRAINT fk_rails_2701a89c0b;")

  company = Company.find(71)

  company.update!(id: 118)

  App.where(company_id: 71).update_all(company_id: 118)

  ActiveRecord::Base.connection.execute("ALTER TABLE apps ADD CONSTRAINT fk_rails_2701a89c0b FOREIGN KEY (company_id) REFERENCES companies(id);")

end

Sunday, 17 November 2024

Add Ajax Without partial

 Routes:   

get 'zzzz' => 'controllers#zzzz', :as => 'zzzz'

------

Controllers:
  include ActionView::Helpers::FormOptionsHelper
 skip_before_action :verify_authenticity_token, only: [:zzzz]
def zzzz
    bank_id = params[:bank_id]
    bank = Bank.find_by(id: bank_id)
    if bank.present?
      modes = options_for_auth_type(bank.mode)
    else
      modes = options_for_auth_type("E-mandate facility not available for this bank")
    end
    options = options_for_select(modes)
    render json: { options: modes }
  end

----------
html.erb file
<%=simple_form_for @customer, html: { class: 'form'} do |f|%>
<%= f.select :bank_id, options_for_select(select_bank, selected: f.object.bank_id), { include_blank: "Select Bank" }, { class: "chosen-select form-control mb-2 mr-sm-2", id: "bank_name", required: true } %>

<div class="col-sm-8">
                  <% if @customer.mode.present? %>
                    <%= f.select :auth_type, options_for_select(options_for_auth_type(@customer.mode), selected: f.object.auth_type), { include_blank: "Select Authorization" }, { class: "form-control mb-2 mr-sm-2"} %>
                  <% else %>
                    <%= f.select :auth_type, options_for_select([["Debit Card",'DebitCard'],["Net Banking",'NetBanking'],["Aadhaar", "Aadhaar"]], selected: f.object.auth_type), { include_blank: "Select Authorization" }, { class: "form-control mb-2 mr-sm-2"} %>
                  <% end %>
                </div>
<% end %>
<script type="text/javascript">
$(document).ready(function() {
  $('#bank_name').on('change', function() {
    var selectedBankId = $(this).val();  // Get selected bank ID
    $.ajax({
      url: '/zzzzz', // The URL where you send the request
      method: 'GET',
      data: { bank_id: selectedBankId },
      success: function(response) {
        var modes = response.options;
        var optionsHtml = '<option value="">Select Authorization</option>';
        $.each(modes, function(index, mode) {
          optionsHtml += '<option value="' + mode[1] + '">' + mode[0] + '</option>';
        });
        $('#customer_auth_type').html(optionsHtml);
      }
    });
  });
 });
</script>

Monday, 21 October 2024

Push html file project on github.io and react js project

This is HTML 

1. Build the design with html and css.

2. Create repo on Github
2.1 repositories should be public
2.2 repositories name is : username.github.io

2.3 push the code on this repo: https://github.com/username/username.github.io

3. GitHub.io only indicates the main branch.

4. Fire up a browser and go to https://username.github.io.


--------------------------------------------------------------------

This is REACT JS

1. npm install gh-pages --save-dev

make sure run this command: npm run build isme koi error and warning nhi ana chahiye    

2. add this line in package.json

{

  "name": "react-app-oct",

  "version": "0.1.0",

  "private": true,

  "homepage": "https://username.github.io/",

// "homepage": "https://username.github.io/github-react-21-oct",  

"dependencies": {}


"scripts": {

    "predeploy": "npm run build",

    "deploy": "gh-pages -d build --repo https://github.com/username/username.github.io.git",

 // "deploy": "gh-pages -d build", pehle iske sath deploy karo nhi to uper wale ke sath

    "start": "react-scripts start",

    "build": "react-scripts build",

    "test": "react-scripts test",

    "eject": "react-scripts eject"

  },

----

ye sab add karne ke baad code ko push karna hai

phit ye run karna hai : npm run deploy


---

ye wali branch deploy hoti hai Gihub per, jb repo per click karoge to waha se "gh-pages" ye wai branch select karni hogi

gh-pages


Check GitHub Pages Settings

  • Go to the GitHub repository https://github.com/username/github-react-21-oct.
  • Ensure the Source is set to gh-pages branch, and save the settings.