On Dec 14, 2007 9:20 AM, David King <[EMAIL PROTECTED]> wrote:
>
> > 1. Website root:
> > I didn´t find out how to use a component as the frontpage (e.g.
> > localhost:8000/) rather than the index.html from app/www.
>
> In myapp_app_controller:hook/1. My entire hook/1 looks like this:
>
> hook(A) ->
> %% render /post/index for /
> A1=case yaws_arg:appmoddata(A) of
> Root when (Root =:= "") orelse (Root =:= "/") ->
> yaws_arg:appmoddata(A, "/post/index");
> _ ->
> A
> end,
>
> Ewc = erlyweb:get_initial_ewc({ewc, A1}),
> case Ewc of
> {page,_}=Page ->
> Page;
> _ ->
> {phased, Ewc,
> fun(_Ewc, Data,_PhasedVars) ->
> {ewc, html_container, index, [A1,
> {data, Data}]}
> end}
> end.
I also find it useful at the beginning of the hook function to ensure
that the arg's appmoddata field is always preceded by a forward slash
(i.e. add it if it's not there).
>
> > 2. Structure of components:
> > Having all controllers/views/templates in one directory seemed odd to
> > me. The templates directory inside each component may be odd, too, but
> > having at least one directory per component "feels" better. So I want
> > to know what your usual way is.
>
> That makes for a lot of directories with only three files each. I
> prefer it the way it is, although not being tied to a given directory
> structure would be nice, as it makes the creation of regular OTP
> applications difficult. That's hard to work around since Erlyweb
> insists on doing the compilation itself (which isn't great), so it has
> to know where to find the files, and just isn't flexible about it.
ErlyWeb is actually quite flexible. As long as your "special" files,
i.e. controllers, models and views, are under some subdirectory of
src/components, you can have any subdirectory structure you like. You
can follow the Rails convention of having a subdir for each category
(e.g. src/components/controllers, src/components/views, etc), or a
subdir for each component . I personally dislike this approach because
it makes it harder to copy components between apps. I also find it
annoying to have to navigate a bunch of subdirectories to open a file
(especially in emacs). I like my directory structure flat, but you can
design it however you want.
>
>
> > 3. Template inheritance:
> > Using the html_container_controller.erl/html_container_view.et as the
> > root-template, how do I reuse header, main-content, sidebar and footer
> > from other components? I only found out how to have a static sidebar
> > and I would like that to be dynamic, for example showing blogrolls
> > related to a category or leaving out latest_entries from an entry
> > detail page.
>
> Use the component system. See my example code on the FOREACH thread,
> or here
> <http://forum.trapexit.org/viewtopic.php?t=11291&sid=bd4ecf2f0188639e9da9efc6aa1c12d4
> > (although trapexit loses all of my intentation).
>
> To summarise, you want a controller function like this:
>
> foo(A, Args) ->
> [{ewc,sidebar,[A]},
> {data,whatever_data(Args)}].
>
> and a view function like this:
>
> <%@ foo([Sidebar, TheData]) %>
> <table>
> <tr>
> <td><% Sidebar %></td>
> <td><% TheData %></td>
> </tr>
> </table>
>
> {ewc,sidebar,[A]} will evaluate the function sidebar:index/1 with A as
> its only argument, and pass the rendered version as an iolist to
> my_view:foo/1. To use a function other than index or with more
> arguments, return an {ewc} like this:
>
> {ewc,sidebar,blogroll,[A,OtherArg,Etc]}
>
> Again: when that is returned from a controller function, Erlyweb will
> render it, and pass the rendered version to the view function. {data}
> tuples, like {data,_MyName="Fred"} are passed as iolists with no
> additional rendering.
I do something similar. In hook/1, I do the following
hook(A) ->
... %stuff
{phased, {ewc, A},
fun(Ewc, Data, PhasedVars) -> % PhasedVars are used in the trunk version
{ewc, html_container,
[A, {ewc, main_layout, [A, {data, Data}]}]}}.
html_container contains the html headers and footers. main_layout
containers more app specific stuff, such as common navbar, sidebar,
etc. For example
main_layout_controller.erl:
index(A, Ewc) ->
[{ewc, navbar, [A],
{ewc, sidebar, [A],
Ewc].
main_layout_view.et:
<%@ index([NavBar, SideBar, Data]) %>
<table>
<tr>
<td colspan="2"><% NavBar %></td>
</tr>
<tr>
<td><% SideBar %></td>
<td><% Data %></td>
</tr>
</table>
This approach is nice because your app can have multiple different
layouts that share the same html header and footer.
>
>
> > I also have no idea how to set individual titles for each page...I
> > read the " <title>s and other non-component data" topic in this group
> > and the "erlyweb-tutorial-using-components-to-create-dynamic-
> > containers" post on yarivs blog, but that was more confusing than
> > helping, because the former is a discussion of advanced users and both
> > seemed to include future ideas and I am not sure what the status of
> > this is.
>
> Use the {phased_vars} return from controller functions. Let me know if
> you need an example. I'm about to convert some of my own code to it
> anyway, so I might be able to just cut-n-paste
Assuming you're working against trunk, return from your controller
function the following:
{response, [{phased_vars, [{title, <<"my title">>}]},
{body, {data, Data}}]}.
The phased vars will be passed to your phased 'fun' in hook/1, as I've
shown above. From there, you can pass the title into html_container.
>
> > 4. Using controllers and views correctly:
> > The only reference I found was this tutorial:
> > http://progexpr.blogspot.com/2006/12/erlyweb-blog-tutorial.html
> > Thats why I complained about the musician example earlier, it doesnt
> > explain much.
>
> See the aforementioned FOREACH thread, I have a pretty thorough
> example there
>
> > If you have a look at my entry_details template
> > http://erlyweblog.googlecode.com/svn/trunk/src/components/entries/templates/entries_detail.et
> > you´ll see, that I do most of the logic in there rather than in the
> > controller. I guess if I wouldn´t be lacking of Erlang knowledge, this
> > may not be a problem, but I simply don´t know how to.
>
> Use the component system
It's better to avoid calling any functions in the view that trigger
SQL queries. The views should only work with iolists and funs (as I
mentioned in the previous email about ErlTL).
>
> > 5. Naming Sql-tables:
> > I used plurals like categories, entries and so on for table names.
> > After setting up relations I had problems getting related entries for
> > a category doing this:
> > C1 = categories:find_id(1).
> > categories:entries(C1).
> > Instead I have to call categories:entrieses(C1).
> > If you have overlooked it, I mean putting "es" to the end of entries.
> > o_0 How do I get around this or should I just use singular for table
> > names?
>
> I'm not sure, I prefer singular names. Yariv might be able to weigh in
Definitely, use singular names. authors:name(Author) is quite
confusing, not to mention the examples you have.
>
> > 6. Complex queries:
> > How would you retrieve a list of entries with their related category,
> > tags, user and comment count in one query? I mean the full datasets,
> > not only an id or a name. Do you fall back to raw-sql and if so, how
> > do you use that in template context?
>
> Right now, erlyweb does that in multiple queries (post:find,
> post:get_comments, etc). I'm working on a modification to allow hooks
> at record-request-time to make this simpler, so that, for instance,
> requesting a post will automatically request all of its comments (I
> have it working locally by attaching a proplist to the end of the
> tuples used by the records, but it's rather dependant on my data-set;
> when I get the time I'll generalise it unless someone beats me to it).
> But it's not quite so efficient at the moment
Currently, your best choice is to use database views. HOWEVER, if you
feel that you need to use joins, you should probably 1) not worry so
much about using multiple queries to get your data and 2) try to
redesign your schema to be denormalized. You will get speed
improvements by avoiding joins in the database (at the cost of extra
space, which is usually a very good tradeoff), and if you ever feel
the need to distribute your data on multiple machines, avoiding joins
in the DB would make your life much easier. In addition, you shouldn't
worry so much about fetching everything in one query. In Vimagi, for
example, when you load a painting, first the controller fetches the
painting record (which contains a list of tags in one of its fields --
this is denormalized data that exists also in the tags table) and then
it fetches the comments in another query. Trying to do everything in
one query isn't always worth the trouble.
>
> > I guess I have way more questions I can´t remember right now, but I
> > will bother you again, don´t worry. :)
>
> Please do
>
> > If you had the same or similar problems, please drop a line, so that I
> > don´t feel alone with my ignorance.
> > Thanks for taking your time reading this and maybe answering a
> > question.
>
> If you're still writing that tutorial, please note the answers to
> these questions on it. The component system isn't documented very well
> all.
>
>
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"erlyweb" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/erlyweb?hl=en
-~----------~----~----~----~------~----~------~--~---