How to add the variables of array to database table - mysql

I have a form. Posting array variables from this form in the same name. (Sorry for my bad English.)
Here is the example:
<input type="text" name="name[]" class="form-control">
It is coming like ["a", "b", "c"]
I need save this variables to mysql from array. Not with array. Just one by one.
Create from my post controller
array_length = params[:type].size
for i in 0..array_lenth
type = params[:type][i]
name = params[:name][i]
title = params[:title][i]
value = params[:value][i]
#And save code.
end
I know i can save with some normal sql query but i dont know should i use or how i can use params require permit . something like
def form_params
params.require(:form).permit(:id, :type, :name, :value, :title, :post_id)
end
If i use this, how can i determine the necessary variables. Please help me and sorry for my English :)
Note: I have new post form and i have to add some variables to another table in post form (it is those arrays)

You have to specify that the param is an actual array, something like:
def form_params
params.require(:form).permit(:id, :type, :value, :title, :post_id, name: [:name_of_attribute, :another_name_for_attribute])
end
And then for your form:
<div class="field">
<%= form.text_field "name[name_for_attribute]" %>
</div>
Where the name_for_attribute is the name of the attribute you want it to be, so on the controller you will read the params like:
"form" => {"name"=>{"name_for_attribute"=>"The entered value"}
You can change the name_for_attribute for whatever you want and if for some reason someone tries to add another weird thing into the array by inspecting the HTML, you will filter all the attributes you want anyway.
Hope this helps! Let me know how it goes

Related

How to pass parameters in correct way from view to controller in Ruby on Rails

I've some time working with Rails but I have a problem and don't know how to solve.
There is a model X and a model YW and between them a joint model
I need to pass from view to controller as part of the parameters the X the x_yw_attributes but I don't know how stablish the correct way of the attribute name in html.
The idea will be this:
"x" => {
"name"=>"Name 1", "description"=>"DescripciĆ³n 1", "status"=>"true",
"x_yw_attributes" =>[
{"yw_id"=>"15", "range"=>"[1,2,3,5]", "payment" => "[2,3,4,5,6,7]"},
{"yw_id"=>"17", "range"=>"[1000,2000,3000,5000]", "payment" => "[20,30,40,50,60,70]"},
{"yw_id"=>"19", "range"=>"[10000,20000,30000,50000]", "payment" => "[200,300,400,500,600,700]"}
],
"categories_ids"=>["", "2", "", "5", "5"]
}
I know how to do it with the categories for example:
<input type="checkbox" name="x[category_ids][]" value="2" checked="checked">
<label for="category_2">Category 2</label>
So let me know how should I write the name attribute or I you need more info.
Thaks for the help.
You can check the document with more detail accepts_nested_attributes_for
And from your question I can't tell where do you want to store the information, in YW or the joint table?
If you want to store data in YW, you can set accepts_nested_attributes_for :yw first, and then pass yw_attributes to controller.
The strong parameters would be something like:
def x_params
params.requires(:x).permit(:name, :description, :status, yw_attributes: [:id, :range, :payment, :_destroy])
end
The code you wrote looks like to store information in the join_table. If that's you want to do, add :id into x_yw_attributes to indicate that you want update rather than create them.
You can also check nested_form gem by Ryan B. which he combines some javascript code to make the life easier

How to take value for Object result in ruby on rails

I want to print specific value from object result. here is i am execute SQL query and take all data from View tables, All data coming from "Employee_Information" view(table).
hr_controller.rb
class HrController < ApplicationController
def internal_employee_page
#employees = MysqlConnection.connection.select_all("SELECT * FROM Employee_Information")
end
end
internal_employee_page.html.erb this is my first view
<div id="job_details">
<% #employees.each do |emp| %>
<%= render partial: "hr/employee_details", locals: {emp: emp} %>
<% end %>
</div>
_employee_details.html.erb this is my second view
<h3> User Name : <%= emp%> </h3>
like this I am trying to print all value
then I got following result
I want to print each value
I tried this also in my second view
<h3> User Name : <%= emp.full_name%> </h3>
But I got Error:
Please help me I tried every thing according to my knowledge, where am I wrong and what is problems
Try this:
<h3> User Name : <%= emp["full_name"] %> </h3>
you are trying to read values from Hash,so emp.full_name will not work, you can read value from hash like Hash['key']
so for full_name do <%= emp['full_name'] %>
<h3> User Name : <%= emp.full_name%> </h3>
full_name is not an attribute of employee instance that's why you got this error. try fetch specific attribute which is present in that employee instance.
Right now your response objects are just simple Hash objects and to access the values for keys you would need to use Hash methods such as [] or fetch to retrieve the values. If you would like more method like syntax you could do one of the following:
Use ActiveRecord or another ORM mapper
Create Dynamic or Static classes yourself and map the results to them
Monkey Patch Hash with something like method_missing to fake this concept

page element definition for cloned rows

I am using the page-object-gem and trying find the best way to define my page elements when a set of text_field have an infinite number of occurrences.
The HTML on page load is similar to the following:
<div><input id="dx_1_code" value=""/> <input id="dx_1_dos" onblur="clone($(this),false)" value=""/></div>
If the user tabs out of the last input then a new row is cloned with id values that increment with HTML like follows:
<div><input id="dx_2_code" value=""/> <input id="dx_2_dos" onblur="clone($(this),false)" value=""/></div>
<div><input id="dx_3_code" value=""/> <input id="dx_3_dos" onblur="clone($(this),false)" value=""/></div>
My first try was to define my class as follows:
class SamplePage
include PageObject
include DataMagic
text_field(:dx_1, :id => "dx_1_code")
text_field(:dx_2, :id => "dx_2_code")
text_field(:dos_1, :id => "dx_1_dos")
text_field(:dos_2, :id => "dx_2_dos")
end
However I quickly ended up with a lot of redundant entries.
Is there a better way to handle an unknown number or entries like this in terms of element setups and use of the populate_page_with method?
The elements are indexed, which makes them a good candidate for the indexed properties feature. The indexed_property lets you define locators where a number is substituted in when accessing the element. The page object would look like:
class MyPage
include PageObject
indexed_property(:dx, [
[:text_field, :code, {id: 'dx_%s_code'}],
[:text_field, :dos, {id: 'dx_%s_dos'}],
])
end
The first two rows would then be inputted using:
page = MyPage.new(browser)
page.dx[1].code = 'a'
page.dx[1].dos = 'b'
page.dx[2].code = 'c'
page.dx[2].dos = 'd'
Unfortunately there is no built-in way for the populate_page_with method to work with indexed properties. As with anything, you could hack in something. The populate_page_with method looks for an "element" method as well as a setter method. By adding your own to the page object, the method could be used.
class MyPage
include PageObject
indexed_property(:dx, [
[:text_field, :code, {id: 'dx_%s_code'}],
[:text_field, :dos, {id: 'dx_%s_dos'}],
])
# Method for inputting the various dx code/dos values based on a Hash
def dx=(values)
values.each_pair do |index, fields|
fields.each_pair do |field, value|
dx[index].send("#{field}=", value)
end
end
end
# This is so that populate_page_with can check that the element is enabled/visible
def dx_element
dx[1].code_element
end
end
This would give you the ability to use populate_page_with by sending a Hash where the keys are the index and the values are the fields/values for that index. The same inputting of the page that we did before can now be written as:
page = MyPage.new(browser)
page.populate_page_with(dx: {
1 => {code: 'a', dos: 'b'},
2 => {code: 'c', dos: 'd'}
})

can't create a record in a database

I am using rails version 4.2 and ruby version 2.2.0. I am trying to save a record to lollypops table. No exceptions indicating reasons.
TASK: As soon as a member is created and saved, I want to populate the lollypops table by calling the create_lollypop(#member.id) in members controller's create method like this:
# POST /members
# POST /members.json
def create
#member = Member.create(members_params)
return unless request.post?
#member.save!
self.current_user = #member
c = Country.find(#member.country_id)
#member.update_attributes(
:country_code=>c.code)
create_lollypop(#member.id) #From here I want to create lollypop
MemberMailer.signup_notification(#member).deliver_now
redirect_to(:controller => '/admin/members', :action => 'show',
:id=> #member.id)
flash[:notice] = "Thanks for signing up! Check your email now to
confirm that your email is correct!"
rescue ActiveRecord::RecordInvalid
load_data
render :action => 'new'
end
def create_lollypop(member_id)
#member = Member.find(member_id)
Lollypop.create(
:member_id=>#member.id,
:product_name=>'lollypop',
:product_price=>100,
:email=>#member.email,
:house_flat => #member.house_flat,
:street=>#member.street,
:city_town=>#member.city_town,
:country =>#member.country,
:postcode_index=>#member.postcode_index,
:name=>#member.name)
end
The 'member' is created but the 'lollypops' table is not populated. The associations are:
MEMBER model:
has_one :lollypop, :dependent=>:destroy
LOLLYPOP model
belongs_to :member
If I use generic SQL command then the lollypops table gets populated but I do not want to do that:
def self.create_lollypop(member_id)
member = Member.find(member_id)
ActiveRecord::Base.connection.execute("insert into lollypops (member_id,product_name,product_price,email,house_flat,street,city_town,country,postcode_index,name)
values(#{member.id},'lollypop',#{100},'#{member.email}','#{member.house_flat}','#{member.street}','#{member.city_town}','#{member.country_code}','#{member.postcode_index}','#{member.name}')")
end
Any advice would be welcomed. Thank you.
In your create_lollypop(), You are not defining #member.
def create_lollypop(member_id)
#member = Member.find member_id
Lollypop.create!(
:member_id=>#member.id,
:product_name=>'lollypop',
:product_price=>100,
:email=>#member.email,
:house_flat => #member.house_flat,
:street=>#member.street,
:city_town=>#member.city_town,
:country =>#member.country,
:postcode_index=>#member.postcode_index,
:name=>#member.name
)
end
Also use create! so in case any validation failed then it will raise exception. So it will help you sort out issue.
For the moment try to create lollypop using the association method create_lollypop directly in your controller. use this code in you create controller method, note that create_lollypop method will fill (member_id field automatically):
#member = Member.create(members_params)
return unless request.post?
#member.save!
self.current_user = #member
c = Country.find(#member.country_id)
#member.update_attributes(
:country_code=>c.code)
#From here I want to create lollypop
#member.create_lollypop(
:product_name=>'lollypop',
:product_price=>100,
:email=>#member.email,
:house_flat => #member.house_flat,
:street=>#member.street,
:city_town=>#member.city_town,
:country =>#member.country,
:postcode_index=>#member.postcode_index,
:name=>#member.name
)
MemberMailer.signup_notification(#member).deliver_now
redirect_to(:controller => '/admin/members', :action => 'show',
:id=> #member.id)
flash[:notice] = "Thanks for signing up! Check your email now to
confirm that your email is correct!"
rescue ActiveRecord::RecordInvalid
load_data
render :action => 'new'
This is not exactly an answer, more like tips and notes, it's a little long and I hope you don't mind.
return unless request.post?
This is more of a php thing not a rails thing, in rails already the routing is checking this, so you don't need to do this check inside the controller, if it isn't a post it will be routed elsewhere.
#member = Member.create(members_params)
return unless request.post?
#member.save!
Saving after creating is meaningless, because create already saves the data, if you are doing it for the sake of the bang save!, then you could use the create with bang create!, not to mention that you do the redirection check after the member's create, so if this did work, it would leave you with stray members.
c = Country.find(#member.country_id)
#member.update_attributes(:country_code=>c.code)
If you have your assocciations correctly, you don't need to save the code like this, because the member knows that this country_id belongs to a country.
So add this to the member model
class Member < ActiveRecord::Base
has_one :lollypop, dependent: :destroy
belongs_to :country
end
This way you could always call #member.country to return the country object, then the code could come from there, like #member.country.code, or you could just write a method to shorten that up
def country_code
country.code
end
this way will get the code through an extra query, but it has an advantage, if you for any reason change a country's code, you don't need to loop on all members who have that country and update their codes too, you could also shorten this up even more using #delegate
#member.save!
#member.update_attributes(:country_code=>c.code)
Here you are updating the attributes of member after saving the member, which is kinda a waste, because you are doing 2 queries for what could be done with 1 query, programmatically it is correct and it will work, but it's bad for scaling, when more users start using your app the database will be more busy and the responses will be slower.
Instead i would recommend to postpone the creation of member till you have all the data you want
#member = Member.new(members_params) # this won't save to the database yet
#memeber.code = Country.find(#member.country_id).code
#member.save
This will only do 1 query at the end when all data is ready to be saved.
redirect_to(:controller => '/admin/members', :action => 'show', :id=> #member.id)
This is ok, but you probably have a better shorter path name in your routes, something like members_admin_path, check your routes name by doing a bin/rake routes in your terminal.
redirect_to members_admin_path(id: #member)
redirect_to ...
flash[:notice] = "message"
I'm not sure this will work, because the redirection needs to be returned, but when you added the flash after it, either the redirection will happen without the flash, or the flash will be set and returned as it's the last statement, but the redirection won't happen, not sure which will happen, to fix it you can simply swap the two statements, create the flash first and then redirect, or use the more convenient way of setting the flash while redirecting, cause that's supported
redirect_to ....., notice: 'my message'
rescue ActiveRecord::RecordInvalid
load_data
render :action => 'new'
This will do the job, but it isn't conventional, people tend to use the soft save and then do an if condition on the return value, either true or false, here's a short layout
# prepare #member's data
if #member.save
# set flash and redirect
else
load_data
render :new
end
The lollypop creation
Now there's a few things about this, first you have the method in the controller, which is bad cause it shouldn't be the controller's concern, the second method the self.create_lollypop is better cause it's created on the model level, but it's a class method, then the better way is creating it as a member method, this way the member who creates the lollypop already knows the data because it's his own self, notice i don't need to call #member because i am already inside member, so simple calls like id, email will return the member's data
# inside member.rb
def create_lollypop
Lollypop.create!(
member_id: id,
product_name: 'lollypop',
product_price: 100,
email: email,
house_flat: house_flat,
street: street,
city_town: city_town,
country: country,
postcode_index: postcode_index,
name: name
)
end
if you want you can also add this as an after create callback
after_create :create_lollypop
ps: This method name will probably conflict with the ActiveRecords create_lollypop method, so maybe you should pick a different name for this method.
As Mohammad had suggested to me, I changed Lollypop.create to Lollypop.create! and
while running my code, one validation error popped up. After correcting it and
altering my code to:
Lollypop.create!(
:member_id=> #member.id,
:product_name=>'lollypop',
:product_price=>100,
:email=>#member.email,
:house_flat => #member.house_flat,
:street=>#member.street,
:city_town=>#member.city_town,
:country =>#member.country_code,
:postcode_index=>#member.postcode_index,
:name=>#member.name
)
The 'lollypops' table got populated.

Changing value of Ruby Variable in Html.erb

I have the following code in my controller:
class TestController < ApplicationController
##a = 1
def index
#temp = connection.execute("select test_id from mastertest limit #{##a}, 5;")
end
And I have the following code in my View(Html.erb) File:
<button type="submit" value="Next" form="submit_form">NEXT</button>
<form id="submit_form">
<% ##a = ##a + 1 %>
<table>
<% #temp.each do |row| %>
<tr><td><%= row[0] %></td></tr>
<% end %>
</table>
</form>
So basically I am trying to change the value of the class variable ##a on clicking the Next button. But it does not change the value of ##aa. Can someone help me how to do that.
Did you try using helper method?
module ApplicationHelper
##a = 1
def increment_a
##a = ##a + 1
end
end
and in your view just call;
<% increment_a %>
Not that the ## variable is a class variable and it's shared among all instances of the that class. So define that class somewhere in the ApplicationHelper class and then it will be shared and can be accessed in the Controllers and views.
In all cases I highly discourage using class variables in such a way and recommend that you ind another way to share data/variables between view / controller. Maybe use another supporting class or store values in the database.
If you want to alter a Rails variable on a form submission, you should put the code to do it in the action which processes the form.
As you've written it, I believe the variable will get set when the template containing the form is rendered.
I also vaguely recall that there's some special considerations about class variables in Rails apps. You should look into that and make sure you're using a technique that won't cause any unexpected results.
Ok I managed to fix this:
Ruby has something called a global variable which can be declared like this :
$a = 1
Using $a everywhere retains its value in the controller and the view as well.