How to use search on rails, use gem ransack? - search

I have a app about hotel, I have a model Room, RoomType:
room.rb
class Room < ApplicationRecord
enum status: {freeing: true, using: false}
belongs_to :room_type
room_type.rb
class Room < ApplicationRecord
has_many :rooms
I want to search room through roomtype and I did in filter_form:
<%= form_tag admin_rooms_path, method: :get do %>
<div class="form-group">
<%= label_tag t(".room_directory") %>
<%= text_field_tag :number_or_room_types_name_cont,
params[:number_or_room_types_name_cont],
class: "form-control" %>
</div>
or I try to work:
<div class="col-md-3">
<div class="form-group">
<%= label_tag t(".room_type") %>
<%= select_tag :room_types_name_cont, options_for_select(#supports.room_types, params[:room_types_name_cont]),
{include_blank: true, class: "form-control"} %>
</div>
and in room_support.rb:
def room_types
#room_types ||= RoomType.all.map{|room_type| [room_type.name,
room_type.id]}
end
controller I have a search_params:
def search_params
params.permit :number_or_room_types_name_cont,
:status_eq, :max_people_gteq
end
But it not work for me. Hope that everyone helpe me!
Thanks so much.

Related

function Map.put/4 is undefined or private

I just started to learn elixir and phoenix.
I am trying to add comments to blog but i got this error
function Map.put/4 is undefined or private
Error is in this line (show.html.heex):
<%= render "comment_form.html", Map.put(assigns, :changeset, :action, Routes.post_post_path(#conn, :add_comment, #post)) %>
My code in post_controller.ex
def show(conn, %{"id" => id}) do
post =
id
|> Posts.get_post!
|> Repo.preload([:comments])
changeset = Comment.changeset(%Comment{}, %{})
render(conn, "show.html", post: post, changeset: changeset)
end
And comment_form.html.heex
<%= form_for #changeset, #action, fn f -> %>
<div class="form-group">
<label>Name</label>
<%= text_input f, :name, class: "form-control" %>
</div>
<div class="form-group">
<label>Content</label>
<%= textarea f, :content, class: "form-control" %>
</div>
<div class="form-group">
<%= submit "Add comment", class: "btn btn-primary" %>
</div>
<% end %>
You may have accidently added :changeset in the code:
- Map.put(assigns, :changeset, :action, Routes.post_post_path(#conn, :add_comment, #post))
+ Map.put(assigns, :action, Routes.post_post_path(#conn, :add_comment, #post))
Map.put/3 can put a new key-value pair into an existing map. Here 3 means the arity (the number of arguments) is 3.
In your case, it makes little sense to put a new assign of :changeset into the inherited assigns which already contain that key.

Cannot read property 'name' of null error

I'm still a baby on web development. I am getting the following error, can
anyone help me?
Schema:
var campgroundSchema = new mongoose.Schema({
name: String,
image: String,
description: String,
_id: String
});
var Campground = mongoose.model("Campground", campgroundSchema);
app.get("/campgrounds/:id",function(req , res){
Campground.findById(req.params.id, function(err, foundCampgrounds){
if(err){
console.log(err);
}else{
res.render("show", {campground: foundCampgrounds});
}
});
});
This is the index.ejs template:
<div class="row text-center" style="display:flex; flex-wrap:wrap">
<% campgrounds.forEach(function(campground){ %>
<div class="col-md-3 col-sm-6">
<div class="thumbnail">
<img src="<%= campground.image %>">
<div class="caption">
<h4> <%= campground.name %> </h4>
</div>
<p><a href="/campgrounds/ <%= campground._id %>"
class="btn btn-primary">More Info</a>
</p>
</div>
</div>
<% }) %>
</div>
show.ejs:
<%- include('partials/header')%>
<h1>this is a show template</h1>
<p><%= campground.name %></p>
<%- include('partials/footer')%>
TypeError:
Cannot read property 'name' of null
You should check if campground is defined at all - you can either do that in your nodejs-controller or in your template. Here's an example for ejs:
<%- include('partials/header')%>
<% if (campground) { %>
<h1>this is a show template</h1>
<p><%= campground.name %></p>
<% } else { %>
<h1>No camground data was found</h1>
<% } %>
<%- include('partials/footer')%>
On the index.ejs. Use a span to retrieve the _id from the
DB, as follows
<span> <%= campground._id %> </span>
Why? Because _id is a unique object and is auto-generated. No need to even
include it on the Schema unless you want to create it yourself on which case
you'll then amend the controller with a variable. I struggled with this but now
okay.

Rails 5 error message: Child-Model Parent-Model must exist

I have two models, Parent is Property, child is Phone. When attempting to create a new Property record with nested Phone data, I receive an error message: Phones property must exist.
I've studied the Rails Guide and a number of other documents without determining the cause. Here is a public github link if you want to see all the code: https://github.com/allenroulston/testnest.git
class Property < ApplicationRecord
has_many :phones
accepts_nested_attributes_for :phones
end
class Phone < ApplicationRecord
belongs_to :property
end
# the form accepting the data
<%= form_for(property) do |f| %>
<% if property.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(property.errors.count, "error") %> prohibited this property from being saved:</h2>
<ul>
<% property.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :address %>
<%= f.text_field :address %>
</div>
<div class="field">
<%= f.label :city %>
<%= f.text_field :city %>
</div>
<div class="field">
<%= f.label "Telephone (example: 613 555 1234 )" %>
<%= f.fields_for :phones do |p| %>
Area Code <%= p.text_field :area %>
Exchange <%= p.text_field :exchange %>
Number <%= p.text_field :number %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
# relevant controller methods ##################
# GET /properties/new
def new
#property = Property.new
#property.phones.build
end
# POST /properties
# POST /properties.json
def create
#property = Property.new(property_params)
respond_to do |format|
if #property.save
format.html { redirect_to #property, notice: 'Property was successfully created.' }
format.json { render :show, status: :created, location: #property }
else
format.html { render :new }
format.json { render json: #property.errors, status: :unprocessable_entity }
end
end
end
As far as I know, this is because when you use nested_attributes_for when creating a new object, the parent object is not yet created, so when attempting to create a reference to the parent object, the validation fails. To fix this you should change to: has_many :phones, inverse_of: :property.
You need to add in the Property model as :-
accepts_nested_attributes_for :phones, reject_if: :all_blank, allow_destroy: true

Having trouble correctly saving a nested form that has file_field

Using paperclip and ruby-mp3info to upload and read file info, I have a form that creates a playlist and its children, tracks:
<%= form_for(#playlist) do |f| %>
<% if #playlist.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#playlist.errors.count, "error") %> prohibited this playlist from being saved:</h2>
<ul>
<% #playlist.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label "Name: " %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label " Image: " %>
<%= f.file_field :photo %>
</div>
<br>
<div class="field">
<br>
<%= f.text_area :description, :size => "80x3"%>
</div>
<br>
<div class="field">
<%= f.fields_for :tracks, Track.new do |ff| %>
<%= ff.file_field :audio %>
<% end %>
</div>
<% if !#playlist.tracks.blank? %>
<table id="tracks" class="table">
<thead>
<tr>
<th>Track</th>
<th>Album</th>
<th>Artist</th>
<th>Label</th>
</tr>
</thead>
<tbody>
<%= f.fields_for :tracks do |ff| %>
<%= render "track_fields", :f => ff %>
<% end %>
</tbody>
</table>
<% end %>
<div class="actions">
<%= f.submit "Save" %>
</div>
<% end %>
The problem with uploading a file is that I won't have it until I click on the Save button. So I read the info from within my controller. Within the update method of my Playlist controller, I try to create a new track by the following code:
def update
track = #playlist.tracks.new()
Mp3Info.open(playlist_params["tracks_attributes"]["0"]["audio"].path.to_s) do |info|
track.audio_file_name = info.tag.title
track.artist = info.tag.artist
track.album = info.tag.album
# tracknum = info.tag.tracknum.to_s
end
respond_to do |format|
if #playlist.update(playlist_params)
format.html { redirect_to #playlist, notice: 'Playlist was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #playlist.errors, status: :unprocessable_entity }
end
end
end
The problem is that the code in my update method will create TWO instances of tracks when I only want one. How do I create only the instance that I am creating from within my controller and ignore the new track that is being created from within the form?
Are there alternative ways to do this?
You are getting two records in tracks table because one you are creating from form (with track_attributes) and other you are creating in update action.
If you just need to update few properties of the track to be saved then do it on the track coming in params[:playlist][:tracks_attributes].
Change the update action as below:
def update
Mp3Info.open(playlist_params["tracks_attributes"]["0"]["audio"].path.to_s) do |info|
params[:playlist][:tracks_attributes]["0"][:audio_file_name] = info.tag.title
params[:playlist][:tracks_attributes]["0"][:artist] = info.tag.artist
params[:playlist][:tracks_attributes]["0"][:album] = info.tag.album
# tracknum = info.tag.tracknum.to_s
end
respond_to do |format|
if #playlist.update(playlist_params)
format.html { redirect_to #playlist, notice: 'Playlist was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #playlist.errors, status: :unprocessable_entity }
end
end
end
This will create only one associated Track record for a Playlist in tracks table.

Search result displays on wrong page

I am having a bit off difficulty implementing the ransack gem I have a pages controller with an index action and post controller also with an index action. However when I perform a search in the index action of the pages controller (pages#index) the results are rendered in the index action of the post controller(posts#index). Does this mean i can only search from within the views of a particular resource or am I making a mistake ?
pages#index
def index
#q = Post.search(params[:q])
#posts = #q.result(distinct: true)
end
pages#index
<%= search_form_for #q do |f| %>
<div class="field">
<%= f.label :title_cont %><br>
<%= f.text_field :title_cont, :class => "input text" %>
</div>
<div class="actions">
<%= f.submit "Search"%>
</div>
<% end %>
<%= search_form_for #q,:url=>pages_path do |f| %>
<div class="field">
<%= f.label :title_cont %><br>
<%= f.text_field :title_cont, :class => "input text" %>
</div>
<div class="actions">
<%= f.submit "Search"%>
</div>
<% end %>
Modify the code in the search form like this. It will work now.

Resources