Use form_for to update array attribute of object - arrays

I've been seeing topics dancing around this issue, so maybe I've actually seen the answer and I've just been banging away at it too long that my brain can't recognize it.
In short, I think I need to mark my form data as dirty so that it will update the array field in the Freelancer object, but I seem to be missing something.
Important info: programmingLanguages below is an array field. In my migration I have:
t.text :programmingLanguages, array: true, default: []
So while I'm currently submitting only one string to said array, I want to be able to submit more than one eventually (and perform operations on the data when I need to down the line...)
I have a form:
<%= form_for(#freelancer) do |f| %>
<%= f.label :programmingLanguages, "Programming languages (seperated by commas): "%>
<%= f.text_field :programmingLanguages %>
.
.
.
<%= f.submit "Submit", class: "button"%>
<% end %>
Which submits fine and gives me a list of params I expect:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"long token", "freelancer"=>{"programmingLanguages"=>"Stuff for an array, more stuff for an array"...}
I then use those params to update attributes for my #freelancer object:
def create
#freelancer = Freelancer.find(session[:user_id])
if #freelancer.update_attributes(freelancer_params)
redirect_to #freelancer
else
render root_path
end
end
Because I'm using a multi-step form (hence the find by session), I'm updating the attributes in my create action vs. saving them because the object I'm working with already exists and is saved to the database. The issue is that when I use update_attributes I notice that the SQL commits are ignoring my array fields, such as programmingLanguages above, but does not disregard the other attributes in the params. In other words my integer field totalPrograms updates easily/correctly, but my 4 array fields get lost somewhere between the params and updating the #freelancer object.
Any help much appreciated!
Update:
Here are the strong params:
def freelancer_params
params.require(:freelancer).permit(:programmingLanguages, :totalPrograms...)
end
One more note with this, I guess: I've tried indicating here that :programmingLanguages is an array (a la :programmingLanguages => [] or programmingLanguages: []) and I get syntax errors (syntax error, unexpected ',', expecting =>). Which of course could just mean my syntax is off in setting theses as arrays in my strong params, but if that's the case then I can't find the dumb little error there either.

Related

Pagination on ruby array without sending request to controller

I have a array of arrays in my rails application and it is something like:
#array=[[1, "Mr.X", "developer"], [2, "Mr.Y", "python"]...... [n, "Mr.Z", "ba"]]
I am getting these records on runtime from a different database server by using SQL query not from ActiveRecord. I want to perform pagination on this data and I am using will_paginate/array
#array = #array.paginate(:page => 1, :per_page => 1)
and in my view, I am calling it by:
<%= will_paginate #array%>
It is showing me the data of one record for the first page and links for other pages, however when clicked on next page link, it is giving the error for nil:nil class, as it is again submitting the parameters but this time, the parameters are not appropriate.
I have the final records in #array and I don't want to send the request in backend again and again and I just want to process it on front end only.
Thanks in advance.
Note: I am having different issue, while submitting the form on the post method for first time, my params are
params = <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"EEzvZTAdFAGZ1vOvfeQ/hx7BmDFknC+xHpP4HdhIUncfZDobL1le1vzeanLRdgVFQtKYLGPCgKOfqf5J9+4J2Q==", "check_box_array"=>["ID", "NAME", "ROLE"], "column_value"=>{"ID"=>"", "NAME"=>"", "ROLE"=>""}, "table_name"=>"employee", "column_length"=>"3", "commit"=>"Search", "controller"=>"test", "action"=>"index"}
and here on the controller index action I am running SQL query and fetching data from database not using any model and storing the results into array, which I am passing to view like ` <%= will_paginate #array %>
But while clicking on any page number, it is submitting the parameters as <ActionController::Parameters {"page"=>"2", "controller"=>"test", "action"=>"index"} permitted: false>
and this time, it is not having any query parameters and it is generating the error for nil class
undefined method for nil:NilClass
But I don't want to send the query parameters, I just want to show the data of #array using pagination i.e. on every page just the required data.

Difference in accessing variables in views

I've two controllers one is "Upload" which deals with images uploads and other is "Page" whid deals with the creation of pages of CMS now if in my "Upload" controller I load both the models i.e 'image_m' which deals with image upload and "page_m" which deals with the pages creation I've highlighted the relevant code my problem is if I access the variables in the view
$this->data['images'] = $this->image_m->get(); sent by this I can access in foreach loop as "$images->image_title, $images->image_path" etc
But the variable sent by this line ***$this->data['get_with_images'] = $this->page_m->get_no_parents();*** as $get_with_images->page_name, $get_with_images->page_id etc produces given error
A PHP Error was encountered
Severity: Notice
Message: Trying to get property of non-object
Filename: upload/index.php
Line Number: 20
what is the difference between these two access levels one for $image & other for $get_with_images because I can only access its values as $get_with_images
class Upload extends Admin_Controller {
public function __construct() {
parent::__construct();
***$this->load->model('image_m');
$this->load->model('page_m');***
}
public function index($id = NULL) {
//var_dump($this->data['images'] = $this->image_m->get_with_images());
//$this->data['images'] = $this->image_m->get_with_images();
***$this->data['images'] = $this->image_m->get();***
$this->data['subview'] = 'admin/upload/index';
if ($id) {
$this->data['image'] = $this->image_m->get($id);
count($this->data['image']) || $this->data['errors'][] = 'Page Could not be found';
}
$id == NULL || $this->data['image'] = $this->image_m->get($id);
/*this calls the page_m model function to load all the pages from pages table*/
***$this->data['get_with_images'] = $this->page_m->get_no_parents();***
You are not posting all your code so its hard to tell but is it because you used $this-> in the controller, but you haven't done the same thing in the view?
In this case i would recommend not using $this-> because its not necessary. Also its much better to check for errors etc when you call the model so do something like
if ( ! $data['images'] = $this->image_m->get($id) ) {
// Failure -- show an appropriate view for not getting any images
// am showing $data in case you have other values that are getting passed
$this->load->view( 'sadview', $data ); }
else {
// Success -- show a view to display images
$this->load->view( 'awesomeview', $data ); }
so we are saying if nothing came back - the ! is a negative - then show the failure view. Else $data['images'] came back, and it will be passed to the view. note i have not had to use $this-> for anything and it won't be needed in the view.
Would also suggest using separate methods - have one method to show all images and a separate method like returnimage($id) to show an image based on a specific validated $id.
====== Edit
You can access as many models as you want and pass that data to the View. You have a different issue - the problem is that you are waiting until the View to find out - and then it makes it more difficult to figure out what is wrong.
Look at this page and make sure you understand the differences between query results
http://ellislab.com/codeigniter/user-guide/database/results.html
When you have problems like this the first thing to do is make a simple view, and echo out directly from the model method that is giving you problems. Its probably something very simple but you are having to look through so much code that its difficult to discover.
The next thing is that for every method you write, you need to ask yourself 'what if it doesn't return anything?' and then deal with those conditions as part of your code. Always validate any input coming in to your methods (even links) and always have fallbacks for any method connecting to a database.
On your view do a var_dump($get_with_images) The error being given is that you are trying to use/access $get_with_images as an object but it is not an object.
or better yet on your controller do a
echo '<pre>';
var_dump($this->page_m->get_no_parents());
exit();
maybe your model is not returning anything or is returning something but the data is not an object , maybe an array of object that you still need to loop through in some cases.

How to update a nested collection_check_box

I have a form for a child (categorization) nested within the parent form (project). The categorization attributes are created using a collection_check_boxes helper like so:
<%= f.fields_for :categorizations do |cat| %>
<%= collection_check_boxes :categorization, :category_id, #categories, :id, :display_name %>
<% end %>
In the Projects controller I'm able to successfully create the new records:
def create
#project = Project.new(project_params)
valid_categorizations = params[:categorization][:category_id].reject! { |c| c.empty?}
#project.categorizations.build(valid_categorizations.map{|cat| {category_id: cat}})
...
end
...
def project_params
params.require(:project).permit(:slug, :title, :body, :published, :category_ids => [])
end
Now, when I want to edit the parent Project record the collection_check_boxes does two undesirable things:
It does not pre-populate attributes (like the .include?(attribute) in a traditional check box), and
It repeats the set of check boxes N times depending on how many categorization records exist in the database (e.g., if Project #1 has three Categorization records the entire set of check boxes will display three times in the edit form).
I can't figure out how to fix this, so any help is greatly appreciated!

Rails 4 : basic use of Merit gem with Devise

Using the merit gem, I want to create a Pioneer badge for the first 100 users of my app.
The code in merit.rb
Merit::Badge.create!(
id: 1,
name: 'Pioneer',
description: "Belongs to the 100 first users of the site",
image: '/images/pioneer.png'
)
The code from badges_rules.rb takes in consideration that i'm using devise for authentification. So I followed this how to.
grant_on 'users/registrations#create', badge: 'Pioneer', model_name: 'User' do |user|
user.id < 101
end
It's not creating any badge. It's interesting to notice that this other badge is working very well :
grant_on 'users/registrations#create', badge: 'Inscription', model_name: 'User'
It seems that Devise is messing with the user object. I did override the registration controller, exactly like the Howto said. And when I call this controller in a simple way, like with this "Inscription" badge, everything's ok.
But when I need to put a condition on the user's id, nothing happens.
For information, this is the code from user's show view, where the badges are displayed (this is working).
<% #user.badges.first(5).each do |b| %>
<%= image_tag(b.image) %>
<%= b.name %>
<%end%>
Add model_name: 'User' to your rule. This happens when the controller name is not named after the object (registrations != user).

how pass variables by arrays not db records?

I'm currently building a data generator. First I want to implement is PESEL (kind of personal ID in Poland based on birth date) generator - I want to enter in form a temporary data with start and end birth date interval - I don't want to store it in database (or I should I do it?)
Here is my pesel controller:
def new
#pesel = Array.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #pesel }
end
end
but I've got an "undefined method `model_name' for NilClass:Class" error - is it a good way anyway of solvint this case? I read somewhere that using temporary variables is not with 'The Ruby Way' - if my solution is wrong, please suggest the correct one. (e.g pass this vars through cookies? hash? helper method?)
here is the stacktrace(I think):
Started GET "/pesel" for 127.0.0.1 at 2011-12-05 16:18:20 +0100
Processing by PeselController#new as HTML
Rendered pesel/new.html.erb within layouts/application (1513.9ms)
Completed 500 Internal Server Error in 1793ms
ActionView::Template::Error (undefined method `model_name' for NilClass:Class):
1: <%= simple_form_for #pesel do |f| %>
2: <%= f.input :date_of_birth, :as => :date, :start_year => Date.today.year - 90,
3: :end_year => Date.today.year - 12, :discard_day => true,
4: :order => [:month, :year] %>
app/views/pesel/new.html.erb:1:in `_app_views_pesel_new_html_erb__708648673_90148530'
app/controllers/pesel_controller.rb:7:in `new'
Rendered /home/ofca/.rvm/gems/ruby-1.9.2-p290/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/_trace.erb (5.6ms)
Rendered /home/ofca/.rvm/gems/ruby-1.9.2-p290/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (4.0ms)
Rendered /home/ofca/.rvm/gems/ruby-1.9.2-p290/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/template_error.erb within rescues/layout (17.6ms)
form_for assumes certain properties exist for the object you pass it, such as model_name.
Instead of using form_for #pesel, just use form_tag and the related _tag methods.
Use a Pesel model. Models are not tables, and your model doesn't have to write anything to the database. Just don't inherit from ActiveRecord, but do provide a model_name and any other fields the form_for helper expects.

Resources