I am using carrierwave and trying to display images of products in the index view. This are my models, controllers and views
product.rb
class Product < ActiveRecord::Base
has_many :order_items
belongs_to :category, required: false
has_many :product_attachments
accepts_nested_attributes_for :product_attachments
mount_uploader :image, ImageUploader
default_scope { where(active: true) }
end
product_attachment.rb
class ProductAttachment < ApplicationRecord
mount_uploader :image, ImageUploader
belongs_to :product
end
products_controller.rb (extract)
class ProductsController < ApplicationController
def index
#products = Product.all
#order_item = current_order.order_items.new
end
def show
#product = Product.find(params[:id])
#product_attachments = #product.product_attachments.all
end
def new
#product = Product.new
#product_attachment = #product.product_attachments.build
#categories = Category.all.map{|c| [ c.name, c.id ] }
end
def create
#product = Product.new(product_params)
#product.category_id = params[:category_id]
respond_to do |format|
if #product.save
params[:product_attachments]['image'].each do |a|
#product_attachment = #product.product_attachments.create!(:image => a, :product_id => #product.id)
end
format.html { redirect_to #product, notice: 'Product was successfully created.' }
else
format.html { render action: 'new' }
end
end
end
private
def product_params
params.require(:product).permit(:name,:price, :active, :description, product_attachments_attributes:
[:id, :product_id, :image], category_attributes: [:category_id, :category])
end
end
index.html.erb
<div class="row">
<div class="col-xs-offset-1 ">
<% #products.each do |product| %>
<%= render "product_row", product: product, order_item: #order_item %>
<% end %>
</div>
_product_row.html.erb
<div class="well">
<div class="row">
<div class="container-fluid row">
<div class="col-md-5 col-lg-5 col-sm-5 col-xs-5 binder">
<br><%= image_tag product.image_url.to_s %><br><br>
</div>
<div class="col-md-4 col-lg-4 col-sm-4 col-xs-4 binder">
<h4 class="text-left"><%= product.name.split.map(&:capitalize).join(' ') %> </h4>
<h4 class="text-left"><span style="color: green"><%= number_to_currency(product.price, :unit => "€") %></span></h4>
<h4><%= link_to Category.find(product.category_id).name, category_path(product.category_id) %></h4>
<h6 class="text-left"><%= link_to 'Delete', product_path(product), method: :delete,
data: { confirm: 'Are you sure?' } %></h6><br><br>
</div>
<div class="col-md-3 col-lg-3 col-sm-3 col-xs-3 binder">
<%= form_for order_item, remote: true do |f| %>
<div class="input-group">
<%= f.number_field :quantity, value: 1, class: "form-control", min: 1 %>
<div class="input-group-btn">
<%= f.hidden_field :product_id, value: product.id %>
<%= f.submit "Add to Cart", class: "btn btn-primary text-right" %>
</div>
</div>
<% end %>
</div>
</div>
</div>
</div>
With <%= image_tag product.image_url.to_s %> the image doesn't appear. When I change it to <%= image_tag product_attachments.first.image_url.to_s %> I get the following error:
undefined local variable or method `product_attachments' for #<#<Class:0x00007f28544ccc68>:0x00007f285dd3aab8>
I am pretty new to Ruby and don't know what I am doing wrong or how to fix this. Any help would be appreciated. I am using Ruby version 2.5.1 and rails 5.2.0 on ubuntu.
I would expect that the following works:
<%= image_tag product.product_attachments.first.image_url.to_s %>
Try this:
image_tag(product.product_attachments.first.image.url.to_s)
It should work. I realized that sometimes image_url doesn't work as expected but image.url does.
If i understand well your snippets, the model you mount the ImageUploader is ProductAttachment (which have the attribute image) so you can remove mount_uploader :image, ImageUploader of your Product model.
The image is mounted on every product_attachments for one product. Just display the images inside the partial by iterating through product_attachments:
<% product.product_attachments.each do |attachment| %>
<%= image_tag(attachment.image.url) %>
<% end %>
Related
Hello guys I searched everywhere on how to output form errors but no luck. I tried almost all the code I found on the internet but still didn't work.
Here are some of my files:
view/books/new.html.erb
<div class="container">
<h2>Create a new book</h2>
<%= form_with model: #book, url: create_new_book_path do |f| %>
<% if #book.errors.any? %>
<ul>
<% #book.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<div class="form-group row">
<%= label_tag(:title, "Title:", class: "col-sm-2 col-form-label") %>
<div class="col-sm-10">
<%= f.text_field :title, class: "form-control" %>
</div>
</div>
<div class="form-group row">
<%= label_tag(:price, "Price:", class: "col-sm-2 col-form-label") %>
<div class="col-sm-10">
<%= f.text_field :price, class: "form-control" %>
</div>
</div>
<div class="form-group row">
<%= label_tag(:subject_id, "Subject:", class: "col-sm-2 col-form-label") %>
<div class="col-sm-10">
<%= f.collection_select :subject_id, #subjects, :id, :name, class: "form-control" %>
</div>
</div>
<div class="form-group row">
<%= label_tag(:description, "Book description:", class: "col-sm-2 col-form-label") %>
<div class="col-sm-10">
<%= f.text_area :description, class: "form-control" %>
</div>
</div>
<%= submit_tag "Create book", class: "btn btn-success" %>
<%= link_to "Cancel", books_path, class: "btn btn-danger" %>
<% end %>
<br/>
</div>
books_controller.rb
class BooksController < ApplicationController
def index
#books = Book.all
end
def show
#book = Book.find(params[:id])
end
def new
#book = Book.new
#subjects = Subject.all
end
def create
#book = Book.new(book_params)
end
def book_params
params.require(:book).permit(:title, :price, :subject_id, :description)
end
def edit
#book = Book.find(params[:id])
#subjects = Subject.all
end
def update
#book = Book.find(params[:id])
if #book.update_attributes(book_params)
redirect_to action: "index"
else
#subjects = Subject.all
render action: "edit"
end
end
def destroy
Book.find(params[:id]).destroy
redirect_to action: "index"
end
end
routes.rb
get 'books/new', to: 'books#new', as: 'new_book'
post 'books/create', to: 'books#create', as: 'create_new_book'
view/layouts/application.html.erb
<main role="main">
<%= yield %>
</main>
I don't really know what I'm missing to get the errors, grateful for your answers!!
try putting them in a flash like this and render it in your view
def create
#book = Book.new
if #book.update(book_params)
flash[:notice] = 'success'
redirect_to action: 'index'
else
flash[:alert] = #book.errors.full_messages.join(', ')
redirect_to action: 'index'
end
end
and in your view render those flashes like
<% if flash[:notice]%>
<span class='notice'><%= flash[:notice] %></span>
<% end %>
<% if flash[:alert]%>
<span class='alert'><%= flash[:alert] %></span>
<% end %>
I'm trying to create a record in a join table named Interventions. Basically in my application a user can do many interventions on an incident, and an incident can have interventions by many users. I pass the needed strong parameters, but the application gives the following errors when I try to save: "Incident must exist" and "User must exist". I spent hours on this, and can't figure out what is the problem. Can you please help me? I post the relevant code here:
user.rb (model)
has_many :interventions
has_many :incidents, through: :interventions
incident.rb (model)
has_many :interventions
has_many :users, through: :interventions
intervention.rb (model)
belongs_to :incident_priority
belongs_to :intervention_status
interventions_controller.rb
def new
#incident = Incident.find(params[:incident])
#user = User.find(current_user.id)
#intervention = Intervention.new(:user_id => #user, :incident_id => #incident)
#project = #incident.channel.project
#mirth = Mirth.find_by server_id: #incident.mirth_server_id
end
def create
#incident = Incident.find(params[:incident_id])
#user = User.find(params[:user_id])
#intervention = Intervention.create(intervention_params)
#project = #incident.channel.project
#mirth = Mirth.find_by server_id: #incident.mirth_server_id
respond_to do |format|
if #intervention.save
format.html { redirect_to new_intervention_path(#incident), notice: 'Intervention was successfully created.' }
format.json { render :show, status: :created, location: #intervention }
else
format.html { render :new, incident: :incident_id }
format.json { render json: #intervention.errors, status: :unprocessable_entity }
end
end
end
< .... >
def intervention_params
params.require(:intervention).permit(:user_id, :incident_id, :incident_priority_id, :begin_date, :end_date, :description,
:intervention_status_id, :forwarded_to)
end
In my view (interventions_form.html.erb):
<%= form_for(#intervention) do |f| %>
<% if #intervention.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#intervention.errors.count, "error") %> prohibited this intervention from being saved:</h2>
<ul>
<% #intervention.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group form-inline">
<%= hidden_field_tag :user_id, #user.id %>
<%= hidden_field_tag :incident_id, #incident.id %>
<strong>Interveniente:</strong>
<%= #user.first_name %> <%= #user.last_name %>
</div>
<div class="form-group form-inline">
<%= f.label 'Prioridade' %>
<%= f.collection_select :incident_priority_id, IncidentPriority.all, :id, :description, {}, {class: "form-control"} %>
</div>
<div class="form-group form-inline">
<%= f.label 'Data início intervenção' %>
<%= f.datetime_select :begin_date %>
</div>
<div class="form-group form-inline">
<%= f.label 'Data fim intervenção' %>
<%= f.datetime_select :end_date, :include_blank => true %>
</div>
<div class="form-group form-inline">
<%= f.label 'Observações' %>
<%= f.text_area :description %>
</div>
<div class="form-group form-inline">
<%= f.label 'Estado' %>
<%= f.collection_select :intervention_status_id, InterventionStatus.all, :id, :description, {}, {class: "form-control"} %>
</div>
<div class="form-group form-inline">
<%= f.label 'Encaminhado para:' %>
<%= f.text_area :forwarded_to %>
</div>
<div class="actions" align="right">
<%= link_to 'Voltar', incidents_path(:mirth => #mirth, :project => #project), class: "btn btn-info" %>
<%= f.submit "Gravar", class: "btn btn-info" %>
</div>
I run debug and the values in the hidden_field_tags are correctly filled. Also in the controller the #user and #incident are correctly populated, but #intervention has nil in the foreign keys :user_id and :incident_id.
Thanks in advance!
You need to associate the user and the incident with the intervention.
in your model...
class Intervention
belongs_to :user
belongs_to :incident
in your create method...
def create
#incident = Incident.find(params[:incident_id])
#user = User.find(params[:user_id])
#intervention = Intervention.create(intervention_params)
#intervention.incident = #incident
#intervention.user = #user
...
You need to change this:
def create
#incident = Incident.find(params[:incident_id])
#user = User.find(params[:user_id])
# ...
end
For this:
def create
#incident = Incident.find(params[:incident_id])
#user = User.find(params[:user_id])
intervention_params.merge(user_id: #user.id, incident_id: #incident.id)
# ...
end
And your model:
class Intervention
belongs_to :user
belongs_to :incident
i have a problem with my form who contains multiple object
When i go on my page "new" for create new team_member, i have this error :
unknown attribute 'team_member_id' for TeamMembersGame.
models/team_member.rb
class TeamMember < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
has_many :team_members_games
accepts_nested_attributes_for :team_members_games
has_many :team_members_weapons
has_many :team_members_champions
end
models/team_member_game.rb
class TeamMembersGame < ActiveRecord::Base
belongs_to :team_member
end
controllers/admin/team_members_controller.rb
class Admin::TeamMembersController < Admin::DashboardController
def new
#member = TeamMember.new
#member.team_members_games.build
end
def create
#member = TeamMember.new(member_params)
if #member.save
redirect_to edit_admin_team_member_path(#member.id), notice: 'Le membre a bien été creer'
else
render 'new'
end
end
def edit
#member = TeamMember.find(params[:id])
#member_game = #member.team_members_games
##member = TeamMember.joins(:TeamMembersChampion, :TeamMembersWeapon, :TeamMembersGame)
end
def update
#member = TeamMember.find(params[:id])
if #member.update_attributes(member_params)
# Handle a successful update.
redirect_to edit_admin_team_member_path(#member.id), notice: 'Le membre a bien été modifier'
else
render 'edit'
end
end
def destroy
TeamMember.destroy(params[:id])
redirect_to admin_team_members_path, notice: 'Le membre a bien ete supprimer'
end
private
def member_params
params.require(:team_member).permit(:name, :id_steam, :color, :avatar, :avatar_color, :description, :rank_cs, :rank_lol, :role_cs, :role_lol, team_members_games: [ :team_members_id, :name_game])
end
def member_games
params.require(:team_members_games).permit(:team_members_id, :name_game)
end
end
view/admin/new.html.erb
<%= form_for(#member, url: admin_team_members_path, html: { method: :post }, id: 'new_news') do |f| %>
<%= #member.inspect %>
<%= #member_games.inspect %>
<div class="row">
<div class="col s12">
<% #member.errors.full_messages.each do |msg| %>
<%= msg %>
<% end %>
</div>
</div>
<div class="row">
<div class="col s12 m6">
<div class="field input-field">
<%= f.label :name, "Nom" %>
<%= f.text_field :name, autofocus: true, :class => "" %>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<p class="bold">
Jeux :
</p>
</div>
<div class="col s12 m6">
<%= f.fields_for :team_members_games do |team_members_games_form| %>
<div class="field input-field">
<%= team_members_games_form.check_box :name_game, {:class => "filled-in", :id => "team_members_game_name_game"}, true, false %>
<%= team_members_games_form.label :name_game, "game" %>
</div>
<% end %>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="btnlog actions">
<%= button_tag(type: 'submit', class: "btn") do %>
Publier <i class='material-icons right'>send</i>
<% end %>
</div>
</div>
</div>
<% end %>
thanks !
you are permitting team_members_id in your code instead of team_member_id
refactor your code to this:
def member_params
params.require(:team_member).permit(:name, :id_steam, :color, :avatar, :avatar_color, :description, :rank_cs, :rank_lol, :role_cs, :role_lol, team_members_games_attributes: [ :id, :team_member_id, :name_game])
end
Change permitted method name and parameters like this:-
def team_member_params
params.require(:team_member).permit(:name, :id_steam, :color, :avatar, :avatar_color, :description, :rank_cs, :rank_lol, :role_cs, :role_lol, team_members_games: [ :id, :name_game])
end
And use this method while creating team member:-
def create
#member = TeamMember.new(team_member_params)
if #member.save
redirect_to edit_admin_team_member_path(#member.id), notice: 'Le membre a bien été creer'
else
render 'new'
end
end
I have corrige some errors, but i haven't idea for get the id of team_member for the table team_member_games :
def team_member_params
params.require(:team_member).permit(:name, :id_steam, :color, :avatar, :avatar_color, :description, :rank_cs, :rank_lol, :role_cs, :role_lol, team_members_game_attributes: [ :id, :name_game])
end
no one element are add in my table team_members_games
How can we DESC order results according to its :date_value in the quantifieds index?
Results being the nested attribute to quantifieds.
Right now the order is according to where the User added the result in the form, regardless of :date_value.
This has proven more difficult than I would have guessed.
class QuantifiedsController < ApplicationController
before_action :set_quantified, only: [:show, :edit, :update, :destroy]
before_action :logged_in_user, only: [:create, :destroy]
def index
if params[:tag]
#quantifieds = Quantified.tagged_with(params[:tag])
else
#quantifieds = Quantified.joins(:results).all
#averaged_quantifieds = current_user.quantifieds.averaged
#instance_quantifieds = current_user.quantifieds.instance
end
end
def show
end
def new
#quantified = current_user.quantifieds.build
end
def edit
end
def create
#quantified = current_user.quantifieds.build(quantified_params)
if #quantified.save
redirect_to quantifieds_url, notice: 'Quantified was successfully created'
else
#feed_items = []
render 'pages/home'
end
end
def update
if #quantified.update(quantified_params)
redirect_to quantifieds_url, notice: 'Goal was successfully updated'
else
render action: 'edit'
end
end
def destroy
#quantified.destroy
redirect_to quantifieds_url
end
private
def set_quantified
#quantified = Quantified.find(params[:id])
end
def correct_user
#quantified = current_user.quantifieds.find_by(id: params[:id])
redirect_to quantifieds_path, notice: "Not authorized to edit this goal" if #quantified.nil?
end
def quantified_params
params.require(:quantified).permit(:categories, :metric, :result, :date, :tag_list, results_attributes: [:id, :result_value, :date_value, :_destroy])
end
end
class Quantified < ActiveRecord::Base
belongs_to :user
has_many :results #correct
accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true #correct
scope :averaged, -> { where(categories: 'Averaged') }
scope :instance, -> { where(categories: 'Instance') }
validates :categories, :metric, presence: true
acts_as_taggable
CATEGORIES = ['Averaged', 'Instance']
end
class Result < ActiveRecord::Base
belongs_to :user
belongs_to :quantified
end
class CreateQuantifieds < ActiveRecord::Migration
def change
create_table :quantifieds do |t|
t.string :categories
t.string :metric
t.references :user, index: true
t.timestamps null: false
end
add_foreign_key :quantifieds, :users
add_index :quantifieds, [:user_id, :created_at]
end
end
class CreateResults < ActiveRecord::Migration
def change
create_table :results do |t|
t.string :result_value
t.date :date_value
t.integer :quantified_id
t.timestamps null: false
end
end
end
form
<%= javascript_include_tag "quantified.js" %>
<%= simple_form_for(#quantified) do |f| %>
<%= f.error_notification %>
<div class="america">
<form>
<% Quantified::CATEGORIES.each do |c| %>
<%= f.radio_button(:categories, c, :class => "date-format-switcher") %>
<%= label(c, c) %>
<% end %>
<br/>
<br/>
<div class="form-group">
<%= f.text_field :tag_list, quantified: #quantified.tag_list.to_s.titleize, class: 'form-control', placeholder: 'Enter Action' %>
</div>
<div class="form-group">
<%= f.text_field :metric, class: 'form-control', placeholder: 'Enter Metric' %>
</div>
<div id="results">
<%= f.fields_for :results do |result| %>
<%= render 'result_fields', :f => result %>
<% end %>
</div>
<div class="links">
<b><%= link_to_add_association 'Add Result', f, :results %></b>
</div>
<div class="america2">
<%= button_tag(type: 'submit', class: "btn") do %>
<span class="glyphicon glyphicon-plus"></span>
<% end %>
<%= link_to quantifieds_path, class: 'btn' do %>
<span class="glyphicon glyphicon-chevron-left"></span>
<% end %>
<%= link_to #quantified, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn' do %>
<span class="glyphicon glyphicon-trash"></span>
<% end %>
</div>
</form>
</div>
<% end %>
index
<!-- Default bootstrap panel contents -->
<div id="valuations" class="panel panel-default">
<div class="panel-heading"><h4><b>AVERAGE</b></h4></div>
<% #averaged_quantifieds.each do |averaged| %>
<div class="attempt">
<b><%= raw averaged.tag_list.map { |t| link_to t.titleize, tagquantifieds_path(t) }.join(', ') %>
<%= link_to edit_quantified_path(averaged) do %>
(<%= averaged.metric %>)</b>
<% end %>
<ul>
<% averaged.results.each do |result| %>
<li>
<b><%= result.result_value %></b>
<%= result.date_value.strftime("%b %Y") %>
</li>
<% end %>
</ul>
</div>
<% end %>
</div>
<div class="valuations-button">
<%= link_to new_quantified_path, class: 'btn' do %>
<b><span class="glyphicon glyphicon-plus"</span></b>
<% end %>
</div>
<br>
<!-- Default bootstrap panel contents -->
<div id="valuations" class="panel panel-default">
<div class="panel-heading"><h4><b>INSTANCE</b></h4></div>
<% #instance_quantifieds.each do |instance| %>
<div class="attempt">
<b><%= raw instance.tag_list.map { |t| link_to t.titleize, tagquantifieds_path(t) }.join(', ') %>
<%= link_to edit_quantified_path(instance) do %>
(<%= instance.metric %>)</b>
<% end %>
<ul>
<% instance.results.each do |result| %>
<li>
<%= result.date_value.strftime("%b.%d.%y") %>
<%= result.result_value %>
</li>
<% end %>
</ul>
</div>
<% end %>
</div>
<div class="valuations-button">
<%= link_to new_quantified_path, class: 'btn' do %>
<b><span class="glyphicon glyphicon-plus"</span></b>
<% end %>
</div>
Thanks so much for your time!
Got it! Add default_scope { order('date_value DESC') } in result.rb
I'm trying to build a small expense tracking app. Using the nested_form gem to add line items. There is an Expense model which accepts nested attributes. Items belong to expenses and there is a foreign key association. Here's the expense controller:
class ExpensesController < ApplicationController
def new
#expense = Expense.new
#item = #expense.items.build
end
def index
#expenses = Expense.all
##items = Item.where(:expense_id => #expense.id)
end
def show
#expense = Expense.find(params[:id])
#items = Item.where(:expense_id => #expense.id)
end
def create
#expense = Expense.new(expense_params)
respond_to do |format|
if #expense.save
format.html { redirect_to #expense, notice: 'Expense Report Submitted.' }
format.json { render :show, status: :created, location: #expense }
else
format.html { render :new }
format.json { render json: #expense.errors, status: :unprocessable_entity }
end
end
end
def edit
#expense = Expense.find(params[:id])
end
def update
#expense = Expense.find(params[:id])
if #expense.save(expense_params)
flash[:notice] = "Expense Report Updated"
redirect_to #expense
else
render 'edit'
end
end
def destroy
#expense = Expense.find(params[:id])
#expense.destroy
redirect_to 'root'
end
private
def expense_params
params.require(:expense).permit(:department_id, :expense_type_id, :notes, items_attributes: [:id, :description, :amount, :issue_date, :_destroy])
end
end
The form looks like:
<%= nested_form_for (#expense) do |f| %>
<% if #expense.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#expense.errors.count, "error") %> prohibited
this expense from being saved:</h2>
<ul>
<% #expense.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class"row">
<div class="col-md-8">
<div class="form-group">
<%= f.label :department_id %><br>
<%= f.collection_select(:department_id, Department.all, :id, :department_name, prompt: true, class: "dropdown-menu") %>
</div>
<div class="form-group">
<%= f.label :expense_type_id %><br>
<%= f.collection_select(:expense_type_id, ExpenseType.all, :id, :expense_name, prompt: true, class: "form-control") %>
</div>
<%= f.fields_for :items do |i| %>
<div class="form-group">
<%= i.label :description%>
<%= i.text_field :description, class: "form-control" %>
</div>
<div class="form-group">
<%= i.label :amount%>
<%= i.text_field :amount, class: "form-control" %>
</div>
<div class="form-group">
<%= i.label :issue_date%>
<%= i.date_select :issue_date, class: "form-control" %>
</div>
<%= i.link_to_remove "Remove", class: "btn btn-default" %>
<% end %>
<div><p><%= f.link_to_add "Add Expense", :items, class: "btn btn-default" %></p></div>
<div class="form-group">
<%= f.label :notes %>
<%= f.text_area :notes, class: "form-control" %>
</div>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
When I hit submit, the expense and items are saved. I checked with Sqlite browser and the foreign key values are captured for each item.
The index file looks like:
<% #expenses.each do |expense| %>
<tr>
<td><%= expense.item.description %></td>
<td><%= number_to_currency(expense.item.amount) %></td>
<td><%= expense.item.issue_date %></td>
<% end %>
I tried the usual combinations (like expense.item.description) by passing through a block, but they aren't working. I would like to know how to display the expense and the associated items in the show and index pages.
Looking at your new action, in your models you would have
class Expense < ActiveRecord::Base
has_many :items
accepts_nested_attributes_for :items
end
So when you are doing expense.items in your view it gives you an active record relation(since expense has many items), try this:
<% #expenses.each do |expense| %>
<% expense.items.each do |item| %>
<tr>
<td><%= item.description %></td>
<td><%= number_to_currency(item.amount) %></td>
<td><%= item.issue_date %></td>
</tr>
<% end %>
<% end %>