I'm trying to display a form on the screen. But I keep getting this error when I try to start the server. locations_controller.ex ==
** (CompileError) web/controllers/locations_controller.ex:5: Locations.__struct__/1 is undefined, cannot expand struct Locations. BTW I'm new to elixir so I'm probably doing something really obvious wrong.
Here is my code:
locations.controller.ex
def new(conn, _params) do
changeset = Locations.changeset(%Locations{})
render conn, "new.html", changeset: changeset
end
def create(conn, %{"locations" => %{ "start" => start, "end" => finish }}) do
changeset = %AwesomeLunch.Locations{start: start, end: finish}
Repo.insert(changeset)
redirect conn, to: locations_path(conn, :index)
end
VIEW
<h1>Hey There</h1>
<%= form_for #changeset, locations_path(#conn, :create), fn f -> %>
<label>
Start: <%= text_input f, :start %>
</label>
<label>
End: <%= text_input f, :end %>
</label>
<%= submit "Pick An Awesome Lunch" %>
<% end %>
model
defmodule AwesomeLunch.Locations do
use AwesomeLunch.Web, :model
use Ecto.Schema
import Ecto.Changeset
schema "locations" do
field :start
field :end
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:start, :end])
|> validate_required([:start, :end])
end
end
Like I said I'm getting this error:
locations_controller.ex ==
** (CompileError) web/controllers/locations_controller.ex:5: Locations.__struct__/1 is undefined, cannot expand struct Locations
Modules in Elixir need to be referred to by their full name or an alias of it. You can either change all Locations to AwesomeLunch.Locations, or if you want to use a shorter name, you can call alias in that module:
defmodule AwesomeLunch.LocationsController do
alias AwesomeLunch.Locations
...
end
I am developing an umbrella project and I was getting the same error some times.
If you create a struct declared in App1, and want to use it in App2 you have to add App1 to App2 as dependency. If you don't do this and If App2 loaded before App1 the error occurs.
Example:
{:app1, in_umbrella: true}
I had the same error and for me it worked configuring the controller, this way:
defmodule AwesomeLunch.LocationsController do
use AwesomeLunch.Web, :controller
alias AwesomeLunch.Locations
...
end
Related
I have some questions about: https://www.npmjs.com/package/gulp-exec#usage
gulp.src('./**/**')
.pipe(exec('git checkout <%= file.path %> <%= options.customTemplatingThing %>', options))
.pipe(exec.reporter(reportOptions));
What do <%= => and file.path mean?
Do they come from node ? Could you give another example ?
Thank you
<%= =>
These are lodash.template "interpolate" delimiters. They allow you to insert arbitrary values into strings. You can provide those values in the second argument to exec(). Those values are then available as properties of the options object in the string. Everything from <%= to => is replaced with the value of the options property in between.
Example:
gulp.src('.')
.pipe(exec('cp <%= options.in %> <%= options.out %>', {in:'foo', out:'bar'}));
In the above:
<%= options.in %> is replaced with foo
<%= options.out %> is replaced with bar
So the command that gets executed is cp foo bar.
file.path
The options object is not the only object that is available for interpolation. The command in exec() is executed for each Vinyl file emitted from gulp.src(). Each time the command is executed the file object refers to the particular vinyl file that the command is executed on.
Example:
gulp.src(['foo.txt', 'bar.txt'])
.pipe(exec('rm <%= file.path %>', {}));
This executes two commands, one for each file matched by gulp.src():
rm /path/to/foo.txt
rm /path/to/bar.txt
It's showing the path for the files passing through the stream for the Gulp task, which is from Vinyl. Vinyl will have more information for what else you could use.
For example, you could get the filename by doing this instead
<%= file.relative %>
I am having a surprisingly hard time figuring out how to create a search bar within the app.html.eex template in the Phoenix Framework. Since the area does not change no matter where on the website you are I would prefer it simply just use a HTML get request with the search parameter, so something like this:
<%= button "Search", to: "/search/^search_parameter", method: "get", class: "btn" %>
However I don't know how I can put a variable into the to: string. This code does obviously not work but I imagine something like this:
<div class="search">
<%= text_input :search, :query, placeholder: "Type search query here.." %>
<%= button "Search", to: "/search/^search_query", method: "get", class: "btn" %>
</div>
I pretty much have no clue what the best approach is and I am just trying this out. So any solution is welcome really.
If you want to change the URL of the search form based on user input, you will need to use Javascript. However I think the better approach is to just use a normal form and have your search action accept POST parameters instead.
The route should be
# web/router.ex
post "/search", SearchController, :index
The form should look something like this
# web/templates/layout/app.html.eex
<%= form_for #conn, search_path(#conn, :index), [name: :search], fn f -> %>
<%= text_input f, :query %>
<%= submit "Search" %>
<% end %>
Then you can use the query parameter in the controller
# web/controllers/search_controller.ex
def index(conn, %{"search" => %{"query" => query}}) do
results = # do the actual search using `query`
render conn, "index.html", results: results
end
If you like, you can keep your original route and action in order to support both methods.
I'm trying to embedded mail_form into my home page.
The 'contacts#new' is rendered on 'static_pages#home' so I instantiate #contact in StaticPagesController's home action to avoid the "First argument in form cannot contain nil or be empty" error.
But I now I get wrong number of arguments (0 for 1..2) errors instead.
I see this behaviour since I updated my ruby to 2.2.2.
Do you think this error is caused by new specification on Ruby, or it is just my simple code error?
static_pages_controller
class StaticPagesController < ApplicationController
def home
#contact = Contact.new
end
end
views/static_pages/home.html.erb
<section id="contact">
<%= render template: 'contacts/new' %>
</section>
contacts_controller
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(contact_params)
#contact.request = request
if #contact.deliver
flash.now[:notice] = "Thank you for your message. We will contact you soon!"
else
flash.now[:error] = "Cannot send message."
render 'new'
end
end
private
def contact_params
params.require(:contact).permit(:name, :email, :message)
end
end
views/contacts/new.html.erb
<%= form_for(#contact) do |f| %>
...
<% end %>
Logs
Processing by StaticPagesController#home as HTML
Rendered contacts/new.html.erb (23.5ms)
Rendered static_pages/home.html.erb within layouts/application (238.2ms)
Completed 500 Internal Server Error in 278ms
ArgumentError (wrong number of arguments (0 for 1..2)):
app/views/contacts/new.html.erb:28:in `block in_app_views_contacts_new_html_erb___4238619170782302276_70113984753480'
I update my version of 'byebug' to '4.0.1' and 'Web-console' to '2.1.2', then it shows where was the error. It was actually really stupid ...
Error:
<%= form_for(#contact) do |f| %>
<%= t.email_field ... %>
...
<% end %>
Correct:
<%= form_for(#contact) do |f| %>
<%= f.email_field ... %>
...
<% end %>
I'm trying to figure out how to search multiple models with Ransack. The goal is to have the search form in my shared header. I'm using a combination of their documentation, an old rails-cast, SO questions, and some code a friend shared with me. Right now I think it works, although I'm not sure because I can't get the results to show on my index page.
First, I created a search controller:
class SearchController < ApplicationController
def index
q = params[:q]
#items = Item.search(name_cont: q).result
#booths = Booth.search(name_cont: q).result
#users = User.search(name_cont: q).result
end
end
Next, I put this code in the header partial (views/layouts/_header.html.erb):
<%= form_tag search_path, method: :get do %>
<%= text_field_tag :q, nil %>
<% end %>
I added a route:
get "search" => "search#index"
My index.html.erb for the Search controller is empty and I suspect that is the problem, but I'm not sure what to place there. When I try something like:
<%= #items %>
<%= #users %>
<%= #booths %>
This is the output I get when I execute a search:
#<Item::ActiveRecord_Relation:0x007fee61a1ba10> #<User::ActiveRecord_Relation:0x007fee61a32d28> #<Booth::ActiveRecord_Relation:0x007fee61a20790>
Can someone please guide me on what the solution might be? I'm not sure if it's an index view problem, routing problem, or something else. On all of the tutorials the search field and results are only for one model so I'm a little confused on how to pull this off across multiple models.
Thanks!
The output you are getting is correct. Each of those variables contains an ActiveRecord_Relation object which can be treated like an array. Normally you'd do something like:
<% #items.each do |item| %>
<%= item.name %> # or whatever
<% end %>
<% #users.each do |user| %>
# and so on
Alternatively, you could combine your results #results = #items + #booths + #users and then:
<% #results.each do |result| %>
# display the result
<% end %>
I am trying to implement simple search form for users to look up other users.. I have been looking around the web for quite some time, but lot of the resources seem to be outdated, either for rails 3 or retired gems...
Can anyone pin point me to a recent rails 4 resources for simple search or show me the skeleton code to start? thank you in advance!
https://github.com/jhund/filterrific
scope :search_query, lambda { |query|
return nil if query.blank?
terms = query.to_s.downcase.split(/\s+/)
# replace "*" with "%" for wildcard searches,
# append '%', remove duplicate '%'s
terms = terms.map { |e|
(e.gsub('*', '%') + '%').gsub(/%+/, '%')
}
# configure number of OR conditions for provision
# of interpolation arguments. Adjust this if you
# change the number of OR conditions.
num_or_conds = 2
sql = "(LOWER(foo.first_name) LIKE ? OR LOWER(foo.last_name LIKE ?)"
where(
terms.map { |term| sql }.join(' AND '), *terms.map { |e| [e] * num_or_conds }.flatten
)
}
That would be a simple example of searching a user by either first_name or last_name.
Filterrific is quite good, but can be heavy on the back side when it does the query if you have many records.
For a very simple search on Users username you can do in your view :
<%= form_tag users_path, :method => 'get', :id => 'users_search' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
In your User model you must define a 'search' method :
#users_controller.rb
def self.search(user_name)
if user_name
user_name.downcase!
where('LOWER(name) LIKE ?', "%#{user_name}%")
else
all
end
end
and finally in your controller you can call this method :
def index
#users = User.search(params[:search])
end
The route can be defined as a GET like your default route for the page :
#routes.rb
resources :users