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.
Related
So the title might not be the best description of my problem because I don't really know how to sum up the problem. I have a forEach loop for each event in my database and each one is classified as type = to either "trip", "ropes course", or "other". I have a section for each type of event, but I would like a way where if there are no events in the section I can not display the bannertron header and if there are no events in the whole database I can display different HTML. My code also seems very WET and I would love any suggestions on how to DRY up this page.
<% include partials/header %>
<div class="image-text">
<img src="../images/trip-photo.jpg" class="bannertron">
<div class="centered">Upcoming Trips</div>
</div>
<div class="container event">
<% events.forEach(function(event){ %>
<% if(event.type === "trip"){ %>
</br>
<h4><strong><%= event.title %></strong></h4>
<span><%= event.startdate %> - </span>
<span><%= event.enddate %></span>
<h6><strong>Location: </strong><%= event.location %></h6>
<p><%= event.description %></p>
<% if(currentUser && (currentUser.admin === true)){ %>
Edit
<form action="/calendar/<%= event._id %>?_method=DELETE" method="POST">
<button class="btn btn-danger">Delete</button>
</form>
<% } %>
<hr class="event-hr">
<% } %>
<% }); %>
</div>
<div class="image-text">
<img src="../images/climbing-photo.jpg" class="bannertron">
<div class="centered">Upcoming Climbing Days</div>
</div>
<div class="container event">
<% events.forEach(function(event){ %>
<% if(event.type === "ropescourse"){ %>
</br>
<h4><strong><%= event.title %></strong></h4>
<span><%= event.startdate %> - </span>
<span><%= event.enddate %></span>
<h6><strong>Location: </strong><%= event.location %></h6>
<p><%= event.description %></p>
<% if(currentUser && (currentUser.admin === true)){ %>
Edit
<form action="/calendar/<%= event._id %>?_method=DELETE" method="POST">
<button class="btn btn-danger">Delete</button>
</form>
<% } %>
<hr class="event-hr">
<% } %>
<% }); %>
</div>
<div class="image-text">
<img src="../images/other-photo.jpg" class="bannertron">
<div class="centered">Other Events</div>
</div>
<div class="container event">
<% events.forEach(function(event){ %>
<% if(event.type === "other"){ %>
<h4><strong><%= event.title %></strong></h4>
<span><%= event.startdate %> - </span>
<span><%= event.enddate %></span>
<h6><strong>Location: </strong><%= event.location %></h6>
<p><%= event.description %></p>
<% if(currentUser && (currentUser.admin === true)){ %>
Edit
<form action="/calendar/<%= event._id %>?_method=DELETE" method="POST">
<button class="btn btn-danger">Delete</button>
</form>
<% } %>
<hr class="event-hr">
</br>
<% } %>
<% }); %>
</div>
<% include partials/footer %>
Ideally, I would be able to loop through the events, check which type it is, put it in its respective area, and if there are none of a type, display some text like "no events scheduled" and if there are no events in total, display something else.
If this was me, I would split the events up into 3 different arrays in the node file, instead of sorting it all out inside of an ejs file. The Array.prototype.filter command would be useful for this. The nice thing about it is it returns a new array, with only items that return true for the function you pass in. It does not alter the original array, just passes a new one in. You can do something like
var trips = events.filter(function(event){
return event.type == "trip";
});
//do similar for "rope course", and for "other" you could do something like
return event.type != "trip" && event.type != "rope course"
// for the return statement.
You can do a
if(events.length == 0){
// show different html file
} else {
// show the html file with events, passing in the arrays
}
Make sure you pass all the arrays into the ejs file. For each array, you can do a similar
if(trips.length != 0){
// show banner and stuff
}
And do it for all three.
Hope this helps!
I haven't enabled Search on SilverStripe before, but it seems pretty easy. I've followed steps from 2 other projects (although they are 3.5 version projects but not sure that makes a difference or not) that have search enabled as well as the tutorial offered on SilverStripe's site, and for some reason, I'm getting asset folder items (i.e. images) in my search results. It only seems to happen if I click to search and nothing has been entered into the search field.
There should be no asset items returned at any time for search, and if there is no search query, then there should be a message saying nothing was entered or something. I noticed that using the default $SearchForm setup provided by the basic install gives me the desired results, but not for the form I'm using (which does work on 2 other SilverStripe sites--I checked and confirmed).
I'm not sure what I'm missing? I feel like everything is done correctly, and I would like to use the setup I have now to give me more styling ability:
From _config.php:
FulltextSearchable::enable();
From my Header.ss file:
<!-- SEARCH BAR -->
<form class="navbar-form navbar-left nav-right-left search-form" id="SearchForm_SearchForm" action="/home/SearchForm" method="get" enctype="application/x-www-form-urlencoded">
<fieldset style="font-size: 0;">
<div class="field text nolabel search-holder">
<input name="Search" placeholder="Search" class="form-control search-field text nolabel active search-box" />
</div>
<div class="ja-search-box">
<button class="icon search-button smiths-search-btn" type="submit"><i class="glyphicon glyphicon-search pull-right"></i></button>
</div>
</fieldset>
</form>
The Search Results page:
<div class="main" role="main">
<div class="container">
<div class="row">
<div class="col-xs-12">
<div id="Content" class="searchResults">
<h1 class="brand-red">$Title</h1>
<% if $Query %>
<p class="searchQuery">You searched for "{$Query}"</p>
<% end_if %>
<% if $Results %>
<ul id="SearchResults">
<% loop $Results %>
<li>
<h4>
<a href="$Link">
<% if $MenuTitle %>
$MenuTitle
<% else %>
$Title
<% end_if %>
</a>
</h4>
<% if $Content %>
<p>$Content.LimitWordCountXML</p>
<% end_if %>
<a class="readMoreLink" href="$Link" title="Read more about "{$Title}"">Read more about "{$Title}"...</a>
</li>
<% end_loop %>
</ul>
<% else %>
<p>Sorry, your search query did not return any results.</p>
<% end_if %>
<% if $Results.MoreThanOnePage %>
<div id="PageNumbers">
<div class="pagination">
<% if $Results.NotFirstPage %>
<a class="prev" href="$Results.PrevLink" title="View the previous page">←</a>
<% end_if %>
<span>
<% loop $Results.Pages %>
<% if $CurrentBool %>
$PageNum
<% else %>
$PageNum
<% end_if %>
<% end_loop %>
</span>
<% if $Results.NotLastPage %>
<a class="next" href="$Results.NextLink" title="View the next page">→</a>
<% end_if %>
</div>
<p>Page $Results.CurrentPage of $Results.TotalPages</p>
</div>
<% end_if %>
</div>
</div>
</div>
</div>
</div>
By default, the full text search will search array('SiteTree', 'File')
http://api.silverstripe.org/en/3.1/class-FulltextSearchable.html
I would try changing your FulltextSearchable::enable(); line to FulltextSearchable::enable(array('SiteTree'));
I haven't tried this before and am not sure if it will work.
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
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.
I am having form of user.Where user table has username and email address and another table of user profile which has user_id,location etc..
i am using the form below
I have done the vaildation for user email_Addreess uniqueness.if validation happens then i render to the same page.
My problem was if validation happen and render to same page the values in the fields of city,locations value field gets cleared.but values remains in other fields.Pls re me soon
<%= form_for #user_usr, :url => { :action => "provider_submit" } do |f| %>
<%=params.inspect%>
<% #user_usr.build_user_profile_pfl%>
<% if #user_usr.errors.any? %>
<div id="error_explanation">
<ul>
<% #user_usr.errors.each_with_index do |msg, i| %>
<!--for valdiation -->
<li><%= msg[1] %></li>
<% end %>
</ul>
</div>
<% end %>
username<%= f.text_field :username_usr,:id=>"p_name",:name=>"p_name", :class=>"lt textbox_provider",:maxlength => 50,:style=>"outline: none;",:onclick =>"focusChangeBorderColor('p_name');",:onblur=>"blurChangeBorderColor('p_name')",:onchange=>"removeunwantedSpace(this.value)", :tabindex => '1'%>
email<%= f.text_field :email_usr,:id=>"p_email",:name=>"p_email", :class=>"lt textbox_provider",:maxlength => 50,:style=>"outline: none;",:onclick =>"focusChangeBorderColor('p_email');",:onblur=>"blurChangeBorderColor('p_email')",:onchange=>"removeunwantedSpace(this.value)", :tabindex => '2'%>
<%= f.fields_for :user_profile_pfl do |builder| %>
City <%= builder.text_field :city,:id=>"b_name",:name=>"b_name", :class=>"lt textbox_provider",:maxlength => 50,:style=>"outline: none;",:onclick =>"focusChangeBorderColor('b_name');",:onblur=>"blurChangeBorderColor('b_name')",:onchange=>"removeunwantedSpace(this.value)", :tabindex => '2'%>
<%end%>
<p><%= f.submit "Submit" %></p>
<%end%>