0

FriendlyID does not seem to find a database entry with the corresponding slug.

Here is what the console shows:

Started GET "/budgets/drinks" for 127.0.0.1 at 2015-07-01 12:42:53 +0200 Processing by BudgetsController#show as HTML Parameters: {"id"=>"drinks"} Budget Load (0.2ms) SELECT "budgets".* FROM "budgets" WHERE "budgets"."slug" = 'drinks' ORDER BY "budgets"."id" ASC LIMIT 1 User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1 MoneyTransaction Load (0.5ms) SELECT "money_transactions".* FROM "money_transactions" WHERE "money_transactions"."budget_id" = ? [["budget_id", 17]]
Budget Load (0.1ms) SELECT "budgets".* FROM "budgets" WHERE "budgets"."user_id" = ? [["user_id", 1]] Rendered budgets/_budget_overview.html.erb (5.5ms) Rendered budgets/_form.html.erb (7.0ms) Rendered budgets/show.html.erb within layouts/application (26.3ms) Completed 200 OK in 224ms (Views: 213.5ms | ActiveRecord: 1.0ms)

Started POST "/money_transactions" for 127.0.0.1 at 2015-07-01 12:43:06 +0200 Processing by MoneyTransactionsController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"EPcX4adigoTRY6A1doxWpdMM9eXy/KyqY84zKp855bE=", "money_transaction"=>{"budget_id"=>"drinks", "amount"=>"24", "title"=>"coke"}, "button"=>""} User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1 Budget Load (0.2ms) SELECT "budgets".* FROM "budgets" WHERE "budgets"."slug" = 'drinks' ORDER BY "budgets"."id" ASC LIMIT 1
(0.1ms) begin transaction Budget Load (0.1ms) SELECT "budgets".* FROM "budgets" WHERE "budgets"."id" = ? LIMIT 1 [["id", 0]]
(0.1ms) rollback transaction (0.0ms) begin transaction (0.1ms) rollback transaction Redirected to http://localhost:3000/budgets/drinks Completed 302 Found in 14ms (ActiveRecord: 0.7ms)

This shows that the slug exists and is correctly related to the ID when I access the page. However after looking for for an entry with the slug "drinks" it only returns an ID of 0.

Budget Load (0.2ms) SELECT "budgets".* FROM "budgets" WHERE "budgets"."slug" = 'drinks' ORDER BY "budgets"."id" ASC LIMIT 1
(0.1ms) begin transaction Budget Load (0.1ms) SELECT "budgets".* FROM "budgets" WHERE "budgets"."id" = ? LIMIT 1 [["id", 0]]

money_transaction_controller.rb

def create
    @budget = Budget.friendly.find(params[:money_transaction][:budget_id])
    @money_transaction = MoneyTransaction.new(money_transaction_params)
    @money_transaction.user = current_user
    @money_transaction.date = Time.now.to_date
    @money_transaction.is_positive = 0

    @money_transaction.save

    respond_to do |format|
      if @money_transaction.save
        format.html { redirect_to @budget, notice: 'Transaction added.'}
        format.json { render :show, status: :created, location: @budget }
      else
        format.html { redirect_to @budget, alert: 'Transaction was not valid.'}
        format.json { render json: @money_transaction.errors, status: :unprocessable_entity }
      end
    end
  end

budget.rb

class Budget < ActiveRecord::Base
  belongs_to :user
  has_many :money_transactions

  validates :amount, presence: true
  validates :title, presence: true
  validates :user, presence: true
  validates :amount, numericality: true

  extend FriendlyId
  friendly_id :title, use: :slugged

  def should_generate_new_friendly_id?
    new_record?
  end
end

budgets/show.html.erb

<%= form_for(@budget.money_transactions.build, :html => { :id => 'money_transaction-form' }) do |f| %>
      <%= f.hidden_field :budget_id, :value => params[:id] %>

      <%= f.number_field :amount, id: "transaction-input", placeholder: "#{@budget.title} ", step: 0.01, :autocomplete => :off %>

      <%= f.text_field :title, class: "", placeholder: "purpose", :autocomplete => :off %>

      <%= f.button(type: 'submit', class: "postfix") do %>
          <i class="fa fa-arrow-right"></i>
      <% end %>

<% end %>

routes.rb

  get '/pages', to: 'pages#index'

  devise_for :users
  resources :users

  resources :budget
  resources :money_transactions


  root :to => 'budgets#index'

Let me know if you need any other files. I worked with friendlyID before and never had problems. I hope you can help me.

EDIT: So I found a workaround. But I feel like there should be a simpler solution. I changed my hidden field to:

<%= f.hidden_field :budget_id, :value => Budget.where(:slug => params[:id]).last.id %>

Now it works. But if you have a better solution, please let me know.

sam
  • 1,711
  • 1
  • 17
  • 24
  • Do you have an attributes called slug into your corresponding model which is currently using the friendly-id extension then please try the query in the rails console, may help you to get solved the issues. – Bharat soni Jul 01 '15 at 10:59
  • Thanks for the fast response. I did check in the Rails console and I can find the model with it's slug: > Budget.where(:slug => "drinks") Budget Load (4.0ms) SELECT "budgets".* FROM "budgets" WHERE "budgets"."slug" = 'drinks' => #, refresh_rate: nil, created_at: "2015-06-30 12:22:34", updated_at: "2015-06-30 12:22:34", user_id: 1, slug: "drinks">]> – sam Jul 01 '15 at 11:04
  • parameters should comes in slug not in id. – Bharat soni Jul 01 '15 at 11:06
  • Try to update your routes brother. – Bharat soni Jul 01 '15 at 11:06
  • Sorry, what exactly do you mean? Which route should I update? – sam Jul 01 '15 at 11:13
  • Share your routes file here. – Bharat soni Jul 01 '15 at 12:43

1 Answers1

0

Don't use FriendlyID for form parameters - just use the straight ID. That lets rails automatically add the association and results in a much more effective SQL query.

<%= form_for(@budget.money_transactions.build, :html => { :id => 'money_transaction-form' }) do |f| %>
  <%= f.hidden_field :budget_id, value: @budget.id %>
  <%= f.number_field :amount, id: "transaction-input", placeholder: "#{@budget.title} ", step: 0.01, :autocomplete => :off %>
  <%= f.text_field :title, class: "", placeholder: "purpose", :autocomplete => :off %>
  <%= f.button(type: 'submit', class: "postfix") do %>
    <i class="fa fa-arrow-right"></i>
  <% end %>
<% end %>

With that you can clean up your controller:

def create
  @money_transaction = MoneyTransaction.new(money_transaction_params) do |mt|
    mt.user = current_user
    mt.date = Time.now.to_date
    mt.is_positive = 0
  end
  respond_to do |format|
    if @money_transaction.save
      format.html { redirect_to @budget, notice: 'Transaction added.'}
      format.json { render :show, status: :created, location: @budget }
    else
      format.html { redirect_to @budget, alert: 'Transaction was not valid.'}
      format.json { render json: @money_transaction.errors, status: :unprocessable_entity }
    end
  end
end
max
  • 96,212
  • 14
  • 104
  • 165
  • That looks much nicer and simpler than my silly workaround. Thanks a lot! – sam Jul 01 '15 at 19:21
  • I just saw that you were creating the form from the budget#show method. Removed the #new action from my answer. – max Jul 01 '15 at 20:43