I am fairly new to Ruby on Rails and have been stuck with this bug for quite sometime now. I am hoping that someone could give me some useful information to fix this bug. I have a feeling I am overlooking something trivial. Anyhow, I have included below my code that is drawing the Error (that is in the View) and also my code that is in my controller. While I have done my research before posting on here, I may have to put my instance variable in my controller -- however, I am unsure how that process goes and then how to call it from my View. I would appreciate any help! Thanks in advance :)
The error I get:
NameError in Search#indx
'#' is not allowed as an instance variable name
Here is my line of code that is drawing the error in my view (apps/views/search/index.html.erb):
<% #search = instance_variable_get("\##{params[:model].to_s.downcase.pluralize}")%>
Here is my code in my controller (apps/controllers/search_controller.rb):
class SearchController < ApplicationController
def index
#containers = Container.search(params[:q])
#cpus = Cpu.search(params[:q])
#disks = Disk.search(params[:q])
#firmwares = Firmware.search(params[:q])
#hardwares = Hardware.search(params[:q])
#hosts = Host.search(params[:q])
#interfaces = Interface.search(params[:q])
#lans = Lan.search(params[:q])
#licenses = License.search(params[:q])
#rams = Memory.search(params[:q])
#networks = Network.search(params[:q])
#products = Product.search(params[:q])
#roles = Role.search(params[:q])
#sites = Site.search(params[:q])
#vmpools = Vmpool.search(params[:q])
#trackings = Tracking.search(params[:q])
end
end
The problem is that params[:model] is nil, so you're essentially doing instance_variable_get("#").
Take a look at the Rails log and see if the params you think are being received are actually being received.
Edit: The below is not directly related to the problem you're having (the previous two sentences explain why you're having that problem), but rather a suggestion for improving the way your code is organized.
Doing instance_variable_get in a view is a pretty bad code smell. Really, doing instance_variable_get at all is a code smell. There's almost certainly a better way to do what you're trying to do. For example:
def index
query = search_params[:q]
#search_results = {
containers: Container.search(query),
cpus: Cpu.search(query),
disks: Disk.search(query),
# ...
}
model = search_params[:model].to_s.downcase.pluralize # <-- this is also pretty smelly
#search = #search_results[model]
end
private
def search_params
params.require(:q, :model)
end
Then in your view you can just access #search.
Related
I have a create method in Rails where I am trying to create multiple objects in a while loop. For some reason it doesn't seem to be hitting the while loop so no objects are being created. The code is below:
def create
#user = User.find(params[:participant][:user_id])
#activity = Activity.find(params[:activity_id])
weeks = #activity.weeks
i = 1
while i <= weeks do
puts "Test"
participant = Participant.new
participant.user_id = #user.id
participant.activity_id = #activity.id
participant.attended = false
participant.paid = false
participant.week = i
participant.save
i = i+1
end
redirect_to user_activities_path(#user, :id => #activity.id)
end
The form I am using to submit is working fine as I can see from the console, and the redirect_to method at the end is working, so it just seems to be missing the loop. If it helps, the value of weeks is 10. Any help would be greatly appreciated.
If multiple Test have been output, try participant.save!, i think the participant save might fail, like some column not valid, so no objects are being created.
Please check if activity record is get fetched. I think your 3rd statement should be as follow.
#activity = Activity.find(params[:participant][:activity_id])
I am working on a Rails app, and I am attempting to insert attributes from JSONs as database entries. I'm running into a problem, though, and would appreciate some guidance.
I've been able to jam a few things together and come up with something that sort of works...
def create
#report_group = Array.new
#report_group.push({location:"home", comments:"Hello, database!"}, {location:"away", comments:"Goodbye, database!"})
#report_group.each do |x|
#new_report = Report.new(x)
#new_report.user_id = current_user.id
#new_report.save
end
end
private
def report_params(params)
params.permit(:user_id,:location,:comments)
end
This is a good first step - this commits two entries to my database, one for each of the hashes pushed into #report_group, but it is suffering from a problem - the create action does not reference the report_params whitelist.
I have built several Rails apps where entries are submitted one at a time via the standard Rails form helpers, but I have never done it with multiple JSONs like this before. Trying out the syntax I'd use in a typical form helper situation
#new_report = Report.new(report_params(x))
throws the expectable error undefined method permit' for #<Hash:0x007f966b35e270> but I am not sure what else to do here.
EDIT TO SHOW SOLUTION
Big thanks to #oreoluwa for pointing me in the right direction. Here's the solution that I came up with.
def create
#report_group = Array.new
#report_group.push({location:"home", comments:"Hello, database!"}, {location:"away", comments:"Goodbye, database!"})
#report_group.each do |x|
hash = ActionController::Parameters.new(x)
#new_report = Report.new(report_params(hash))
#new_report.user_id = current_user.id
#new_report.save
end
end
private
def report_params(params)
params.permit(:user_id,:location,:comments)
end
You're getting the error because a Hash is not the same as an ActionController::Parameters. In order to use the permit method with your Hash you may need to first convert it to ActionController::Parameters, as such:
hash = {location:"home", comments:"Hello, database!"}
parameter = ActionController::Parameters.new(hash)
parameter.permit(:user_id,:location,:comments)
I don't know if that is what you're looking for, but I thought to point you in the right direction.
I'm using rails 3.2.11 and ruby 1.9.3.
I have a slow page and I know I have many ways to optimize it. Currently I am focused on the method update_attributes.
Here is my code:
def create
#user = current_user
#demo = #user.demos.new
race_ethnicity_response = []
params[:race_ethnicity_response].each do |response, value|
race_ethnicity_response << response if value != '0'
end
params[:demo][:race_ethnicity_response] = race_ethnicity_response.join(', ')[0, 254]
#demo.update_attributes(params[:demo])
end
Or should I use something like build and save or create?
#demo = #user.demos.build
...
#demo.save!
Or
#users.demos.create!(params[demo])
I am curious which is faster. I know if it save 2ms then I should use the one which is more code correct/readable.
On a small operation like this you aren't going to see much of a performance difference. Go for readability + maintainability. The code above does seem a little scattered, particularly the middle block. Here is a straightforward approach although I may be missing something related to the params[:race_ethnicity_response] loop.
#demo = Demo.new(:params)
#demo.race_ethnicity_response = race_ethnicity_response.reject{|i| i == 0 }.join(', ')[0, 254]
current_user.demos << #demo
Need a little help over here :-)
I'm trying to extend the Order class using a decorator, but I get an error back, even when I use the exactly same code from source. For example:
order_decorator.rb (the method is exactly like the source, I'm just using a decorator)
Spree::Order.class_eval do
def update_from_params(params, permitted_params, request_env = {})
success = false
#updating_params = params
run_callbacks :updating_from_params do
attributes = #updating_params[:order] ? #updating_params[:order].permit(permitted_params).delete_if { |k,v| v.nil? } : {}
# Set existing card after setting permitted parameters because
# rails would slice parameters containg ruby objects, apparently
existing_card_id = #updating_params[:order] ? #updating_params[:order][:existing_card] : nil
if existing_card_id.present?
credit_card = CreditCard.find existing_card_id
if credit_card.user_id != self.user_id || credit_card.user_id.blank?
raise Core::GatewayError.new Spree.t(:invalid_credit_card)
end
credit_card.verification_value = params[:cvc_confirm] if params[:cvc_confirm].present?
attributes[:payments_attributes].first[:source] = credit_card
attributes[:payments_attributes].first[:payment_method_id] = credit_card.payment_method_id
attributes[:payments_attributes].first.delete :source_attributes
end
if attributes[:payments_attributes]
attributes[:payments_attributes].first[:request_env] = request_env
end
success = self.update_attributes(attributes)
set_shipments_cost if self.shipments.any?
end
#updating_params = nil
success
end
end
When I run this code, spree never finds #updating_params[:order][:existing_card], even when I select an existing card. Because of that, I can never complete the transaction using a pre-existent card and bogus gateway(gives me empty blanks errors instead).
I tried to bind the method in order_decorator.rb using pry and noticed that the [:existing_card] is actuality at #updating_params' level and not at #updating_params[:order]'s level.
When I delete the decorator, the original code just works fine.
Could somebody explain to me what is wrong with my code?
Thanks,
The method you want to redefine is not really the method of the Order class. It is the method that are mixed by Checkout module within the Order class.
You can see it here: https://github.com/spree/spree/blob/master/core/app/models/spree/order/checkout.rb
Try to do what you want this way:
Create file app/models/spree/order/checkout.rb with code
Spree::Order::Checkout.class_eval do
def self.included(klass)
super
klass.class_eval do
def update_from_params(params, permitted_params, request_env = {})
...
...
...
end
end
end
end
I'm kind of a newbie in some areas of ruby and rails. So I I'm writing a class to read excel depending on the extension and return the row in a each routine. Something like this:
class ExcelRead
(dependencies)
def initialize(path, sheet_n = 0)
type = File.extname(path)
if type == JitExcelRead::XLS
Spreadsheet.client_encoding = 'UTF-8'
book = Spreadsheet.open path
book_sheet = book.worksheet sheet_n
elsif type == JitExcelRead::XLSX
book = Creek::Book.new path
book_sheet = book.sheets[sheet_n]
end
#book = book
#book_sheet = book_sheet
#book_rows = book_sheet.rows
#path = path
#type = type
end
end
So this means that I call on my application
xls = ExcelRead.new(uploaded_file.filename_path)
and everything runs smooth. I have the objects I need at my disposal. My problem now is how to iterate through them. I thought that adding a method to may class like this
def each
binding.pry
end
and calling it normally on my app like so
xls.book_rows.each do |row|
end
would make me enter that code, but not really...
help?
If you added a each method to your ExcelRead class, and you create an instance of this class called xls, then you have to access it using xls.each, not xls.book_rows.each.
Using the former, you are calling the each method from the Enumerator, as book_rows is a collection.
I can only guess that you want a custom way to iterate your book_row, so i think something like this should be what you are trying to achieve:
def iterate
self.book_rows.each do |br|
# do stuff
end
end
And you call it like:
xls.iterate
But this is only a wild guess.