I am trying to use faux active record (a model that has no persistence in db).
I followed this example:
https://quickleft.com/blog/using-faux-activerecord-models-in-rails-3/
And I have this error:
ArgumentError in SearchController#new
wrong number of arguments (2 for 1)
app/models/search.rb:32:in assign_attributes'
app/models/search.rb:27:ininitialize'
app/controllers/search_controller.rb:4:in new'
app/controllers/search_controller.rb:4:innew'
It seems that when you call Search.new it needs the parametters but my goal is to make it an empty Search object.
Here are my model, controller, view, route:
Model
class Search
include ActiveModel::MassAssignmentSecurity
TRUE_VALUES = ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES
attr_accessor :query
attr_reader :safe_search, :results_per_page
alias_method :safe_search?, :safe_search
attr_accessible :query, :safe_search, :results_per_page
RESULTS_PER_PAGE = [10, 25, 50, 100].freeze
include ActiveModel::Conversion
include ActiveModel::Validations
validates :query, presence: true
validates :results_per_page, presence: true, inclusion: { in: RESULTS_PER_PAGE }
def persisted?
false
end
def initialize(attributes = {})
assign_attributes(attributes)
yield(self) if block_given?
end
def assign_attributes(values, options = {})
sanitize_for_mass_assignment(values, options[:as]).each do |k, v|
send("#{k}=", v)
end
end
def results_per_page=(value)
#results_per_page = value.to_i
end
def safe_search=(value)
#safe_search = TRUE_VALUES.include?(value)
end
end
Controller
class SearchController < ApplicationController
def new
#search = Search.new
render "search/new.html.erb"
end
def create
#search = Search.new(params[:search])
# TODO: use the #search object to perform a search. Adding
# a `results` method on the search object might be a good starting point.
end
end
View: search/new.html.erb
<%= form_for #search do |f| %>
<%= f.label :query %>
<%= f.text_field :query %>
<%= f.label :safe_search %>
<%= f.check_box :safe_search %>
<%= f.label :results_per_page %>
<%= f.select_box :results_per_page %>
<%= end %>
Here is the solution that I found:
In the model I am using this:
def initialize(attributes = {})
assign_attributes(attributes)
end
def assign_attributes(attributes)
sanitize_for_mass_assignment(attributes).each do |k, v|
send("#{k}=", v)
end
end
Here are my new and create methods in the controller:
def new
#search = Search.new
render "search/new.html.erb"
end
def create
#search = Search.new(params[:search])
respond_to do |format|
format.html { render :template => "search/create.html.erb" }
end
end
By the way i had to rename my controller to SearchesController because controllers must be pluralized.
And here is my new.html.erb view:
<%= form_for #search, url: { action: "create" }, :method => :post do |f| %>
<%= f.label :query %>
<%= f.text_field :query %>
<%= f.label :safe_search %>
<%= f.check_box :safe_search %>
<%= f.label :results_per_page %>
<%= f.select(:results_per_page, [10, 25, 50, 100]) %>
<%= f.submit %>
<% end %>
I hope this will be useful to somebody.
Related
My route :
patch '/projects/:project_id/budgets/:id', to: 'budgets#update', as:'patch_budget' #update
when i send a patch method to this route, :project_id should be my project_id, like:
/projects/test_project/budgets/14
but it turns to budget.id, like:
/projects/14/budgets/14
_form.html.erb
<%= form_with model: budget do |f| %>
<div>
<%= f.label :name, "預算名稱" %><br>
<%= f.text_field :name %>
</div>
<div>
<%= f.label :description, "說明" %><br>
<%= f.text_field :description %>
</div>
<div>
<%= f.label :category, "預算類別" %><br>
<%= f.text_field :category %>
</div>
<div>
<%= f.label :quantity, "數量" %><br>
<%= f.text_field :quantity %>
</div>
<div>
<%= f.label :unit_cost, "單位成本" %><br>
<%= f.text_field :unit_cost %>
</div>
<div>
<%= f.label :issue_id, "議題" %><br>
<%= f.select(:issue_id, Issue.all.collect { |i| [ i.subject, i.id] }) %>
</div>
<div>
<%= f.submit "送出" %>
</div>
<% end %>
edit.html.erb
<h1>編輯預算</h1>
<%= render "form", budget: #budget %>
<br/>
<%= link_to "回預算列表", budgets_path %>
budgets_controller.rb
class BudgetsController < ApplicationController
before_action :find_project, :authorize
def index
#budgets = Budget.all
#sum = Budget.all.sum(:total_cost).round(1)
end
def new
#budgets = Budget.new
end
def create
#budgets = Budget.new(budget_params)
#budgets.project_id = #project.id
#budgets.total_cost = #budgets.quantity * #budgets.unit_cost
#budgets.created_by_id = User.current.id
if #budgets.save
redirect_to budgets_path, notice: "新增預算成功!"
else
render :new
end
end
def edit
#budget = Budget.find(params[:id])
end
def update
#budget = Budget.find(params[:id])
if #budget.update(budget_params)
redirect_to budgets_path, notice: "修改成功!"
else
render :edit
end
end
def destroy
#budget = Budget.find(params[:id])
#budget.destroy if #budget
redirect_to budgets_path, notice: "預算已刪除!"
end
def show
#budget = Budget.find(params[:id])
#create_by = User.find(#budget.created_by_id)
if #budget.modified_by_id != nil
#modified_by = User.find(#budget.modified_by_id)
end
end
private
def find_project
# #project variable must be set before calling the authorize filter
#project = Project.find(params[:project_id])
end
def budget_params
params.require(:budget).permit(:name, :description, :category,
:quantity, :unit_cost, :issue_id)
end
end
Create and delete are running normally, I try many ways in my form, but it didn't work, thanks for the help.
You need to pass an array to generate nested routes:
<%= render "form", budget: #budget, project: #project %>
<%= form_with model: [project, budget] do |f| %>
See https://api.rubyonrails.org/v7.0/classes/ActionDispatch/Routing/PolymorphicRoutes.html
I have created a gallery module with the help of this tutorial https://kolosek.com/carrierwave-upload-multiple-images/ and now I want to add one more image attribute has a master image to the same model. So I thot of creating one more uploader but I'm bit confused about how to call that the controller can anybody help me out?
My code looks like this:
MOdel Code:
class Image < ApplicationRecord
belongs_to :gallery
mount_uploader :image, ImageUploader
mount_uploader :avatar, AvatarUploader
end
class Gallery < ApplicationRecord
has_many :images
accepts_nested_attributes_for :images
end
gallery_controller.rb
class GalleriesController < AdminController
def index
#galleries = Gallery.all
end
def show
#images = #gallery.images.all
end
def new
#gallery = Gallery.new
#image = #gallery.images.build
end
def create
#gallery = Gallery.new(gallery_params)
respond_to do |format|
if #gallery.save
params[:images]['image'].each do |a|
#images = #gallery.images.create!(:image => a, :gallery_id => #gallery.id)
end
format.html { redirect_to #gallery, notice: 'Gallery was successfully created.' }
format.json { render :show, status: :created, location: #gallery }
else
format.html { render :new }
format.json { render json: #gallery.errors, status: :unprocessable_entity }
end
end
end
def gallery_params
params.require(:gallery).permit(:title, :details, :status, images_attributes:[:id, :gallery_id, :image, :avatar])
end
Image Controller code:
class ImagesController < AdminController
def image_params
params.require(:image).permit(:gallery_id, :slideshow_id,:image, :avatar)
end
end
form.html.erb
<%= form.fields_for :images do |p| %>
<div class="field">
<%= form.label :master_image, class: "col-2 col-form-label" %>
<%= form.file_field :avatar, :multiple => true, name: "images[avatar][]" %>
</div>
<% end %>
<%= form.fields_for :images do |p| %>
<div class="field">
<%= form.label :image, class: "col-2 col-form-label" %>
<%= form.file_field :image, :multiple => true, name: "images[image][]" %>
</div>
<% end %>
I am confused in modifing the gallery controller create part.
You can add the images creation 2 times in the create method if you have 2 uploaders
params[:images]['image'].each do |a|
#gallery.images.create!(:image => a, :gallery_id => #gallery.id)
end
params[:images]['avatar'].each do |a|
#gallery.images.create!(:avatar => a, :gallery_id => #gallery.id)
end
but i think it's a little bit verbose and it not really prevents if you don't want to upload any image in your form (return params[:images]['...'] nil)
Btw your form is not correct for the form.fields_for. It's :
<%= form.fields_for :images_attributes do |p| %>
<div class="field">
<%= p.label :master_image, class: "col-2 col-form-label" %>
<%= p.file_field :avatar, :multiple => true, name: "images[avatar][]" %>
</div>
<% end %>
<%= form.fields_for :images_attributes do |p| %>
<div class="field">
<%= p.label :image, class: "col-2 col-form-label" %>
<%= p.file_field :image, :multiple => true, name: "images[image][]" %>
</div>
<% end %>
I have a model where students can enter information about themselves and others can view them. Since there are a lot of profiles, I have added a search section too. If they want only CS majors, they can select from a drop down. I had things like major, college... today I added "level", which is level of education and I get an error (Error shown at the end). I know this is long, but any help would be really really useful. Thanks!
(Userinfo is the student model)
My controller looks like this:
class UserinfosController < ApplicationController
before_action :find_userinfo, only: [:show, :edit, :update, :destroy, :log_impression]
def index
#userinfors = Userinfo.search(params[:search])
#search = Search.new
#college = Userinfo.uniq.pluck(:college)
#major = Userinfo.uniq.pluck(:major)
#level = Userinfo.uniq.pluck(:level)
end
def show
end
def new
#userinformation = current_user.build_userinfo
end
def create
#userinformation = current_user.build_userinfo(userinfo_params)
if #userinformation.save
redirect_to userinfo_path(#userinformation)
else
render 'new'
end
end
def edit
end
def update
if #userinformation.update(userinfo_params)
redirect_to userinfo_path(#userinformation)
else
render 'edit'
end
end
def destroy
#userinformation.destroy
redirect_to root_path
end
private
def userinfo_params
params.require(:userinfo).permit(:name, :email, :college, :gpa, :major, :token, :skills, :level)
end
def find_userinfo
#userinformation = Userinfo.friendly.find(params[:id])
end
end
My information fill out form (please note how the way of input is different in major and level of edu, maybe thats the problem?):
<%= simple_form_for #userinformation, :html => { :multipart => true } do |f| %>
<%= f.input :name, required: true, label: 'Full name' %>
<%= f.input :college, required: true, label: 'Name of college' %>
<%= f.input :gpa, required: true, label: 'Enter GPA' %>
<%= f.input :email, required: true, label: 'Enter email address' %>
<%= f.input :major, required: true, label: 'Major' %>
<%= f.input :level, collection: ["College undergrad", "College grad"], required: true, label: 'Level of education' %>
<%= f.input :skills, required: true, label: 'Skills' %>
<%= f.button :submit, 'Create account' %>
<% end %>
Search controller:
class SearchesController < ApplicationController
def new
#search = Search.new
#college = Userinfo.uniq.pluck(:college)
#major = Userinfo.uniq.pluck(:major)
#level = Userinfo.uniq.pluck(:level)
end
def create
#search = Search.create(search_params)
redirect_to #search
end
def show
#search = Search.find(params[:id])
end
private
def search_params
params.require(:search).permit(:keyword, :college, :min_gpa, :major, :token, :level )
end
end
Search model:
class Search < ActiveRecord::Base
def search_userinfos
userinfos = Userinfo.all
userinfos = userinfos.where(["name LIKE ?","%#{keyword}%"]) if keyword.present?
userinfos = userinfos.where(["college LIKE ?", college]) if college.present?
userinfos = userinfos.where(["cast(gpa as numeric) >= ?", min_gpa]) if min_gpa.present?
userinfos = userinfos.where(["major LIKE ?", major]) if major.present?
userinfos = userinfos.where(["level LIKE ?", level]) if level.present?
userinfos = userinfos.order("gpa")
return userinfos
end
end
This is where the search section is displayed (index view):
<%= simple_form_for #search do |s| %>
<%= s.input :keyword, label: 'Name' %>
<label>College</label>
<%= s.select :college, options_for_select(#college), :include_blank => true %>
<%= s.input :min_gpa, label: "Minimum GPA" %>
<label>Major</label>
<%= s.select :major, options_for_select(#major), :include_blank => true %>
<label>Job type</label>
<%= s.select :level, options_for_select(#level), :include_blank => true %>
<%= s.button :submit, "Search" %>
<% end %>
The error I get when I try to visit the index view:
NoMethodError in Userinfos#index
Showing app-path/index.html.erb where line #25 raised:
undefined method `level' for #<Search:0x000000139d6c38>
Line 25 is:
<%= s.select :level, options_for_select(#level), :include_blank => true %>
Everything works if I remove that line. When I show the education level in the user profile page, it works perfectly.
Schema for searches:
create_table "searches", force: :cascade do |t|
t.string "keyword"
t.string "college"
t.decimal "min_gpa"
t.string "major"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
As you commented, you do not have a level attribute in your Search model.
rails g migration add_level_to_searches level:string
And of course
rails db:migrate
Happy to help!
Here is my form:
<%= simple_form_for #item do |item_builder| %>
<div class="well">
<%= item_builder.input :name %>
<%= item_builder.input :description, as: :text %>
<%= item_builder.input :tag_list %>
<%= item_builder.simple_fields_for :user_items do |user_item_builder| %>
<%= user_item_builder.input :foo, as: :hidden, input_html: { value: "bar" } %>
<%= user_item_builder.simple_fields_for :user_item_images do |user_item_images_builder| %>
<%= user_item_images_builder.input :picture, as: :file,
input_html: { multiple: true,
name: "item[user_items_attributes][user_item_images_attributes][][picture]" } %>
<% end %>
<% end %>
</div>
<div class="clearfix">
<%= item_builder.submit 'Submit new item request'%>
</div>
<% end %>
and my items_controller
def new
#item = Item.new
#user_item = #item.user_items.build
#user_item.user_item_images.build
end
def create
#item = Item.new item_params
#item.user_items.first.user_id = current_user.id
if #item.save
redirect_to items_path, notice: "Thank you for your item request!"
else
render :new
end
end
def item_params
params.require(:item).permit(:name, :description, :tag_list,
user_items_attributes: [:item_id,
user_item_images_attributes: [:user_item_id, :picture]]).merge(created_by: current_user.id, status: Item::STATUS[:pending])
end
I am getting an error no implicit conversion of String into Integer that points to the first line in my create action. item_params is undefined in the webconsole. Any ideas where my error might be?
I'm trying to customize the format when i'm saving to xls :
I want help customizing= "Date" + "ejecutive selected" + ".xls"
My models
class Policy < ActiveRecord::Base
unloadable
belongs_to :ejecutive
has_many :policy
def self.search(search)
if search
find(:all, :conditions => ["ejecutive_id = ? ", search.to_i ] )
else
find(:all)
end
end
end
class Ejecutive < ActiveRecord::Base
has_many :policies
end
Here is my controller.
Here i put my format that i'm trying to customize with date + ejecutive selected + .xls
class PolicyManagement::PolicyController < ApplicationController
def generate_print_ejecutive_comercial
#ejecutives = Ejecutive.find(:all)
#search = Policy.search(params[:search])
#policies = #search.paginate( :page => params[:page], :per_page =>10)
#results= Policy.search(params[:search])
respond_to do |format|
format.html
format.xls { send_data render_to_string(:partial=>"report_by_ejecutive"), :filename => Date + #ejecutives.name"reporte.xls" }
end
end
Here is my view
<% form_tag :controller=>"policy_management/policy",:action =>"generate_print_ejecutive_comercial", :method => 'get' do %>
<%= select_tag "search", options_for_select(#ejecutives.collect {|t| [t.name.to_s+" "+t.lastname1.to_s,t.id]}) %>
<%= submit_tag "Search", :name => nil %>
<% end %>
Results
<% #policies.each do |policy| %>
<p> <%= policy.num_policy%> </p>
<p> <%= policy.ejecutive.name %> </p>
<p> <%= policy.ejecutive.last_name %> </p>
<% end %>
<%= will_paginate #policies %>
<%= link_to "Export", :controller=>"policy_management/policy",:action=>"generate_print_ejecutive_comercial" ,:format=>"xls",:search => params[:search],:page => params[:page] %>
I tried this
respond_to do |format|
format.html
format.xls { send_data render_to_string(:partial=>"report_by_ejecutive"), :filename => Date + #ejecutive.name + ".xls" }
end
You cannot + something to the Date class or a specific date like Date.today. But the following works.
:filename => "#{Date.today}#{#ejecutive.name}.xls"
"#{something}" evaluates something, calls to_s on the result and inserts its into the string.