passing multiple id with URL using Rails 3 - ruby

my requirement is passing array of ids with URL and extract them into controller method.Suppose I have the ids like below.
#userid=[1,2,3,4]
I have the link_to tag like below.
<%= link_to "update",users_update_path(:all_id=#userid) %>
In users_controller.rb file i want to access all id which are present in #userid variable.
users_controller.rb:
class UsersController < ApplicationController
def update
end
end
Please help me to resolve this issue.

convert the array into string and pass string to controller like
<% c= #userid.join(‘,’) %>
<%= link_to "update",users_update_path(:ids => c) %>
in controller using split method convert string back to array
class UsersController < ApplicationController
def update
s = params[:ids]
#ids = s.split(/,/)
end
end
in routes.rb
match ‘your_users_update_path/:ids’ => ‘users#update’

You can try this, I hope this will help.
<%= link_to "update",users_update_path(params.merge!(:all_id => [1,2,3,4])) %>
## Output
puts params[:all_id]
[1,2,3,4]

Try this:
<%= link_to "update",users_update_path(:all_id => #userid.to_s) %>
users_controller.rb:
class UsersController < ApplicationController
def update
#user_ids = params[:all_id]
end
end

Related

Using will_paginate with array routing issue

My project is currently configured to only have one view, import.html, that allows the user to upload and view contents of a CSV file (after uploading).
Here is the controller class import method:
class UploadController < ApplicationController
require "CSV"
require 'will_paginate/array'
def import
return if params[:file] == nil
file = params[:file]
#table = []
rowi = 0
CSV.foreach(file.path) do |row|
if rowi == 0 #and headers (for later)
#headers = row
else
#table << row.join("~")
end
rowi = rowi + 1
end
#table = #table.paginate(page: params[:page], :per_page => 20)
session
end
end
Here is the view:
<h1>Upload#import</h1>
<h4>UPLOAD A CSV FILE:</h4>
<%= form_tag({:action => "import"}, multipart: true) do %>
<%= file_field_tag :file %>
<%= submit_tag( "Import" ) %>
<% end %>
<% if #headers and #table %>
<h1>RESULTS</h1>
<table>
<thead>
<tr>
<% #headers.each do |column| %>
<td><%= column %></td>
<% end %>
</tr>
</thead>
<tbody>
<% #table.each do |row| %>
<tr>
<% row.split("~").each do |cell| %>
<td><%= cell %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<%= will_paginate #table, inner_window: 1, outer_window: 0%>
<% end %>
Here are the routes:
Rails.application.routes.draw do
root 'upload#import'
post "/" => "upload#import"
end
When interacting with my table to go to a different page, my routes have no specified instruction for:
GET "/?page=(pagenumber)"
I don't know what to tell it to do in order for the correct page to show.
It just defaults to redirecting to the import_page which clears all the data that has been imported. How should I fix this?
In a nutshell, you'll likely want to use a singular resource for this.
So you'd need the following:
In routes.rb:
resource :uploader, only: [:show, :create]
(N.B. this is a different use case to the more commonly-seen resources plural.)
This will give you the following routes:
POST /upload uploads#create # create the new upload
GET /upload uploads#show # display the one and only upload resource
In your controller:
class UploadController < ApplicationController
require "csv"
require 'will_paginate/array'
def create
return if params[:file] == nil
file = params[:file]
#table = []
rowi = 0
CSV.foreach(file.path) do |row|
if rowi == 0 #and headers (for later)
#headers = row
else
#table << row.join("~")
end
rowi = rowi + 1
end
# save the file to the db
# redirect to upload_path
end
def show
# Find the relevant table
#table = Table.last.paginate(page: params[:page], :per_page => 20)
end
end
Then you'll want to rework the form in your view to use #table, something like:
...
<%= form_for #table, multipart: true) do %>
<%= f.file_field :file %>
<%= f.submit "Import" %>
<% end %>
...
This is a very basic summary of how your project should work. The crux of it is using the correct, separate actions to create and show the table.
You'll likely want to look at using strong params and other Rails conventions.
Finally, if it helps, have a look at a generated Rails controller (i.e. rails generate controller my_example_controller) - this will have the create and show actions pre-built, and you can look to merge your code into something similar.
Hope this helps - give me a shout if you've any questions.

Error trying to call a method on an object that belongs to another object

I have recs, which belong to a list, and lists, which have many recs. I am trying to figure out why I can't call my 'to_do' method below on the recs that belong to a list? This is in the 2nd row of view code. I'm getting the following error:
SQLite3::SQLException: near ")": syntax error: SELECT "recs".* FROM "recs" WHERE "recs"."list_id" = ? AND (done = 'false'))
Rec Model
class Rec < ActiveRecord::Base
belongs_to :list
scope :to_do, lambda {where("done = ?)", 'false')}
end
List model
class List < ActiveRecord::Base
has_many :recs
end
Controller
def index
#recs = Rec.to_do
#lists = List.all
#networks = Network.all
end
View
<% network.lists.eat_lists.each do |list| %>
<% if list.recs.to_do.present? %>
<%= list.name %></br>
<% list.recs.each do |rec| %>
<%= rec.name.split(',').first %>
<%= rec.notes %>
<%= rec.done %>
<%= link_to 'Done', marked_as_done_url(rec), method: :patch %></br>
<%= link_to 'Delete', rec, method: :delete %></br>
<% end %>
<% end %>
<% end %>
change your scope to this scope :to_do, lambda {where("done = ?", false)} or scope :to_do, lambda {where(done:false}, notice i have removed one closing bracket in string

has_many and belongs_ association rails 4

I am while leraning how to use association in rails 4 application
I have a user having many opinions and I want to add user opinion in the book show page
This is how i proceed:
my user.rb
class User < ActiveRecord::Base
has_one :panier
has_many :opinions
end
opinion.rb
class Opinion < ActiveRecord::Base
belongs_to :user
end
views/books/show.html.erb
<h2>Votre opinion nous intéresse:</h2>
<%= form_for([#user, #user.opinions.build]) do |f| %>
<p>
<%= f.label :body, 'votre opinion' %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
opinion_controller.rb
class OpinionsController < ApplicationController
def create
#user = current_user
#opinion= #user.opinion.create(opinion_params)
end
private
def opinion_params
params.require(:opinion).permit(:body)
end
end
and in books_controllers this is my show method:
def show
#user= current_user
#books= Book.all
end
my routes:
get 'books/show' => 'books#show' , as: :books_list
resources :users do
resources :opinions
end
what I got as error:
undefined method `opinions' for nil:NilClass
in this line of code:
Most probably #user.opinions in your form causing this issue. check whether current_user returning object or not.
Also in your create method there is typo(#user.opinion), it should be #user.opinions.
Use accept nested attributes for same.

Search form with two fields not working

I'm making an RoR app that allows users to CRUD guidelines. I also am adding various search functions, including the option to search by two attributes "investor" and "program", which are two text fields in my search form. It's not working. My logic works when searching by one attribute, but not two. This is almost certainly due to me not understanding how to send two text fields as params to a search function, and I can't seem to find enough documentation to find the answer myself.
my model file:
def self.invprogsearch(params[:investor], params[:program])
where(['investor LIKE? && program LIKE?', "%#{investor}%", "%#{program}%"])
end
my index controller
def index
if params[:invprogsearch]
#guidelines = Guideline.invprogsearch(params[:invprogsearch])
else
#guidelines = Guideline.all
end
end
and my search form
<p>Search by Investor and Program</p>
<%= form_tag(guidelines_path, :method => "get", id: "search-form") do %>
<%= text_field(:guideline, :program_code, placeholder: "Enter investor") %>
<%= text_field(:guideline, :investor, placeholder: "Enter program") %>
<%= submit_tag "Search", :name => nil %>
<% end %>
I appreciate the help here, I'm anxious to become more proficient in Ruby/Rails
Try to rework your code like that :
View :
<p>Search by Investor and Program</p>
<%= form_tag(guidelines_path, :method => "get", id: "search-form") do %>
<%= text_field_tag :program_code, nil, placeholder: "Enter investor" %>
<%= text_field_tag :investor, nil, placeholder: "Enter program" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
Model:
def self.invprogsearch(params)
where('investor LIKE ? AND program LIKE ?', "%#{params[:investor]}%", "%#{params[:program_code]}%")
end
Controller :
def index
if params[:program_code].present? && params[:investor].present?
#guidelines = Guideline.invprogsearch(params)
else
#guidelines = Guideline.all
end
end
end
Also, here is a cool screencast about implementing a search feature :
https://www.codeschool.com/screencasts/basecamp-search
Your model should read
def self.invprogsearch(investor, program)
where(['investor LIKE ? && program LIKE ?', "%#{investor}%", "%#{program}%"])
end
params is not set at the time your model definition is being read.
And the controller should say
def index
if params[:invprogsearch]
#guidelines = Guideline.invprogsearch(params[:investor], params[:program_code])
# ^----- Change here
else
#guidelines = Guideline.all
end
end
The basic problem is that the names of the fields in your form need to match up with the named of the fields in params that you pass into your model.
I hope this helps.
Is a good idea to handle scopes for reusage
class Guideline < ActiveRecord::Base
scope :by_program_code, -> (program_code) {
if program_code.present?
where(arel_table[:program_code].match("%#{program_code}%"))
else
current_scope
end
}
scope :by_investor, -> (investor) {
if investor.present?
where(arel_table[:investor].match("%#{investor}%"))
else
current_scope
end
}
scope :by_program_code_and_investor -> (program_code, investor) {
by_program_code(program_code).by_investor(investor)
}
end
And in controller
class GuidelinesController < ApplicationController
before_action :guidelines, only: [:index]
def index; end
protected
def guidelines
if params[:program_code] && params[:investor]
#guidelines ||= Guideline.by_program_code_and_investor(params[:program_code], params[:investor])
end
#guidelines ||= Guideline.all
end
end
If you want a more flexible search
def guidelines
#guidelines = Guideline
#guidelines = #guidelines.by_program_code(params[:program_code]) if params[:program_code]
#guidelines = #guidelines.by_investor(params[:investor]) if params[:investor]
#guidelines = #guidelines.all
end

Not showing created blog entries

I'm fairly new to Rails and learning to create a blog using this tutorial. On step 10, once I define create and show, after creating a new post in browser I don't see any entries on show with id page. All I see is heading and and blank title and post header.
Following is my controller -
class PostController < ApplicationController
def index
end
def new
end
def create
#post = Post.new(params[:posts])
#post.save
redirect_to #post
end
def show
#post = Post.find(params[:id])
end
end
Show view ---
<h1>Show a post</h1>
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<p>
<strong>Text:</strong>
<%= #post.text %>
</p>
Route ---
RailsBlog::Application.routes.draw do
resources :post
root :to => "post#index"
end
Form ---
<%= form_for :post, url: {action: 'create'} do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit 'Submit' %>
</p>
<% end %>
May be this is just a spelling mistake, but since I've recently started learning Rails, I'm unable to resolve this.
Update: I can go to particular id using
http://localhost:3000/post/1
but am only seeing blank page with view headers
The problem is here:
#post = Post.new(params[:posts])
It should be params[:post] - singular, not plural.
Also note that the best practice with form_for is to pass an object instead of symbol:
form_for #post do |f|
Then:
You don't need to specify url
You can reuse the same form for an edit action or create action (if object creation failed due to failing validation)
This however requires to initialize new object in your new action:
def new
#post = Post.new
end
UPDATE:
Also your routes are incorrect. When defining plural resources, you need to use plural form (it's more the convention than requirement, but since you're learning stick with it). So change your routes to:
resources :posts
And rename your controller to PostsController (remember to rename file name as well). restart the server and all should work.
ANOTHER UPDATE:
You also need to rename folder app/views/post to app/view/posts.
AND YET ANOTHER UPDATE:
In rails 4, you are not allowed to mass assign any params which has not been whitelisted using strong parameters. You need to tell rails which fields you allow to be assigned first - this is a security thing. You need to make some changes to your controller:
class PostsController < ApplicationController
...
def create
#post = Post.new(post_params)
...
end
...
private
def post_params
params.require(:post).permit(:title, :text)
end
end
This is the way to tell your controller that you are expecting those attributes from your form and they can be safely assigned.
I had just similar problem on the same tutorial.
The code spelling was correct and clearly accorded to examples in tutorial and BroiSatse's answer above.
The mistake was in order of private method definition.
How it was:
...
private
def post_params
params.require(:post).permit(:title, :text)
end
def show
#post = Post.find(params[:id])
end
...
The working order:
def show
#post = Post.find(params[:id])
end
private
...
Anyway, this topic was rather helpful. Thak you for your answers!

Resources